i have recently encountered problem for my app with insufficient session expiration.Basically we have session storage field that contains user token , like that for some more we have tokens. On logout since we are using SSO , we are clearing user session only not other data. we have recently reported this problem.
reference
what might be the solution
To properly cancel the user's session, you should not only delete the local session token, but also cancel the token with the SSO provider.
You don't specify who you are authenticating with, but every reputable SSO provider should have a sign out or log out option which will invalidate their session at the back-end. Then you can delete the user token since it is no longer valid, and no malicious 3rd party will be able to use a session that is secretly still active.
Related
I use jwt tokens in my project. Long-lived refresh tokens to authenticate and short-lived access tokens for protected resources. The refresh token is saved in a http-only cookie to reduce the risk of xss attacks. The access tokens will be only stored in my vuex store of my frontend. Should I renew my refresh token if the user changes the password? I don't store refresh tokens in my database, because as I understood the the main purpose of jwts is that I can use cryptography to verify my incoming refresh token and do not have to look it up in my database (then I don't have to use jwts at all).
But how do I invalide an already sent refresh token e.g. on an other device or browser? If I don't use a database to store refresh tokens the token would be valid as long as the expiration time is. I appreciate any advice.
Since you don't store tokens in the database you can't invalidate them remotely. But there are some common practices to overcome this issue.
NOTE: These are not standards, Just a practice used by major
companies.
1. Store tokens in Cache Database (Not in the main DB)
Storing JWT tokens in the cache database such as Redis or Memcached will allow you to retrieve and verify the token much faster. To invalidate the token you just need to remove it from the cache.
2. Use short-lived access and refresh token
This is mentioned in a lot of Security Submits. Expert says to set a very short life (in minutes) to both access and refresh tokens. Also, exchange the refresh token every time you get a new access token. This renewing process can be happing in the background (maybe using workers). So you don't need to invalidate tokens, It will be invalidated automatically after a few mins.
Recommend you to watch this: https://www.youtube.com/watch?v=rCkDE2me_qk
Store your refresh tokens in a database, with enough context to create a new JWT token (also expiry date, allowed IPs/regions/browsers ...etc) this database will be used only by your Auth service, and only when managing auth (login, logout, refresh access token).
Storing JWT in a database introduces a single point of failure for your microservices (Assuming you are using this architecture), if you're storing JWTs somewhere it would be a simpler implementation to just use session IDs and data.
Give each JWT token an ID (it's already in the default claims), and link that ID to a refresh token
when you invalidate a refresh token, broadcast an event to all your services telling them that any JWT with the token.JwtId is invalid. this invalidates all JWTs created by that token on all services (You can invalidate by token context as well, ex: user id to invalidate all tokens for a user that were created before X)
I am trying to build a simple project where a user can search a movie from an api and add the selected movie to their "/movies" page, after being logged in.
I am using Nodejs, mongodb, express for backend and vanilla javascript for the front end.
When the user is registered or logged-in I am creating a JWT token and adding the token to the database.
My goal is to redirect them to their home page, which is "/user/movies"
Assume the user has logged in the first time, and it closed the
website, after some time has passed (not enough to expire the token)
the user opened the website again and went to "/user/movies" (which
requires an authentication.)
My question is, how would we still keep authenticated with the user after re-visiting, how can we reach the token that is previously created?
When I use postman, I can manually check the token from the database and enter the Authorization token to header and send a post request to validate the user.
But in the browser, how can I reach my previously created token to validate the user again?
I have tried localStorage but, in order to save token to the
localStorage, I need to take it from the database, but you can't
change localStorage in the backend.
I have tried cookies with http-only flag, but then how can I reach
the token from the front-end, since http-only, restrains from using javascript
What are my options in order to reach a JWT token from the front-end so that I can keep the user still authenticated, even after they close the website and come back later. (not enough to expire the token)
I am very new to how authentication works If I am making a logical mistake please tell me.
You need to send JWT token along with your other data as a response from your login API. Once you receive the response on the front end then just store the JWT Token to the localStorage by "localStorage.setItem("token",response.data.token).
Now you can always reference localStorage.getItem("token") to get the token even user close the browser and comeback again. Please do not forget to clear this localStoage by localStorage.removeItem("token") when user logout.
Also please note to not provide any expiry during the JWT token creation otherwise even you store that locally in localStorage then also it will get expire on server side and give "Forbidden error"
When you authenticate the user for the first time, store the token in the localStorage.
And since localStorage's data never gets deleted on its own, you can listen to the event of DOMContentLoaded where you can retrieve the token from the localStorage and authenticate the user with it, when the page is revisited.
You can read more about localStorage here
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 have a Koa based Node.js backend for my personal/hobby application.
I implemented session handling with JWT tokens. The client (AngularJS) gets the token after a successful login and stores the token somewhere (currently in sessionStorage but for the purposes of this question it shouldn't matter).
I have two questions:
When I need to update the user record which the JWT represents, say, the user turned on Two-factor authentication (2FA) so I asked him to provide his phone number and I'd like to set this phone number in the user's record. Currently, after a successful verification on the phone number I call my backend to update the user record and I create a new JWT token with the updated user record (I exclude sensitive information from the JWT token like the hashed password, but I'd like to include the phone number for client side usage). Is it okay to create a new token when some of the credentials change and update the existing client side token with this new token? Should I never-ever create another token, only to create the one and only upon successful authentication? How do I then update the payload in the token?
How should I handle expired JWT tokens? In my mind I have 3 (possible) scenarios:
2.1. The JWT is set to short living, say 15 minutes. If the backend server replies with a 401 Unauthenticated 'Invalid token' (I guess this is the default behavior of koa-jwt) then I automatically log-out my client and require re-authentication. But I also set up a complementary middleware, which is the last in the chain on the backend to re-create the token with a refreshed expiry and the client would also replace the existing token with the refreshed one. So if the user is active and uses the application every protected API call, in case of success, would create a new token to replace the old token.
2.2. The JWT is set long-living, say 1 week, and if it expires I opt-in re-authentication from the client.
2.3. Copy https://www.rfc-editor.org/rfc/rfc6749#section-1.5. Here when creating the JWT token after a successful authentication we send an access_token as well as a refresh_token. When the access_token is expired and the server responds with HTTP 401 'invalid token' (koa-jwt default) then the client sends the refresh_token to the backend to require a new access_token (and optionally a new refresh_token). In this case I don't fully understand how the refresh_token is verified against the old access_token to provide a new token? Or why do we need to have a refresh_token?
Any generic advice on the upper topics (JWT updates and JWT expiration) would be helpful.
Starting from the bottom, I would ignore refresh tokens as I don't think they will help you here. They are generally aimed at other scenarios where the client application can provide storage more secure than the user browser -- think native mobile applications or server-side web applications.
Refresh Tokens are long-lived. This means when a client gets one from a server, this token must be stored securely to keep it from being used by potential attackers, for this reason it is not safe to store them in the browser.
(emphasis is mine; source refresh tokens)
This means that option 2.3 is basically the same as 2.2, which is not a bad option. It's not uncommon to have web applications with long session duration. If your application is not highly sensitive it's acceptable to use long session to improve user experience. For example, Django uses a default of two weeks for the age of its session cookie. See SESSION_COOKIE_AGE.
The remaining option (2.1), is usually referred as sliding session. The session timeout is short, but as long as the user keeps using the application within that interval the session gets automatically renewed. This is possibly the most common approach, or at least the one I used most time, so I'm biased. The only thing I would note is that sliding session are usually implemented with opaque session identifiers stored client-side as cookies and then with the actual session data stored on the server.
Your approach is a bit different because you have a stateless JWT token (it contains actual user data) stored on browser local storage. Like you said, in order to update the token you'll have to generate a new one, because you'll have to generate a new signature.
The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn’t changed in the way.
(emphasis is mine; source JSON web tokens)
Having said all that, I would consider the following:
Ask yourself if you really need JWT's or if regular session identifiers stored as cookies (HTTP Only) would simplify your logic.
If JWT's are a requirement, for example, you have another API that will also accept these tokens as authentications, then I would consider option 2.1 or 2.2 as refresh tokens for a browser-based application are not recommended.
Having said that, you should also consider that JWT's are not huge, but they will still be an overhead if you decide to be automatically renewing. You may mitigate this a little by choosing a session duration of 20 minutes and only perform automatic renewal after half the session has elapsed.
Another point is that a vulnerability like XSS in your application will expose the access token to an attacker as the injected scripts would be able to read from localStorage/sessionStorage, this can be another point in favor of HTTP only session cookie storage.
I would like to answer your second question before I can get on to the first one.
Basically the third option which you have mentioned is the best way to renew your access tokens. Access token should be short living(~5mins) and refresh token has longer life. When your access token gets expired, send your refresh token to the backend and get a new access token. So your response should be something like this:
{
"token_type":"bearer",
"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s",
"expires_in":10,
"refresh_token":"7fd15938c823cf58e78019bea2af142f9449696b"
}
So the idea is to seperate your application into Authorization Server (which generates access token / refresh token) & Resource Server (validate access token and access the resources ). You can maintain a schema to validate the refresh token against the access token in Authorization Server. Please refer to the schema section mentioned in this link which might give you some idea. Oauth2. You can modify the schema according to your need. You need not send your refresh token along with your access token for each request call. Refresh token can only be sent to Authorization server for generating new access token. How to generate refresh tokens? If I am using Java, I would use UUID.randomUUID() to generate a unique refresh token.
Now to answer your first question, if you want to update your JWT payload based on your updated user records, then you can use the same refresh token to generate a new access token with the updated payload. The logic remains same because if phone number exists in the user record it gets added to the payload and if not, it will be null in the payload.
The main advantage of using Refresh token is that the Access Tokens can be renewed at any time using Refresh Tokens
I'm setting up an HTML5 and JavaScript web application to consume Azure Mobile Services tables using the JavaScript client library. I've managed to get authentication setup successfully with the MicrosoftAccount identity provider. On load, my application checks if the user is already logged in, or if we have a token and username stored locally. If true, I hide the login button, and display the logout button, and proceed to load application data.
My problem is that when a token that is stored locally expires, my application still thinks the user is logged in. Therefore when I request table data, I get a 401 Unauthorized HTTP response.
Is there a graceful pattern to renew an expired token without burdening the user with relogging in every time their token expires?
You will need to log the user in every time, unfortunately. The token must have a lifetime associated with it. On some client platforms, you can get much longer lifetimes via single-sign flows, but these are generally not available for HTML. The common pattern is to, upon receiving the 401, retrigger your login code. Here is a blog post showing the approach for the Mobile Services Managed SDK. The same concepts should apply for JS.