Im trying to make chat rooms in my web app. That chat rooms will be protected by password. How to securly store that passwords?
I figure out that way:
I know there are firebase security rules that i can change but:
Or is there better way to do that?
I managed to do that by using firebase functions. I created collection that matches rooms with users.
One function for: If password passed in request is correct for room which id was also passed in request, add document to that collection that match this room with passed user id.
And another one: Return data about all rooms which ids are connected with user id.
Code below i help it will help anyone:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const cors = require('cors')({ origin: true });
admin.initializeApp(functions.config().firebase);
exports.passwordCheck = functions.region("europe-central2").https.onRequest((req, res) => {
cors(req, res, () => {
const { uid, password, id } = req.body;
// refs to room with given args
const roomRef = admin.firestore()
.collection('rooms').doc(id)
roomRef.get().then((doc) => {
if (doc.data().password == password) {
// ref to room_members list in requested room
const room_members = admin.firestore().collection('room_members');
const is_member = room_members.where("user_uid", "==", uid).where("room_id", "==", id);
is_member.get().then((docs) => {
if (docs.docs.length == 0) {
room_members.add({
user_uid: uid,
room_id: id,
}).then(() => {
res.status(200).end();
})
}
}).catch(err => {
// user already in members
});
// Success status
}
else {
// wrong password
res.status(400).end();
}
}).catch(err => {
// not found room
res.status(404).end();
});
});
});
/* Example request for that function
curl -X POST https://europe-central2-xxx.cloudfunctions.net/passwordCheck
-H 'Content-Type: application/json'
-d '{"uid": "B2Xidd3Vw1PL9Kyt5ERFXCjniuF3","id":"Sjucgsyuw2723"
"password": "xxxx"}'
*/
exports.rooms = functions.region("europe-central2").https.onRequest((req, res) => {
cors(req, res, () => {
const { uid } = req.body;
// refs to rooms members list objects with given user id
const membersRef = admin.firestore()
.collection('room_members').where("user_uid", "==", uid);
membersRef.get().then((doc) => {
if (doc) {
// get all ids of rooms that user is in
const rooms_ids = doc.docs.map((docx) => { return docx.data().room_id });
// get all datas from that rooms
const roomsrefs = rooms_ids.map(id => admin.firestore().collection("rooms").doc(id));
admin.firestore().getAll(...roomsrefs).then((rooms) => {
res.json(rooms.map(room =>
Object.assign({}, { "id": room.id }, room.data())))
res.status(200).end();
})
}
else {
// not found resurces
res.json([]);
res.status(401).end();
}
}).catch(err => {
//Internal server error
res.status(500).end();
});
})
});
/* Example request for that function
curl -X POST https://europe-central2-xxxx.cloudfunctions.net/rooms
-H 'Content-Type: application/json'
-d '{"uid": "B2Xidd3Vw1PL9Kyt5ERFXCjniuF3"}'
// */
Response time of the functions is like 500ms so im sure that it's not the best solution but it works :)
It's also possible to do with firestore rules but its neccesary to have matching strucure of data.