Good day friends,
I am developing an application, in my user system add the functionality for administrators to raise the level of the account (if level 10, it's admin) or ban it from the site.
Once the user logs in, he receives a token that contains information about the level of his account, whether it is banned or not.
This function works perfectly, but if the user is banned, they can continue using the site until they receive a new token or it has expired, since the information is acquired from the token. I want to force the user to close their session (destroy JWT token) once it is banned or its level has been edited.
I can verify in the routes that every time the user makes a call, the backend checks in the database if the user is banned or not. But I would like to simplify this step so that the server does not make so many calls to the database. It occurs to me to remove the user's specific token or make it invalid once it is banned from the site or its level has been altered. So the user is forced to log in again and get a new token.
Is there a method or library that makes it easy for me to remove the tokens or make them invalid?
Because if i enter with my admin account and try to edit my account and give it a level 1, i should not be able again to edit this user because my lvl is 1 and i need lvl 10 again for using this route functions, but i can edit it again because token authorization is valid and that shouldn't happen
I want to force the user to destroy their JWT token once it is banned or its level has been edited.
This is not possible, a user can retain any data you've given them.
The best solution you can get with tokens would be to have a very short expiry for their access tokens, and verify the blocked status and level every time you create a new one for them. If a few minutes of lag is acceptable to you, this is the way to go.
Is there a method or library that makes it easy for me to remove the tokens or make them invalid?
You are looking for plain HTTP sessions. You would not hand out any signed tokens with the data at all, you would store the session data on the server side - in ram, an extra cache, or a database. From there you can purge it to invalidate the session and log out the user, or change their access status.
There's a standard implementation for about every server ecosystem. Don't implement this yourself with a database request on every route, use a middleware solution like express-session (see How to use session variable with NodeJs?).
I'd like to simplify the authentication workflow in my Firebase app, and let users connect without password:
With third party OAuth providers: Facebook, Google, etc.
or
With email
If the later, the user would just fill in their address, receive a URL, and instantly get logged in without having to type/remember a password.
Whenever they logout, or, their session times out, they would enter their email again, and receive a new link to start a new session.
How to do that with Firebase?
I feel like it's not possible on the client, so what would be the best server side routine to achieve that workflow?
Finally, after taking some time to figure this out, I quickly realised that the email verification process cannot be used to solve this: the function to get this email sent can only be called by already logged-in users (which makes perfect sense). Hence it cannot be used to sign-in.
I ended up using this workflow with Firebase custom authentication :
CLIENT User asks to login, he's asked his email address, and told he will receive a link to complete log in upon form submission.
SERVER Receives the email address. Finds or creates user id belonging to that user, creates a custom token with this uid and sends an authenticated link by email (for example: http://myapp.com/?token=XYZ)
CLIENT User comes back in the app by clicking on that link, and the app can use the token parameter to immediately log-in the user using firebase.auth().signInWithCustomToken(token).
Look, ma, no passwud!
For Email part you can :-
Use custom passwords from Front-End eg:- timestamp's or some random words+timeStamp . And store that timeStamp in the users's Database for future reference for session expiration.
For sending a link for starting a session you can use the verification email to send a link inside and modulate the contents of the mail as per your needs.
For knowing when your session expire's:-
Just retrieve the timeStamp lets say that is timeKeyRetrieved
Check how much time has passed since the timeStamp
PS:- For checking wether user session has expired during the user is online. You will have to use timer. And whenever your users gets online just retrieve the timeStamp in AppDelegate methods or viewWillAppear:
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I would like to know the best practices to invalidate JWT without hitting db while changing password/logout.
I have the idea below to handle above 2 cases by hitting the user database.
1.Incase of password changes, I check for password(hashed) stored in the user db.
2.Incase of logout, I save last-logout time in user db, hence by comparing the token created time and logout time, I can able to invalidate this case.
But these 2 cases comes at the cost of hitting user db everytime when the user hits the api. Any best practise is appreciated.
UPDATE:
I dont think we can able to invalidate JWT without hitting db. So I came up with a solution. I have posted my answer, if you have any concern, you are welcome.
When No Refresh token is used:
1.While changing password: when the user changes his password, note the change password time in the user db, so when the change password time is greater than the token creation time, then token is not valid. Hence the remaining session will get logged out soon.
2.When User logs out: When the user logs out, save the token in a seperate DB (say: InvalidTokenDB and remove the token from Db when token expires). Hence user logs out from the respective device, his sessions in other device left undisturbed.
Hence while invalidating a JWT, I follow the below steps:
Check whether the token is valid or not.
If valid, check it is present in invalidTokenDB (a database where logged out tokens are stored till their expiry time).
If its not present, then check the token created time and changed password time in user db.
If changed password time < token created time, then token is valid.
Concern with the above method:
For each api request, I need to follow all the above steps, which might affect performance.
When Refresh token is used: with expiry of access token as 1 day, refresh token as lifetime validity
1. While changing password: When the user changes his password, change the refresh token of the user. Hence the remaining session will get logged out soon.
2. When User logs out: When the user logs out, save the token in a seperate DB (say: InvalidTokenDB and remove the token from Db when token expires). Hence user logs out from the respective device, his sessions in other device left undisturbed.
Hence while invalidating a JWT, I follow the below steps:
check whether the token is valid or not
If valid, check whether the token is present in InvalidTokenDB.
If not present, check the refresh token with the refresh token in userDB.
If equals, then its a valid token
Concern with the above method:
For each api request, I need to follow all the above steps, which might affect performance.
How do I invalidate the refresh token, as refresh token has no validity, if its used by hacker, still the authentication is valid one, request will be success always.
Note: Although Hanz suggested a way to secure refresh token in Using Refesh Token in Token-based Authentication is secured? , I couldn't able to understand what he is saying. Any help is appreciated.
So If anyone have nice suggestion, your comments are welcome.
UPDATE:
I am adding the answer incase your app needs no refresh token with lifetime expiry. This answer was given by Sudhanshu (https://stackoverflow.com/users/4062630/sudhanshu-gaur). Thanks Sudhanshu. So I believe this is the best way to do this,
When No Refresh token needed and no expiry of access tokens:
when user login, create a login token in his user database with no expiry time.
Hence while invalidating a JWT, follow the below steps,
retrieve the user info and Check whether the token is in his User database. If so allow.
When user logs out, remove only this token from his user database.
When user changes his password, remove all tokens from his user database and ask him to login again.
So with this approach, you don't need to store neither logout tokens in database until their expiry nor storing token creation time while changing password which was needed in the above cases. However I believe this approach only valids if your app has requirements with no refresh token needed and no expiry of the tokens.
If anyone has concern with this approach, please let me know. Your comments are welcome :)
There is no way I know of to arbitrarily invalidate a token without involving a database one way or another.
Be careful with Approach 2 if your service can be accessed on several devices. Consider the following scenario...
User signs in with iPad, Token 1 issued and stored.
User signs in on website. Token 2 issued. User logs out.
User tries to use iPad, Token 1 was issued before user logged out from website, Token 1 now considered invalid.
You might want to look at the idea of refresh tokens although these require database storage too.
Also see here for a good SO discussion regarding a similar problem, particular IanB's solution which would save some db calls.
Proposed solution
Personally, this is how I'd approach it...user authenticates, issued with access token with a short expiry (say 15 mins) and a refresh token valid either for a much longer period or indefinitely. Store a record of this refresh token in a db.
Whenever the user is 'active', issue a new auth token each time (valid for 15 mins each time). If the user is not active for over 15 minutes and then makes a request (so uses an expired jwt), check the validity of the refresh token. If it's valid (including db check) then issue a new auth token.
If a user 'logs out' either on a device or through a website then destroy both access refresh tokens client side and importantly revoke the validity of the refresh token used. If a user changes their password on any device, then revoke all their refresh tokens forcing them to log in again as soon as their access token expires. This does leave a 'window of uncertainty' but that's unavoidable without hitting a db every time.
Using this approach also opens up the possibility of users being able to 'revoke' access to specific devices if required as seen with many major web apps.
I am not sure if I'm missing something here but I find that the accepted answer is more complicated than is necessary.
I see that db has to be hit to validate or invalidate a token for each api request, however the total process could have been simpler as I see things here.
Whenever a jwt is created, i.e. during login or change/reset password, insert the jwt with userid into a table and maintain a jti (a uuid number basically) for each jwt. The same jti goes into jwt payload too. Effectively jti uniquely identifies a jwt. A user can have multiple jwts at the same time when the account is accessed from multiple devices or browsers in which case, jti differentiates the device or the user-agent.
So the table schema would be, jti | userId. (and a primary key ofcourse)
For each api, check if the jti is in the table, which means the jwt is a valid one.
When the user changes or resets the password, delete all the jti of that userId from the db. Create and insert a new jwt with a new jti into the table. This will invalidate all the sessions from all other devices and browsers except the one that changed or reset the password.
When the user logsout, delete that particular jti of that user but not all. There would be a Single Login but not a single Logout. So when the user logs out, he shouldnt be logged out from all the devices. However, deleting all the jtis would logout from all the devices too.
So it would be one table and no date comparisons. Also it would be the same case if a refresh token is used or not.
However to minimize the db interference, and possible delays, cache usage would certainly help to ease things on processing time front.
Note: Please reason if you are down voting it.
If a user is changing their password, you're going to hit the db there. But don't want to hit the db for authorization?
I have found the benefits of storing a per user string, and a global shared string hashed together gives us the most flexibility with our JWT implementation. In this particular case I'd store a hash of the password to use with the global string and hash them together for a JWT secret.
I agree solely with #gopinath answer just want to add one thing that you should also remove the change password time when all of your tokens expired for example suppose you have set 3 day expiry time for every token to expire now instead of just normaly saving change password time in database you can also set its expiry time of 3 days because as obviously tokens before this will be expired so no need to check for every token again that whether its expiry time is greater then change password time or not
I need to access status updates of an artist page to display as feed on my website.
So everytime a user accesses the artist' space on my website, he sees the artist's status feed in a tab.
Do I need to ask for the artist's permission every session? That would not be practical I guess.
Thanks
You only need to ask permission once, when the user logins for the first time.
If you use the client side JS SDK, that is really all you need to worry about. The access_token will be automatically refreshed by the SDK whenever needed. The user only needs to be logged in to facebook, no action is required.
You will most likely be using the JS SDK.
So unless you use a manual server side oauth flow, see below:
If you use a manual server side oauth flow you usually get a short-term access_token that is valid for 2 hours after the user logs in for the first time.
You can request a long term access_token by sending a request to oauth/access_token with some additional parameters:
See here:
https://developers.facebook.com/docs/facebook-login/access-tokens#extending
This long lived access_token is valid indefinitely, but may expire at ANY moment.
Reasons could be:
user password change
user logout
use de-authorizes app
...
So you are to just reuse the access_token whenever you want to interact with the users facebook account ( you don't have to ask them to log in again).
But as soon as your access_token becomes invalid, you have to update the acces_token by sending the user trough the oauth flow again.
I have an application that uses backbone.js on the front end. So I had a question of how does it handle the user session? Everytime i send a GET,PUT,POST request, the user has to be authenticated else I get a error from the server side. Hence I used the Backbone.basicauth.js plugin which enables the basic authentication before any requests are sent across the server. I just need to call Backbone.BasicAuth.set('username', 'password');
But the problem here is that I need to hardcode my username and password everytime. So I wanted to know a way where in I can dynamically do that or a way in which I can track if a user is already logged in or i need to redirect him to a login page.
What if the user enters a random url instead of the home page, how will I track if he is logged in or not and how will I save the session?
At www.TheLadders.com we use form authentication and then drop a cookie with an encrypted token which we use to authenticate subsequent requests. We like it better than a traditional server side session approach because we can run all our servers stateless.