Generate Firebase Verify token on the backend side - firebase

We are migrating users to the Firebase and for specific app reasons I need to create a verify token on the backend side.
So the schema is next -
I receive the user email and password from the user. Passing it to
the backend.
Backend generates a verify token, retrieves all the
info from Firebase, and informs the user.
I'm looking for some way to do it with firebase SDK, but I don't see any option.

Related

Firebase - Email / Password provider device authorization endpoint

I'm trying to implement OAuth 2.0 device authorization for a Firebase project that uses the Email / Password provider for sign in.
In a response from a previous question I was able to test device authorization using a Firebase Device Flow project and the Github and Google providers successfully.
For each of these providers there is an endpoint that is used to request a device code:
Google https://oauth2.googleapis.com/device/code
Github https://github.com/login/device/code
Facebook has the following endpoint, which I have successfully tested:
Facebook https://graph.facebook.com/v2.6/device/login
Is there an equivalent device code authorization endpoint for the Email / Password provider?
EDIT: Looking at the firebase auth library I don't see a credential method that takes an access token. This implies perhaps this isn't possible. Perhaps something could be built to use the credentialWithLink method; an email would be sent with device id and the sign in would enable the polling client to receive a response with a link.
I ended up building the infrastructure myself by setting up:
Endpoints: to get a device token, sign in to validate the device code, get a custom user token for a device token
Website: for the user to enter in credentials to send to validate the device code
Client app: to request the device token, show the qr code and poll for the user token and swap the custom token using the firebase auth method signInWithCustomToken
I used firestore to store the device tokens and update them with the uid, expiry timestamp and verification state with each step.

sign in with slack and validate request from firebase backend for the angular app

i have built a webapp using angular material and firebase functions + realtime DB as the backend. I am using slack "Sign in with Slack" API oauth flow. All works well and i am able to generate a accessToken in the backend which i can store against the user in the realtime DB. Once that is done i make a redirect call to my angular app on the dashboard page. Currently i am passing userid in the redirect url which i use to drive user to dashboard and show his data.
This functionally works fine but is a big security issue. As i can directly type the redirect url and boom. I am in the dashboard.
So, how do i solve this? What should i be doing in the url redirect that is secure and validates the response is the the result of a valid request?
I am not familiar with the Slack OAuth SDK but in general, this is true for all OAuth providers. Ideally, at the point where you redirect to your callback URL with the slack authorization code and you exchange the auth code for a Slack access token before returning that access token to the client, you call the Slack API to get the Slack user ID with the access token and then mint a Firebase custom token with that uid. You then return that custom token to the client and signInWithCustomToken. Make sure you are checking the state field (which you set when started the Slack sign in) along with Auth code to verify that the flow started and ended on the same device.

Using firebase Idtoken instead of custom token without compromising security

I have following use cases:
I have cloud functions which are accessible with HTTP endpoint and they use authorization using custom token because the app is only accessible with certain IPs stored in RTDB so I have created one cloud function with will generate a custom token after signing in user using firebase client SDK and then it will create a custom token using admin SDK after checking IPs which are stored in RTDB.
Now with every subsequent call client will send token and functions will serve the request.
I have event listeners bound with the RTDB on a client and use file upload using client SDK which client initialize with firebaseApp.auth().signInWithCustomToken(custom token).
On the function side I use the same sign in the method that also utilizes my firebase SDK and then I serve that request. The problem here is this sign in the method is very slow like it is taking generally more than 1 second only in sign in.
Alternative
Now alternative is I can use id token which can be created using currentUser.getIdToken() on the client side itself and it takes barely few ms to decode that token but I cannot initialize SDK with that token. so I have to use admin SDK but my IP node in RTDB is not accessed by the normal user and can only be accessed with admin SDK, so if I use ADMIN SDK with Control Access with Custom Claims and Security Rules to give admin SDK similar access that the authorized user has then IP node will not be accessible.
Issues with id token
Id token can be refreshed on the client side so once a client has a custom token, It can generate as many tokens it wants and that is not desirable. Apart from that validating IP everytime is not the operation that I wanted to do so with custom token I only use that in generating a custom token and then for a refreshing token but with id token, this would not be possible as the client can generate it with SDK.
Basically, I have to use firebase SDK on the client side which will need custom token(for additional authorization check) to initialize and at the same time I call the clound function from the similar app so what is the best way to implement this use case.

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.

Can I access the registration tokens of all users registered in my Firebase notifications?

Sometimes I want to send a message through Firebase notifications to one unique user, then I want access the token from that user, so I like to know what is the best practice for get that token at any time?
On initial startup of my app, the FCM SDK generates a registration token for the client app instance.
I can get that token, but if I save that token in Firebase realtime database, I think other people can access that data because it is "set persistent mode on" to access offline data.
My questions is:
Is it possible to get tokens of all users without save that in a database?
Can I get these tokens direct from Firebase Authentication? If not, what is the best practice for access these tokens?
I think other people can access that data because it is "set persistent mode on" to access offline data.
Simply save the registration token details to a secure node. Making sure that only you (or even including the user itself) to be the only ones that can access it. Read more on Understand Firebase Realtime Database Rules.
I can get that token, but if I save that token in Firebase realtime database, I think other people can access that data because it is "set persistent mode on" to access offline data.
Users won't be able to get the data they're not allowed to/wasn't designed to have on their device if you choose to restrict them.
Is it possible to get tokens of all users without save that in a database?
There is no API to get all the registration tokens related to your app. As mentioned in the documentation (emphasis mine):
After you've obtained the token, you can send it to your app server and store it using your preferred method. See the Instance ID API reference for full detail on the API.
It's the developer's (you) responsibility to send and store the registration token to a secure location.
Can I get these tokens direct from Firebase Authentication?
I'm not entirely sure what you mean by this. FCM Registration tokens are different from auth tokens. So, no.
If not, what is the best practice for access these tokens?
So long as you store the tokens in a secure location and make sure that you're always using the most recent/valid token, it should be good.

Resources