I'm using a Node.JS express backend and an Angular 4 frontend in this app. I use JWT tokens to store an id which I use to find a user. Please note these JWT tokens do not expire.
Scenario:
User logs in.
JWT Token is generated and signed (containing the user ID)
JWT token is saved in localStorage
JWT token is used from then on to find the current user that's logged in
This was working perfectly. Now, something really weird happens. In production, occasionally, the JWT token seems to change value which then throws an error on my application as the user can no longer be found. I've run through all the code, nothing on the app itself should be changing the value at all.
I appear to have isolated this issue as only occurring mostly in Google Chrome however, (I think) I might have seen it occur in Safari at times. I have no idea why this would be happening. When I go to a protected page in Angular, it checks if a JWT token exists or not before proceeding. If it doesn't then it'll go to login. Nowhere is the value of that token changed.
Does anyone know what I may be doing wrong/why this is happening?
Are you using a middleware function in order to implement your JWT logic?
If not, I would recommend using a middleware function, that is written prior to your route logic/handler function. I guess, that helps debugging the problem and also a good practice.
Related
I'm currently trying to keep the user logged in. E.g. if he goes from "/homepage" to "/foo" the user data should persist.
I thought about using JWT to create a token, that I store inside the req.headers, verify the token everytime the user changes pages and then call the api to get the user from the database.
Also thought about using cookies to store the JWT Token inside.
But I'm not sure if thats the correct way and if that way is that secure.
Any help would be much appreciated :D.
Thank you.
I'm currently trying to figure out what the difference between gapi oauth access tokens and access tokens created via the googleapis package is. There apparently is a difference, since when I try to use the access token generated by gapis to authenticate to google picker using setOAuthToken() only the gapi access token works. This is unfortunate, since I need to refresh tokens on the backed and I therefore cannot use gapi. When I try to use the googleapis token, I get prompted to sign in, which is also not very ideal.
The scopes for both are exactly the same and the client_id is the same. The only idea I have is, that it might have to do with the googleapis one being an offline token, but that shouldn't matter right?
The code for the picker is pretty much straight from their docs:
picker = new google.picker.PickerBuilder()
.setCallback(pickerCallback)
.setDeveloperKey(apiKey)
.addView(google.picker.ViewId.SPREADSHEETS)
.setOAuthToken(access_token)
.build();
Anyone know what's going on here?
I have also seen a couple other people ask similar questions, but either their answers didn't fix anything (probably because some of the problems date back to 2012 and earlier).
EDIT: Nevermind. Somehow it resolved itself. I really have no idea why....
I am resolving user data using firebase for auth like so:
from firebase_admin import auth
decoded_token = auth.verify_id_token(client_id_token)
I am initializing my firebase creds with firebase_admin.initialize_app(cred)
Here cliend_id_token is a token that the client sends. However, this takes around 1 second to perform, which seems way too long. One possibility is to use a caching layer above this (lru cache, memcache) but it still seems that it should not fundamentally take so long. Looking at the the signature of verify_id_token there does not seem to be anything that stands out as something that I can pass in:
def verify_id_token(id_token, app=None):
Any thoughts on how to diagnose (or if I am missing something)?
The problem is because that function does an http request in order to have the key to decode the jwt. In addition, because it returns info such as the email of the user, while the jwt contains only the uid as sub field of the decoded jwt, I think that it does another http request under the hood to get the user from the decoded uid.
You should implement your custom decode function, following the docs: https://firebase.google.com/docs/auth/admin/verify-id-tokens
I'm having the same issue. It's about 200ms for me (I'm using fastapi). #EuberDeveloper - glad to hear it's the same on node js - you saved me from testing it out.
I wanted to mention how I got my setup working faster in case anyone would benefit.
I've got Google API gateway with Firebase security defined in the swagger spec in front of a Cloud Run instance. API gateway validates the jwt (as per the swagger spec) and passes on the authorization header to the backend as a renamed header (from memory it's X-FORWARDED-AUTHORIZATION but best to double check). This is pretty fast.
Then in the backend you don't need to validate the id token since it'll already be validated by the time the request gets there. And if you send the UID along in the request to your backend as well as the idtoken in the authorization header, you can fetch users with the UID field you send. This removed that 200ms it was costing me to decode the id token.
Note - if you want to do things like check how old a refresh token is and revoke it for some reason then you'll still need to decode the id token.
I'm trying to work out the best way to keep users logged in to my RN app once they've logged in, until they uninstall the app.
I'm using a Node/Express back end that accepts a JWT with every request and my only plan at the moment is to send a never expiring JWT on log in and store it permanently using AsyncStorage.
This instinctively feels unsafe, but I'm no expert in security and tokens. I'm using Expo to get my RN app off the ground at the moment but in the future I plan to "eject" it and once I do I can store it more securely using react-native-keychain but it'll still be a JWT that never expires.
My spotify app never asks me to log back in, so I know what I'm trying to do is not crazy.
But is there a better way?
You should not use long-term JWT since they can be cracked easily if the secret keys used are weak or short.
There are some of the libraries available which might help you track the bruteforce duration under which JWT can be cracked, such as jwt-cracker, c-jwt-cracker.
Therefore you should use the SecureStore already available in the Expo SDK.
IOS values are stored using the keychain services and Android values are stored in SharedPreferences, encrypted with Android's Keystore system.
If there is an error in the API, that uses a token, you can simply make a call to either reauthenticate or refresh it using Interceptors
I've built my MEAN web application. To authorize users I'm using JWT tokens. But there is one problem. Sometimes while reloading page I get 401 Unauthorized while I'm still authorized. I checked twice my token in locale storage and it was right there. Then I tried to reload other my pages and it's so weird cause some of the are reloading nicely and some are returning 401. I have this error while hosting my app on Heroku . I'm using angular 5 for frontend and Node js for back. Does anyone have such a problem. If you need code it's on my github https://github.com/tia337/MEAN-Stack .
I think it have some problem in package. tokenNotExpired function have some issue. You can also check by your own whether token expired or not. Just decode your token from JWT library and compare expire time with current time.
Hope it will help.