Can i use a Firebase token (JWT) to identify a user with an expire date > than 1 hour? - node.js

I'm using Cloud Firestore for Firebase to store informations about a Rest API Service written in NodeJs.
So, every request to Node will ask to Firebase informations about the service and, for first, it will authorize the request.
I thought that use an user generated JWT will be the best solution because the client have to simply include the JWT in his requests to authorize itself.
A Firebase JWT is related to the uid of the user that generates it.
Obviously, there'll be a control panel where the user can log in with email/pw and generate the JWT, and then the JWT will be included in his client system, for example like simple APIs that requires an API Key to identify the user and to work.
So, the idea appears to work good but i noticed that the Firebase JWTs expire in only 1 hour!
The user have to log-in to the control panel every hour to re-generate the JWT. That's not so friendly.
How can avoid this problem? How can i make the JWT expires in more than only 1 hour?

According to documentation:
The maximum lifetime of a token is 24 hours + skew.
[...]
with a skew of up to 10 minutes.
That means you cannot use these tokens forever, which kind of makes sense.
I looked at custom tokens and found:
The time, in seconds since the UNIX epoch, at which the token expires. It can be a maximum of 3600 seconds later than the iat.
Note: this only controls the time when the custom token itself expires. But once you sign a user in using signInWithCustomToken(), they will remain signed in into the device until their session is invalidated or the user signs out.
Perhaps you can do something with the signInWithCustomToken() as once logged in it expires only when the user is invalidated or signs out, but I believe the best course of action would be to look for another approach.

Related

Which is the correct way to persist Firebase Session after cookie expires?

I've been dealing with authentication, reading and watching videos about it. I came up building my own JWT solution, based on an access_token who expires after five minutes, and a refresh_token that never expires. I stored that tokens in cookies and I use the second one to provide more access_tokens when needed. I store the refresh_token in Redis, to be able to revoke if one of those is leaked / stolen.
Nowadays, I need to move my auth system to Google Firebase in order to store my users there, and to add the Google and Facebook login as well. But I found that I need to create a sessionCookie that expires in, as much, two weeks. After that, the user is signed-out from the app and it needs to access again manually. I want to refresh that firebase sessionCookie in the correct way (automatically, server-side), but the docs say nothing about it. I came up doing my own solution again, but I believe it is not right.
I don't want to use the getIdToken method because, with that thing of custom tokens, I need to modify each of my api calls in the client side, and that's not the idea. I want to do the refresh at server-side.
So, which is the correct way to refresh the sessionCookie automatically and to keep the user authenticated permanently?
Info that I read here:
How to Refresh Firebase Session Cookie (stackoverflow)
How to extend Firebase Session Cookie Beyond 2 weeks? (stackoverflow)
Refresh Tokens (by Auth0)
JWT Auth with Node.js (youtube)
Server-side Firebase Authentication Using Express JS (youtube)
And, of course, the official docs from Google Firebase
Firebase session cookies expire in an hour, to my knowledge this cannot be modified or changed. the main takeaway should be why you would need a token to expire after 2 weeks rather than demand it on a per need basis from the Refresh token?
The solution is to generate a custom JWT token and store it online(optional) and pass it to the client. The client then uses this key for long-term authentication. this does mean that all requests would have to be validated and decoded within your backend, the only issue from there would be local caching, which can be done in several ways including standard local storage and cookies.
The flow would be: Firebase Refresh token -> Generate Firebase Auth ID Token -> Get user.uid -> Load custom JWT from storage or Generate a new jwt from the admin-sdk.
From the Admin SDK documentation with custom auth, these 3 topics are of interest.
https://firebase.google.com/docs/auth/admin/create-custom-tokens#create_custom_tokens_using_the_firebase_admin_sdk
https://firebase.google.com/docs/auth/admin/create-custom-tokens#sign_in_using_custom_tokens_on_clients
https://firebase.google.com/docs/auth/admin/create-custom-tokens#create_custom_tokens_using_a_third-party_jwt_library
The only thing to figure out is how you want to store the jwt client side.

Only allow signing in from one device at a time in NodeJS

I am using JWT for authentication. However I do not want the user to be logged in from multiple devices. How do I ensure this?
Right now - All I can think of is to store the JWT into DB and then check if it exists . And if it exists, what was the time it was generated at. If too much time - we go and regenerate the token and pass on back to the 2nd device.
That's pretty much your only option, the JWT is pretty stateless on purpose. Similar to how you can't really do a server side logout without similar technique
As jfriend points out, storing the JWT alone is insufficient. What you need to do with it is ensure that the next time a user requests login, that they don't already have an unexpired JWT issued to them.
Going through the flow for completeness:
Case 1: User isn't logged in anywhere. In this case, JWT is issued and stored. Possibly in the user record for easy retrieval.
Case 2: User tries to log in on another device. Whether you make them explicitly log out of the first device or do it for them, you have to now send that stored token into a list of revoked tokens. Your token validation logic will have to take that list into account when determining if a token is valid or not.
/* Further clarification */
I feel like a bit more detail might be useful for folks, so I'm going to go into implementation a bit.
** Unauthenticated requests **
This shouldn't change, but it's worth mentioning that I'm assuming you have routes that require authentication, and requests to those routes which do not include an active and valid JWT get rejected with a 401 (and probably provided the URL to the login url).
Login
Login logic always includes a user lookup, so as described above, the flow in this application should include that lookup, but before logging the user in the application you will check to see if there's already an assigned token to the user which has not expired.
If there is not a token already assigned to the user, then check credentials however you normally would, generate a JWT (with an exp heading to indicate expiration time in the payload), save that token back in the user document/record for future reference.
If there is an assigned token which is also unexpired, then you either have to log the user out of the other device (more on that in a second), and log them in to the current device, or else you have to reject the login attempt and keep the person logged out of the new device. I think the former approach is more user friendly, but it depends on the needs of your application.
Logout
With JWT, the only way to guarantee a user is unable to use an issued token is to either include an expiration time (exp) in the payload, and use a verifier that checks that, or to know on the server which tokens are no longer valid and check against them. The most robust solutions do both.
So, assuming you're handling the expiration already the explicit logout feature would be handled by creating a revoked tokens list somewhere. If you're using MongoDB, for example, you'd create a collection to store those. You'd ideally also set a TTL on each one that is set to some point after the expiration date, so that Mongo will evict tokens that are otherwise expired anyway, to save yourself time and space.
If you're doing the auto-logout on a new login request, you'll hit this logic to place the old token into the revoked tokens list when you save the new token in the user's document.
The logout route should also be reachable by authenticated users, to explicitly logout if they want, regardless of whether you do the auto logout or not.
Authenticated Requests
By this point you should be reasonably certain that users can only login on one device. However, you also need to make sure that they aren't trying to make a request with a revoked token.
Your generalized route security middleware would then need to also check the revoked token list to see if the token offered by the client is on said list after checking to make sure it's not expired (since the expiry can be checked upon validation, saving a round-trip to the DB.
I totally agree with #Prateek Narendra.
once user is logged in store it's token in DB (i stored it in activeJWT field) then on further login check if activeJWT is null or not.
If yes then allow login else not.
At logout time u need to make activeJWT field null.
you can decode the current token for that.
Note: I am not an expert in auth.
I think you should save the last_login date time in DB.
Set JWT expire to 7 days. Renew JWT token for every request (for example user request /user this endpoint here sends new JWT token every time.)
On logout set last_login to null
When someone tries to log in
check the last_login field if it is null or last_login date-time is older then 7 day then procced otherwise
display a message to Logout first.

How to manually revoke an auth-token on Rackspace?

Say I generated an authentication token on rackspace, and use it for a session login.
Now, for security reason I want to invalidate/revoke that token before the expiry date manually, so that on each new session of the application I have a new token to be safe.
Note: There is only one session at any given time.
I read the rackspace API docs. And it says that: the token's default lifespan is 24 hours. But that is too long. Can I set the expiration time manually?
The doc page at: http://docs.rackspace.com/cdns/api/v1.0/cdns-devguide/content/Authentication-d1e647.html
says that: A token may be manually revoked before the time identified by the expires attribute. So I started searching more but no luck.
There was this question on setting the expiration time manually for the token
https://community.rackspace.com/developers/f/7/t/669
and it say that there is no way to set it manually now.
I think revoking the token is possible currently, but I can't find any way for it, I just wanted to make sure I didn't miss something in the docs.
You should be able to revoke a token by sending a DELETE call to the identity endpoint: https://identity.api.rackspacecloud.com/v2.0/tokens/{tokenId}. It's documented in the identity service guide:
http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/DELETE_revokeToken_v2.0_tokens__tokenId__Token_Calls.html

JsonWebToken: activity-based expiration vs issuing time-based expiration

I'm fairly new to token based authorization. I'm trying to find the flaws in a custom expiration/token-refresh scheme.
I have a basic JWT auth setup in an Express API; I'm setting the JWT expiration to 1 hr; However, JWT checks token expiration relative to the time the token was issued. I would prefer that the expiration time gets reset after each successful api call. If my user is actively using the app for more than an hour, I don't want them to have to log back in to refresh the token (and possibly lose whatever data they are working on.)
On the the other hand, I do want the token to expire if they are not responsive for more than an hour.
I have come up with the following approach:
During every successful API request, issue a new JWT and send it in a
custom response header. My client side code is responsible for
checking this JWT response header and using its value as the new default Authorization request header. Thus, if there is no API
request from the user for more than 1 hour, the token will expire and
not be refreshed. Login would then be required. In addition, the original issue-date of the token (timestamp of login-authentication) will be stored so that a "hard-expiration" of the token will be enforced after 24 hours.
This seems fairly straightforward and reasonably secure, but I haven't seen any reference to it in my JWT research. Is there a better way to achieve the same goal? Am I missing a major security hole with this approach?
UPDATE:
After thinking of this for some time, I realized that the problem with this is that it opens the door to replay attacks that could not be thwarted by token expiration. So there should absolutely be a "hard-expiration" check: hard expiration would invalidate the token at some time after issue date, regardless of recent user activity.
Here you can check my answer for this scenario:
implementing refresh-tokens with angular and express-jwt
What I have done is to have a time window where the server checks if the token expiration and the local server time is in this window and then send a response header with the refreshed token.
If you agree and realize that you need a hard expiry time anyhow, why not set the expiry time of the (one and only) access token to that and stick to plain OAuth 2.0? An asymptote of what you're doing now, would be to issue your own API specific token/cookie after first use of the access token (in the API response) and enforce subsequent API access based on that. That is a valid approach, but duplicates a lot of stock OAuth 2.0 Authorization Server functionality in your own API. I don't see a good reason to go there.

Instagram access token expire

I have an app, that pulls data from my Instagram account.
I authorized this app once, and got access token. But I'm worried,
what if this token expires? Should I authorized the app each time the
token expires?
Can I receive another access token from the auth code?
If no, what can I do to have my app always pulling data from account
without my participation?
Thanks.
But I'm worried, what if this token expires?
AFAIK, Instagram accesstokens don't expire currently.
Note: From Instagram documents.
Note that we do not include an expiry time. Our access_tokens have no explicit expiry, though your app should handle the case that either the user revokes access or we expire the token after some period of time. In this case, your response’s meta will contain an “error_type=OAuthAccessTokenError”. In other words: do do not assume your access_token is valid forever.
Should I authorize the app each time the token expires?
At the moment, you do not need to do that, as token does not expire. As and when the token expires in future, a corresponding warning or error code and message will be sent to you, which you need to handle.
what can I do to have my app always pulling data from account without
my participation?
You can try following:
Use sharedpreference to store the accesstoken.
First time when you try to fetch data that needs accesstoken(Authenticated requests), first check in the sharedpreference whether the accesstoken is stored or not.
if yes then you don't need to login, just use that accesstoken. If you don't have the accesstoken in preference then do the login using instagram credentials, get the accesstoken and then share it in shared preference and use that for subsequent requests.
You can provide instagram logout option in which you just need to clear the accesstoken from sharedprefernce.
Hope this is helpful to you.
Update - This no longer works as mentioned in the comments
While not well documented, It's worth pointing out that retrieving a feed of posts does not require an accessToken.
https://api.instagram.com/v1/users/{user-id}/media/recent/?access_token=ACCESS-TOKEN
can also be called passing just your client_id
https://api.instagram.com/v1/users/{user-id}/media/recent/?client_id=CLIENT_ID
This isn't made clear in their documentation though.
https://instagram.com/developer/endpoints/users/
The Instagram access token expires at arbitrary times.
Twice in the in the last 7 months from my experience.
I did not find any way to regenerate the token without my participation, the only valid solution IMHO is to avoid the official API and use something like:
https://stackoverflow.com/a/33783840/
For the last 3 week, I have created new token multiple time and its expire after 2 days, but I also notice that some token didn't expired which were created before 3 years. Also, Instagram docs say the token can expire any time in the near future.
There is a hack at this moment to show the user's last post just append URL with `/?__a=1''
after user name such as
https://www.instagram.com/vaseem.ishak/?__a=1
you will get user last post with image text, no of comment like etc.just dig little the return JSON

Resources