I am attempting to use firebase on my server for authentication and to provide an authentication experience for users that does not require pulling in firebase client side (for the moment).
A /login endpoint receives a username and password. Using firebase.auth().signInWithEmailAndPassword, I am then returning the JWT token to the user. They can then use that in subsequent requests to my RESTful API as the bearer token.
The problem I'm struggling with is when that token expires (after an hour). Part of my flow when a request comes in that requires auth validation is verifying the token with admin.auth().verifyIdToken, and rejecting the request if it's no longer valid.
Is it correct to:
(1) provide the client with the refresh token as well in the initial sign-in so they can handle the rejection and then request a new JWT token?
(2) perform some action on the admin SDK to refresh the token on the user's behalf
In typical oauth scenarios I've worked with before, the client has always been responsible for refreshing the token, however I can't for the life of me figure out how to retrieve a new JWT token from that refresh token using either the admin SDK or the firebase SDK
I don't know if the firebase SDK that usually resides client side is handling this token refresh behind the scenes whenever it is used with firebase.database, etc. If i'm not using that client SDK, but instead using the token as a bearer token, can I have the client pass the refresh token for exchange of a new JWT token from the backend?
It's likely staring me right in the face, I'm just not seeing it.
The Firebase Authentication SDKs keep the refresh token in the client-side code, together with the ID token, and then use the former to mint a new ID token when needed (about 5 minutes before the current one expires).
Related
I am using Firebase authentication to authenticate users. Whenever, the user is logged in, I get the user's ID token with user.getIdToken(true) and set it on the local storage. With that token in the authorization header, I am requesting my back-end API.
On the back-end side, I am using Firebase admin SDK to authenticate the request and the user with the client-side ID token passed in the request authorization header.
This works for a while. But after some time I get error:
ExpiredIdTokenError: Token expired, 1620908095 < 1620915515
I saw that Firebase refreshes the ID token on its own. But I don't think that's the case. I have looked through the developer tools network tab, and there's also an observer method to check whenever the token has changed => onIdTokenChanged(), but the token is never refreshed.
I couldn't find any information on the Firebase docs either, and I was hoping if you could help me:
How can I generate a token without expiration limit to last until signed out or at least for some more time (1 week maybe)?
If I cannot the set the expiry limit of the token, what steps should I take so that I can send a valid unexpired token when I am request data from my back-end? Do I have to call user.getIdToken(true) every-time and get a fresh token before I request from my back-end API?
The idTokenChanged() observer is a bit misleading. It will fire when the token is refreshed, but the token is only refreshed automatically when you also use other Firebase products (like its database or file storage). In other cases, as you said you should call user.getIdToken(), which will refresh an expired token for you if necessary, everytime you call your API. You don't need to pass true into this method unless you want to have a completely fresh token everytime (which you most likely don't need).
To my knowledge you cannot control the expiration of tokens generated with the client SDK, for that you would need to generate your own tokens on the server.
I have a nodejs as the api server and react as the web app. I only use jwt token to authenticate users and store the token in browser local storage. How do I force a user to logout?
You better store token in your server side. Then you can easily revoke or remove a token. User has to authorize or validate token each time when they use your api. If your use express session, you can just call req.session.destroy().
The token can contain an expiration date as part of the payload. This way every time you make an api call with that token you can check if the date is expired.You can have middleware that performs this check on every request. If the token is expired, you can force them to re-login and assign a new token at that point.
Remove the jwt token and just restart our react web app
TLDR
I am looking for somewhere to send cognito JWT's from the backend to verify the user's status.
I currently have a react app, with a serverless apollo api, and dynamodb database, all running locally.
The react client uses aws-amplify to register, sign-in etc with
aws-cognito - returning access, id and refresh tokens.
Users can also sign in with facebook and google,
amplify.Auth.federatedSignIn which returns the cognito identity
credentials.
The tokens are then passed to the backend, where they are verified.
So far I cannot find where to send the tokens from the backend, to verify that the user is signed in to cognito.
I have scoured the docs but TBH that has left me more confused.
As far as I can understand, in production API Gateway, or AppSync can intecept the tokens between the front and backend, but since I have verified tokens at the backend currently is there an endpoint or SDK method I can hit with tokens/ access keys etc to check the users status?
Feel free to tell me if I'm going about this the wrong way.
If you need to verify that a token is valid and unexpired, with the JavaScript SDK use
const cognitoServiceProvider = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
await cognitoServiceProvider.getUser({
AccessToken: accessToken
}).promise();
This will throw an error if the token is not valid.
If you are using a different SDK, find the equivalent call.
I have a problem understanding the principle handling of oauth 2.0 tokens.
My scenario is, I have a web based frontend backend system with node.js and angular 2.
A user should be able upload a video on this site. Then some additional metadata is created (dosen't matter for this question). When that is done, the user could upload the video to youtube with the additional data by clicking on a button.
My question is how many tokens/credentials are there in this process. The youtube api needs an oauth token. Does the user also have its own token?
Here is the tutorial I used:
https://ionicabizau.net/blog/14-uploading-videos-to-youtube-using-nodejs
As you can see one token for the API is created for local testing. But is this token generated in a different way in a live version? And how is the user of my website recognized. Also via this token? Or do I have to generate a second token for him?
I am not sure what you mean by 'Token'.
In order to access any Google API you will first need to register your application on Google Developer console. You will then need to create Oauth2 credentials. Oauth2 credentials is were your application will request access from a user to access the data on their YouTube account.
On Google Developer console you will need to save the Client id, client secret and the redirect uri. All three will be needed by your code to authenticate the user.
When the user grants your application access to their YouTube data. You will get an access token and a refresh token back from the authentication server. Access tokens are short lived about an hour and are used to make requests (like upload) to the API. A refresh token can be used to request a new access token once the one you have currently has expired.
You will probably end up with the following:
client id, client secrete, redirect uri, and a refresh token.
If you are interested I have a tutorial that is part of my Google Development for beginners tutorial series that explains Oauth2 and how it works.
An access token is generated from the Server side and sent back to client from where the access request is generated. For all the subsequent requests you need to pass the access token which will be verified with the signature of the token saved on the server to check the authentication of valid requests. You will only get 1 access token which will be used.
You can also use "Refresh" tokens in case you need to keep your access tokens valid for longer duration.
I'm currently using firebase.auth().createUserWithEmailAndPassword(email, password) to authenticate users and using the JWT token from firebase.auth().currentUser.getToken(true) for API requests. However, Firebase is invalidating the token after 1 hour. So I'm wondering how should I refresh the token. Do I have to use my own custom token generation to properly utilize token refreshing?
I'm currently using this though I only tested it once but it seems to work.
firebase.auth().onAuthStateChanged(function () { // Refresh token here })
I've been reading the docs over and over again and haven't seen any mentions of refreshing the tokens for the Web Apps. I've also looked at example repositories for firebase and have not seen anyone use onAuthStateChanged for something like this. So I'm wondering is this the right approach for client side token refresh? The reason why I feel this might not be the best approach is because this might have a race condition. For example if the token expires and I send an API request with the old token before I refresh the token then my API request will have an auth failure for token expiration.
This is very similar to the question in Firebase DB HTTP API Auth: When and how to refresh JWT token? but slightly different in the sense that the question is for using Python and no mentions of onAuthStateChanged.
Thanks!
For those who came into this post looking for an answer. You can grab the token right before all your API calls to get the token.
// Make sure you don't pass in true which will always refresh the token
firebase.auth().currentUser.getToken()
Firebase will internally determine if the token needs to be refreshed or grab from cache. If you notice Firebase will not send any network requests until the token is expired.