Firebase login with custom auth token does not expire after 1 hour - google-cloud-firestore

I have a react app where I am able to login with custom token as follows:
await firebase.auth().signInWithCustomToken(tokenResp.token);
As per this, firebase custom jwt have one hour expiry. And this is what I expect.
But when I make calls to collections that require authentication(i.e. request.auth!=null via firestore rules) after 1 hour, I am able to access them. I would expect the firebase instance to fail(automoatically) after one hour for these calls.
So why is it happening and how do I fix it?
Also note that I have logged in the jwt used to authenticate and clearly the expiry date is one hour by looking at the exp field in jwt decoder.

When the documentation states that the Custom Token (tokenResp.token in your case) is valid for one hour, it means that the signInWithCustomToken call must happened within one hour after token creation. Once the user is "signed in" (using any of the signInXXX methods), they get an access token and a refresh token, which can be used indefinitely until sign-out or revocation.
It sounds like you're trying to use Security Rules to limit access to users who have signed in within the last hour. To achieve that, inspect the auth.token.auth_time field which contains when the user has authenticated (in seconds since epoch). For example: request.time < timestamp.value(auth.token.auth_time * 1000) + duration.time(1, 'h') evaluates to true if the request time is within one hour of sign-in time. You can use that in place of request.auth!=null.
In addition, you can automatically sign users out after one hour on your client side, say using JavaScript timers and checking (await firebase.auth().currentUser.getIdToken()).auth_time as well. (Please note that this merely improves user experience on the client side and is not a substitute for the Security Rules, since client code cannot be fully trusted.)

Related

How to prevent log out users when changing JWT secret?

I am using a JWT token implementation of this https://jwt-auth.readthedocs.io/en/develop/quick-start/
I need to update the secret key and is there a way to update it without logging out every user? I presume it's not possible to reuse the old token once my secret key is changed. So all my users will be logged off and need to log in again. Is there any way to go around this?
If not, if for security reason, I need to update the secret monthly, that will be pretty troublesome to ask my user to re-login monthly.
Thanks!
If you change your keys it's correct to invalidate all the tokens signed with the old ones as they are to be considered expired.
It's a good practice to let the token expire as well after a certain amount of time. Usually you implement a mechanism based on two tokens, access_token with an expiration of 1h (usually) and a refresh_token with a longer expiration (usually 24h). The second one is used to renew the first one. When the second one expires, the user has to be considered logged out.
What you need is to implement a refresh token mechanism. You can implement it from scratch, for learning purposes, or you could just implement OAuth 2.0 protocol, since it's a flow that it already supports. There are lots of libraries both for server side and client side implementations
https://oauth.net/

How to handle JWT expiration

I have a question on "make the browser send out a request to exchange for a new token at the sixth day. Accordingly, on the server side, create a restful API named /token/extend which will return a new token if given a valid token."
Let's assume that I implement this concept. When token is about to expire, we will generate new valid token if old valid token is provided.
Now, let's assume, Hacker gets the token. He uses this token to communicate with APIs. Hacker communicates for 6 days. On 6th day, our "/token/extend" API will generate new token for him so he can communicate for another 6 days, and probably forever. Will this situation occur? or Am I missing something here?
The general way you would force your users to obtain a new token after 6 days would be by simply setting the exp field (expiry) in the claims of the JWT to expire after 6 days. The exact mechanism by which users would use to obtain a new token depends on your implementation.
The most basic implementation would be to just let the incoming request on the sixth day to fail, forcing the consumer of the API to redirect to the login page. From there, the user would have to login again to obtain a new valid JWT. A more elaborate method would use refresh tokens. With this approach, when the user first logs in, he would receive an authentication token with a 6 day expiry (as before), but would also receive a refresh token which would expire a little bit later. On the sixth day, when the user tries to access a service, the request would again fail. However, in this case, the consumer (e.g. a website or mobile app) could take the refresh token and request a new access token under the hood. This would be a more seamless way of handling the mandatory 6 day expiry. Note that with the refresh token approach, the user might never know about the 6 day expiry.
Regarding your concerns about hackers obtaining other people's tokens, you should mostly just forget about this. If someone stole your wallet, there is all sort of havoc he could do to you, e.g. using your credit cards, stealing your identity, etc. The same could happen with a stolen/sniffed JWT. The best practice here is to just make sure you are using two-way SSL for all communication, and also encourage your users not to use your services in places like Internet cafes.

JWT and one-time tokens?

I'm in the process of rolling my own JWT token auth, however, I would really like it to be a one time-token – so once it's used, the server generates a new token and the client will have to use that token during the next request/call.
However, it has come to my understanding that JWT is supposed to be 'stateless' – but with the approach of a one time token, I guess I would need to somehow store the valid tokens, since the token will be refreshed once it's used. Or is there any way to avoid storing a value on the server, and still be able to create one-time tokens?
The two main reasons for why I don't want to store any value is first of all scalability (sure, I could have cache-server inbetween to store the values, but it would be nice if that wasn't required), secondly, JWT is supposed to be stateless from my understanding, which it wouldn't be if I need to store a value on the server to be able to validate the token.
Any ideas?
Use the user's current password's hash for signing the JWT token, in this way all tokens generated before a successful password change would get invalidated the next time. I got the idea from here https://www.jbspeakr.cc/howto-single-use-jwt/.
Solutions exist, of course.
As with any distributed system (you mentioned scalability) you have to choose between availability and consistence.
You choose availability. In this case you could maintain a list of already-used tokens that you replicate in a eventually consistent manner between all the endpoints. For example when a token is used the respective endpoint send that token to the other endpoints in the backgound. There is however a (short) time frame when that token can be used a second time by another endpoint until that endpoint is updated.
You choose consistency (you won't allow a token to be used multiple times whatsoever). In this case you use a central database with already-used tokens and you check that database everytime you need to perform an action. Scalability? You could use sharding on the token and have n databases, each one being responsible for a tokens subset.
It depends on your business what solution fits best.
Not really no, a JWT token is valid if it hasn't expired and the signature is correct, commonly people will keep a DB of blacklisted tokens which are usually ones where people have logged out etc.
The only sensible way I can think of is give them a short expiry time and maintain a list of tokens that have already been used, you'd then periodically remove the ones that subsequently expire from the DB.
There are actually some DB's that have a TTL on records (dynamoDB, mongodb) so you'd just put the tokens in and set a TTL for when the token expires.
Update 2022
Just to be clear JWT tokens AREN'T stateless they have claims that, as long as they're signed by the right private key - give you a stateful piece of data that can be reissued by your API to reflect the current state of the user.
You'd just need to handle token re-issue on the consumer.
Like others have mentioned, it depends on your business case. Password resets links can be like mentioned on https://www.jbspeakr.cc/howto-single-use-jwt/.
If you have the Single-Use & Single-Auth scenario, where you might want to invalidate any previously used and unused token, you can store a single nonce and update it on every new token request and also when its used.

JWT: why do I need a refresh token?

I've been reading a lot about JSON web tokens lately. A big thing that I see is that to have a timeout based on last access, and not a hard timeout, you need to use a separate refresh token. The one thing I don't see is WHY.
Why would a separate token be needed? Why not just refresh a last access value in the initial token every time it's received? The initial access time can still be preserved and a longer hard timeout established regardless.
There are so many options on how to implement JWT and most of what it comes down to is your requirements and how you want the application to behave.
My guess is that reissuing the token every time and updating on the front end will not perform well in a large application. You have to replace the token completely because the last access time stamp is part of the payload and thus, if you change any part of the payload, the signature for the payload will be different. If it's not part of the token, it accessible on the front end and could easily be changed to allow indefinite access.
Refresh tokens are typically associated with OAuth2. Setting up an Authorization server to issue tokens provides a nice division of responsibility and abstracts out a fairly large portion of your application in well documented, standard based way. It also allows you to revoke the refresh token, making it possible to revoke access (although not immediately) of your users. Most importantly it allows you to use the same access token for each request without reissuing it.

OAuth REST access_token and instance_url expiry time?

I am working with Oauth2.0. In that i could able get the access_token and instance_url. Is there any expiry time for these two.
Can I store them and use it for all my REST calls without getting the new access_token and the instance_url. Is it possible for me to use it for long hours or even days.
The access token is only valid for the length of a session (as defined in the Salesforce Org's settings — I believe the longest this can be is 8 hours without activity), as it's actually a session ID, that said, you should also be given a refresh token. The refresh token has a much longer lifetime and can be used to authenticate the user once the session has expired, without them having to enter any credentials — this allows you to do it in the background without them even having to concern themselves with the login process.
model metrics do a good job of explaining the token flow here.