Reputation: 10551
I have web portal single page login form where on user account I want to redirect users to different URLs, for example. I have enabled email/password in firebase authentication: Now
I mean I want to allow or restrict different domains to different users. one way is to right js code with if-else and reidrect user to a specific domain. But this is not safe as the code exists in JS.
Edit (Dharmaraj Answer): I have received Dharmaraj answer but there is a confusion or a clarification required. Currently I am not allowing publically to register any user for security reason. I am just creating user on firebase console. So only the sign in required. Therefore the code snippet is slightly changed like this (Please correct me if it is secure).
firebase.auth().signInWithEmailAndPassword(username, password)
.then((userCredential) =>
{
var user = userCredential.user;
console.log(userCredential);
console.log(user);
//This code is not working
/*const userDocRef = firebase.firestore().collection("users").doc(userCredential.uid);
const domain = userDocRef.get().data();
//const domain = (await userDocRef.get()).data()
if(domain)
{
console.log(domain + " domain");
}*/
console.log(userCredential.uid + " uid");
console.log(userCredential.user.uid + " uid");
//getting user specic domain! Is this safe
firebase.firestore().collection("users").where('email','==', username).get().then((snapshot) =>{
console.log("user specifc data");
console.log(snapshot);
snapshot.docs.forEach(doc => {
console.log(doc.data());
window.location.href = doc.data(),domain;
break;
});
})
//unsecure way to redirect users to specific page
// window.location = "TrenoxPilot/index.html"; //redirect user to specific path
})
Further, the given security rule is not allowing me to get the records from firestore so i have changed like this but it is not save.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}
Upvotes: 1
Views: 2379
Reputation: 50850
One way is to right JS code with if-else and redirect user to a specific domain. But this is not safe as the code exists in JS.
That sounds like you don't want to hardcode all the domains in your code and allow users to check their domain only. In such cases, you should store user-specific data in a database or you can even use Custom Claims if it's just a single URL. You would have to use a Cloud function to set that claim whenever user sets their domain.
exports.setDomain = functions.https.onCall((data, context) => {
const {domain} = data;
const {uid} = context.auth
return admin
.auth()
.setCustomUserClaims(uid, { domain })
.then(() => {
// The new custom claims will propagate to the user's ID token the
// next time a new one is issued.
return {data: "Domain updated"}
});
});
Now whenever a user signs in, just check for this claim and redirect them.
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(async ({user}) => {
// Signed in
const {claims} = await user.getIdTokenResult()
if (claims.domain) {
console.log("Domain present")
window.location.href = claims.domain
} else {
console.log("Domain is not present")
}
})
Do note that you can also store user's domain in a database like Firestore and read the value from it instead of custom claims. However, I'd prefer using custom claims if it's just a single URL to save some Firestore reads.
If you do not wish to use Cloud function then you can use Firestore (or realtime db). Whenever a user sets their domain, update it in their documents. Then you can read the domain when the user logs in.
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(async ({user}) => {
// Signed in
const userDocRef = firebase.firestore().collection("users").doc(user.uid)
const snap = await userDocRef.get()
if (snap.exists) {
console.log("User Doc present")
const {domain} = snap.data()
if (domain) {
window.location.href = domain
} else {
console.log("Domain not present")
}
} else {
console.log("User doc is not present")
}
})
Make sure your security rules allow users to read their own document only by setting the following rule:
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
Edit:
The code in updated question does not work as intended since you are not handling promises correct here: const domain = userDocRef.get().data();
Try changing the security rules as in my answer above. Users will be able to read and write their own documentation only so I don't think there's any security risk involved.
Upvotes: 2
Reputation: 17903
It's OK to redirect with JS as long as the destination does a server-side check to make sure that user is allowed on the domain. (Similar to how you repeat server-side form validation even if you have client-side form validation.) So the flow would be:
I think you have to handle the Firebase auth redirect response from client-side JS (the access token is returned after a #
to prevent it from reaching the server), but after getting the token, you can just do the redirect from the server.
Some notes:
If the domains are different you will probably run into some problems:
Upvotes: 1