Firebase signInWithCustomToken custom claims not working in emulator only - firebase

I am setting up a firebase authentication system with firebase. As I wanted it to be username and password, I needed to do it myself.
The workflow is this:
Cloud function gets username and password
It get the corresponding email from firestore
It use signInWithEmailAndPassword() to sign in and get the user data
It it createCustomToken() with the user uid and data that I need
It returns the token to the webclient
Webclient use signInWithCustomToken() with the token
The onAuthStateChanged callback gets trigger and setup my data from the user data
This process works great when deploy in firebase.
The problem is that when I want to use it with the firebase emulator, the user variable on step 7 has no data (no email, no displayName, etc are all set to null). I know that custom token are not signed when generated from the emulator, but is there a way to still get the data out of them?
Thanks

Related

Is there a way to log out a specific user using firebase auth go sdk?

background of this question
I'm using firebase auth for user authentication on my app.
I realized that firebase doesn't have a log of user information changes, so I can't answer user questions about it.
So, I'm planning to move the feature of changing user account info (like email, display name, and password) from using the client-side firebase auth library to using server-side firebase auth SDK for the purpose of taking logs of these changes to use for user support. Also, I'd like to make logout a user who changes account info.
I've looked for the appropriate API on the document firebase.google.com/go/v4/auth and found UpdateUser function. The struct UserToUpdate which is a parameter of UpdateUser can set a new email address, new password and new display name, but I can't find to set the parameter to make a user logout.
my question
Is there a way to log out a specific user by firebase auth go SDK?
Firebase Authentication's client-side sign-in is based on ID tokens, which are valid until their built-in expiration (by default: an hour after they are minted). Since no server keeps a list of all the ID tokens it has minted, there is no way to mark a token as invalid on such a list either.
The common approach to revoke access for a user is to:
Revoke the refresh token, so that they can no longer mint new ID tokens with it.
Add the ID token(s) of the user to a self-managed list of revoked ID tokens.
Detect the presence of an ID token in this list from your server-side code and security rules.
Optionally detect the refresh token revocation on the client
Instead of logging the user out, you can also force-refresh their ID token/profile on the client to get the latest information from the server.

Firebase auth customClaims not exists for user created with help of createCustomToken()

I want to store some secret data in user' customClaims. I create a token on server with:
var customToken = createCustomToken(uniqueId, {mySecretData:"VerySecretData"}),
sending it to my app , logging user in with signInWithCustomToken(customToken), and it works fine,
BUT, when i am fetching user later on server by calling admin's getUser(uniqueId) and trying to see its customClaims there is nothing, undefined.
The interesting thing is that i do see this secret data in callable function context' auth property' token object.
Question: why developerClaims are not user' customClaims ?
Reference: https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createcustomtoken
Claims added via createCustomToken() only exist in the Auth token issued by the Firebase Auth. They are not stored anywhere beyond that, and getUser() response will not include them. You should use the setCustomUserClaims() to get the behavior you've indicated.

Where does firebase authentication store the displayName of its users?

I'm using Firebase Authentication as the authenticator for a .NET app.
I'm not using any other part of Firebase (eg. Firestore, Realtime DB) other than the Authentication.
When I log in using the firebase-ui to get a JWT token issued, it returns a "displayName" as part of the AuthResult which is basically the name field when the user first signed up.
I'm only using the Email / Password sign-in method. Where is this data stored? The Users tab on Firebase Authentication console only shows 5 fields - Identifier, Provider, Created, Signed In and User UID.
Is Firebase authentication storing the user fields like this in some sort of hidden place that I can't access unless I log in as the user?
Firebase Authentication stores user profiles in its internal database. Some of the properties are exposed in the Firebase console, but not all of them. You can get all documented properties through the Admin SDK.

Firebase cloud functions security

I'm using firebase cloud functions with the admin sdk in order to perform some operations on the realtime database on behalf of the user.
For example, if the user wants to store a new parameter on the database, it will press a button on its android client which relies on a directly callable function (onCall). This callable function will save the parameter in the right location in the database.
Now, I understand the onCall function receives automatically some info about the user in the context parameter, such as the user id and the token, but I don't know if these parameters are used to control the effective identity of the user.
Since the function is running with the admin sdk in full privilege mode, I want to be sure that the user is who he claims to be. In a scenario in which one user steals the uid of another user, and calls the function with this uid but with its own Auth token, he will be detected?
Does the function check if the user id (uid) is compliant with the Auth token?
If yes, the only thing I have to do is to check if context.auth is different from null?
Just to move from the comments, the context.auth.uid value is validated server side, so you can trust that the user hasn't manipulated the value. (See the code here.) Now, when you use the firestore or realtime db admin API, the function has access to any value in the database, so you do need to ensure the user has access to the value in the DB (i.e. add a where uid='uid').

Keeping emails synchronized between Firebase auth and database

I am using Firebase Web for a SaaS solution. My purpose is to have access to users' email at any time, either for sending notifications or triggering alerts from the backend.
For security reasons, Firebase auth does not allow to list users' email or to fetch emails based on user IDs. As a consequence, I keep a copy of the email into a specific collection in the Firebase database when a user account is created. The copy is made by a Cloud function that is triggered on user creation (following guidelines: https://firebase.google.com/docs/auth/extend-with-functions).
Thanks to the copy available in the Firebase database, I can access users' email. However, my issue is when a user changes his email.
Firebase auth provides the updateEmail function that returns a promise. I use this last to update the email in Firebase auth. Then, when the promise resolves I update the user email in the Firebase database. However, this has a major drawback: all the logic is performed on the client side and since both operations are not performed in a transaction if the client refreshes or closes his browser (or assume it crashes), then it is possible that Firebase auth is updated but not the Firebase database, thus leading to an inconsistent state.
I looked at the documentation, expecting the possibility to trigger a Cloud function when user auth information is updated. Unfortunately, I cannot find such a feature.
Another solution I thought about is to update the database from the Web client. Then, this last triggers a Cloud function that updates Firebase auth with the admin SDK. This last solution works but bypasses the check performed by updateEmail that ensures the new email is not used by another account. Also, the account hijacking protection performed by updateEmail is evicted, which is really bad from a security point of view.
Any idea to solve this problem properly is welcome.
Here are a couple of options:
When calling updateEmail, update the email in your database first before calling updateEmail. THowever, if an error occurs, you need to catch it and undo that change in your db.
When a user wants to updateEmail, send their id token and new email to your server or firebase function http endpoint. There you verify the ID token with the admin SDK, then use the client SDK require('firebase'), using the uid from the ID token, admin.auth().createCustomToken(uid), then using client SDK, firebase.auth().signInWithCustomToken(customToken). You can then call user.updateEmail(newEmail) on the backend and save the email.
Always save the uid only and just use Admin SDK admin.auth().getUser(uid) to look up the user and get their email. This guarantees you get the user's latest email as you will not be able to catch the email revocation if the user chooses to do so.
No need to save anything. Use the CLI SDK to download all your users and their emails. Check https://firebase.google.com/docs/cli/auth#authexport
This is also better as you will always be able to get the latest email per user even if they revoke the email change.

Resources