Signing in into my firebase app via REST https://firebase.google.com/docs/reference/rest/auth only returns tokens which expire after 1 hour (3600 seconds, according to the REST response). I don't see any way to change this.
Using firebase JS SDK, the authentication persists "forever", which is what I would like to achieve. However I do not want to include the JS SDK in my app, if there is a way around it (mostly because of its size (~700kb)).
Is there a way to obtain a persistent login from the official firebase REST api?
Using firebase JS SDK, the authentication persists "forever"
This is because the JS SDK automatically takes in charge the action of getting a new user's Firebase ID token when the current one expires, by using the refresh token. See the doc.
So you need to implement this mechanism yourself when you work with the Firebase Auth REST API, by using the endpoint that allows exchanging a refresh token for an ID token.
For that you should use the refresh token you received the last time you logged in, e.g. by using the endpoint that signs in a user with email/password, or the last time you refreshed the ID token (see below).
You'll get a response which contains the new Firebase ID token and refresh token. Next time this new ID token expires, use again the refresh token, and so forth...
Related
Current Setup
I'm using cloud functions and the admin sdk for my backend. The front-end is a combination of React, Firebase Auth (web sdk), and redux firebase for authentication. Currently, I force a token refresh for each request for specific components of my react app and save the token to local storage.
Reasoning
Initially, I thought I could simply listen for the auth state to change in my front-end's index.js and then refresh the token accordingly i.e. firebase.auth().onAuthStateChanged A few processes on my app can take quite a while (i.e. uploading content) and I've noticed the change of auth state doesn't get triggered anytime outside of the initial login or a logout.
For example, the user begins to upload content 1 minute before the token is set to expire. The final API requests following the uploading then fail because they finish after the token has expired. The token doesn't get updated and requests fail to my backend as 403 unauthorized. The solution was to use currentUser.getIdToken(true) upon the first load of each of these components. Therefore ensuring a new token is always available.
Problem
Are there security risks to this approach? If yes, how can I mitigate them or is there a better approach to persist the token? I'm nervous about giving users the ability to indefinitely refresh their tokens.
is there a better approach to persist the token?
You're supposed to use onIdTokenChanged to listen to changes in the user's ID token as it changes over time. It works like onAuthStateChanged, except you get fed ID tokens. It's updated automatically as needed by the client SDK. You can store the latest token for use in your calls without having to fetch one with an API call each time.
Are there security risks to this approach?
Not really. Refreshing an ID token is necessary, and the Auth SDK does it automatically internally anyway.
I am not sure what a proper FCM token handling mechanism would be so I’m writing our process down here just to get some validation or suggestions for improvements:
Fetch FCM token on client Login (Flutter)
Save FCM token on our Database (Using our REST API)
Delete FCM token on Logout (Using our REST API)
Q1: Should we be getting the FCM token more often than just on login? AFAIK, FCM token only changes on app re-installs, clearing cache, etc. Does this also include app-updates from the PlayStore? In that case, should we save the FCM token on every app launch since the user will remain logged in after an app update and hence we wouldn't trigger the save FCM call.
Q2: Did I mention the right way to handle deleting FCM tokens from our DB? We don’t want the user to keep getting notifications once they have logged out.
Q3: An add-on idea is to send the device_id to the server along with the fcm_token so that server deletes all previously saved FCM tokens for that device_id. This is useful to not have useless tokens on the DB from cases where the user uninstalls the app without logging out (which means that the DELETE fcm_token call never went through.)
The FCM token is refreshed under conditions that you don't control, and those conditions have even changed over time. To handle token updates properly, you'll need to implement both initially getting the token and then monitoring for token updates.
Note that FCM tokens are not associated with a user. It is fine if you want to associate them with a user, but it's up to your application code in that case to maintain the association. So that for example includes deleting the token from your database when the user signs out, as you're doing in step 3. 👍
For keeping your token registry clean, you can indeed do this proactively as you intend, or reactively as shown here: https://github.com/firebase/functions-samples/blob/master/fcm-notifications/functions/index.js#L76-L88
Hi Rohan fundamentaly you should use below logic to save tokens on server.
Step1:
as soon as you get token in callback whether new or same try to save it localstorage.
Step2:
Call your REST API to save it to your server. it is upto you if you want to send unique user identifier along with the token.
Step3:
It is obvious you will recieve token callback a lot of time so you can check whether you have similar token in localstorage, it means you have the token on the server so no point calling REST API.
Step 4: Now your app can send events back to server and based on it trigger Push notifications to the users.
Step 5: You can Add/update user token based on uniqye user identifier. In some cases a user can be guest user, so your app should generate guest userId and link it with token.
Stay safe.
I am using Firebase Auth for SMS login and I want to add to new users a custom "countryCode" claim to the token.
After the Android app validate the SMS code, it invoke the account service in my backend to create the new account and
in that step add the custom claim with Firebase Admin SDK.
The app need to do a force refresh token to get the new claim.
I need to know if after adding the "claim" the update is eventually consistent or not.
If it is eventually consistent I can't guarantee that the refreshed token have the new claim.
I'm not entirely sure what you mean by "eventually consistent" in this context, but you can be sure that these two situations are reliable:
After writing the claims successfully using the Firebase Admin SDK, an immediate call to re-read the claims using the SDK will return the same previously written claims.
A client token refresh that happens after a change to custom claims on the backend will result in the client seeing the new claims. You will need to make sure that the client doesn't refresh until the claims are successfully committed, so that there is no race condition. This could involve the backend signaling to the frontend by changing something in Realtime Database or Cloud Firestore to indicate to the listening client that it's time to refresh the claims. You could use a timestamp that indicates the time of the last write of claims for the user, and the client could compare that to the time it last refreshed.
Okay so in my iOS app I log the user into firebase, then get the jwt token. So now I have my server with an api which accepts an idtoken in the header of the GET.
What do I do here? Certainly I wouldn't be validating the JWT againt firebase on every single API call right? I mean its fast, but that adds latency with a second external check, no? How does one simply just decode that guy in C#? I have an Auth0 layer already and that decodes the JWT with my server-stored secret, but that same code doesn't work for the Firebase token.
Could it just be decoded then extract the user details from that, maybe just check expiry and if expiry > X months it's still okay?
In order to verify Firebase ID tokens and JWTs in general, you only make a network call on your server to get the public certs which are usually not updated for several hours. You could cache that and try to verify with an ID token and if it fails, only then, load the new public certs.
And yes, you must verify the ID token on each call especially since Firebase ID tokens expire after typically an hour and need to be refreshed continuously.
For firebase, I'm using custom authentication because our organization uses CAS for single sign on.
Does custom authentication handle refresh jwt tokens automatically or would I need to develop a refresh workflow within my app?
I am not creating custom tokens using a third party library. My token is created via var token = firebase.auth().createCustomToken(uid, additionalClaims) as described on https://firebase.google.com/docs/auth/server/create-custom-tokens. But this page doesn't mention anything about refresh tokens.
My clients are mainly web, and I've found notes that if you use the Android SDK, this refresh happens automatically. But I'm unsure about refresh tokens and web clients for custom authentications.
After you create the custom token using createCustomToken, you pass that token to the web client and call firebase.auth().signInWithCustomToken(token). The promise returned will resolve with a firebase User. The onAuthStateChanged listener will trigger as expected. A firebase Id token will be available. The token will be refreshed every hour and will be handled by the Firebase SDK. Anytime you call a user method or getToken on user, the token will be automatically refreshed if the old one was expired.