If I'm implementing an authentication layer in my app using a mix of JWT and Redis to store session data, do I need to include an expiring in the JWT token itself?
For example, when you login to the app, a session id is generated and added to the redis database with an expiry of 3 days. Then that session id (along with username) is used to create the JWT payload. On all auth requests, I make sure the session id from the token exists in the redis database. If it doesn't, the session has expired and I issue a new token.
Are there security issues with this implementation?
No security issues but one may argue that by including an expiry field in the JWT, the Redis layer can be made obsolete. In principle the JWT allows the application to become stateless. If your application is going to store all of its session data in Redis anyhow (because the JWT would be too large for that) one may argue that the benefit of using a JWT over a plain random session identifier is gone.
Bottom line: the exp field in a JWT is optional and you are free to implement another mechanism to achieve the same.
It depends on how you implement your authentication/authorization layer.
Your authentication/authorization flow is stateful, thus expiration is very coupled with the session. I would include expiration just to let consumers of the whole JWT know when is going to expire and take actions based on this information.
There's also the stateless approach where there's no session identifier and there's no server storing information, but the JWT is self-descriptive, containing expiration and other data as claims. Since the consumer of the JWT relies in the JWT producer, and communications are secured by using a transport-level security approach like HTTPS/SSL, there's no need to maintain state but the state is the JWT itself.
One of most well-known and standarized autentication/authorization flows is OAuth2. I would say that you should build your security layer on top of industry standards. This is good because you avoid a lot of R&D, security holes and time.
Related
We are trying to implement an application where UI is in angular and backend is in Spring boot.
We need to implement openId and oauth2 in our application.
Backend api's needs to be more secure.
I am just confusing which oauth flow to be used either authorization grant flow and password grant flow.
Can any one suggest me which one need to use in this scenario and why?
Storing tokens in the front end is not recommended. It also distributes token handling logic across FE and BE because BE will have to validate tokens on each request anyway.
Therefore to avoid handling and refreshing tokens in the frontend and to simplify the overall architecture, you can implement authorization code flow in Spring Boot. This will also reduce the risk of XSS exposure in the FE.
You could implement a dedicated endpoint that initiates the flow and receives code from identity server. It then exchanges this code for id token and stores it. Then it creates an HttpOnly, strict SameOrigin session cookie for the front end. From that point onwards all calls to the API inside your Spring Boot will automatically carry this cookie without any additional code on the FE.
To eliminate token storage on the BE, you could even put token inside the cookie. However, the token may be quite large and may need to be broken into chunks. This would not affect FE in any way.
You will need to check token expiry on each API call inside the BE and refresh token in the backend as well. This will keep user session seamless. If token can not be refreshed due to revocation or refresh token expiry, the API would have to return 401 and the FE would need to initiate re-login.
We decided to switch from Basic-Auth to JWT because of the session-ids that were stored in the memory and which leads sometimes to over-memory consumption in shoot-down of our Spring-Boot server that serves an Android mobile app like Twitter.
But we have some questions about JWT for our mobile use-case:
How long should an access token lives ?
How long should the refresh token lives ?
How to logout a User by invalidating his access-token and refresh token ? (For the logout we already delete the tokens on the mobile app side, but what if the tokens have being stolen by somebody and are still valid ?)
I will try to answer your queries
How long should an access token live?
You can easily configure expiry time so it depends on your requirement.
In general, try to keep it short.
How long should the refresh token live?
Above goes for refresh token with a condition that refresh token generally lives longer than access token for obvious reasons.
How to logout a User by invalidating his access-token and refresh token?
This part can be a little tricky.
You cannot manually expire a token after it has been created. So, you cannot log out with JWT on the server-side, as you do with sessions.
Can implement a few options like
When a user performs logout action or compromised. Have a blacklist which stores invalid tokens until their initial expiry date. You will need to lookup DB for every request but storage should be less as you will be storing tokens that were between logout & expiry time. You can make the blacklist efficient by keeping it in memory instead of DB.
Store Client IP Address in the claims objects JWT. When validating the token you can check with this client's IP address if it is the same source or not. You can refine it based on need like use User-Agent along with Client IP.
Worst of all reset user credentials or JWT token components to generate a new one which automatically invalidates all existing ones.
Adding a few links for more in-depth detail
Invalidate JWT Token
Destroy JWT Token
I mean it looks more like you should just be using sessions.
JWTs are not a simple replacement. They have a specific function and for some reason they have become embedded as some sort of automatic go to for any auth system.
From what you have described (the lifting of a basic auth to a more secure and modern auth system) you should be using sessions.
Good ol' Cookie sessions.
I'd go in to why more but to sum up:
A) You can control the session without odd stick on "banlist" tables and extra architecture for the JWTs for users that are banned/logged out for a system that doesn't actually need these if you just used traditional cookie based sessions.
B) They are tried and tested and the browser will keep them safe! Session cookies can be made "secure" and "http-only". There are many odd places people put JWTs including the local/session storage of a browser just waiting for a naughty js injected advert to suck them up. JWTs,just like SessionIDs, should
be in an Http-Only, Secure and Same-Site strict Cookie.
So you may as well just use a session ID and get on with life without strange front end state management when the browser is quite happy and doing that securely for you when using a Session Cookie.
C) Traditional sessions are easy to implement. Harder to understand how/why they work with all the SameSite/HttpOnly/CORS/Secure parts going on...but to implement when once understood is 99x easier and require less code when there is the Spring Framework already doing that 99% for you.
I mean sure it isn't hard to write your own JWTAuthTokenAuthFilter and implement a JWTAuthenticationProvider and a JWTCreationService and a `JWTAutoRefreshFilter...and whatever else you dream of...but why bother if you just need a session. Spring does it in like 20 lines of well tested code.
To sum up:
I mean of course properly implemented JWTs are secure...it is just maybe they are not always the best fit tool for a job.
Have a read of:
Stop Using JWTs for Sessions
Of course JWTs have a use. They are for letting a 3rd party know "yes, this is someone I know" before the client hits their API end points. Or for say having one of your servers talk to another of yours...or having client's servers talk to yours or even your servers talk to another companies:
JWT Auth - Best Practices
I have implemented a spring boot application which does authentication and authorization using Spring OAuth2.
I am using JDBC token store to main the token issued to the client for performing Custom claim verification and some other user status verification during application run-time.
The question is, since i had used traditional JSESSIONID with CSRF token, i cannot find any advantage with the new OAuth standards because after login i would store the user details in the session and retrieve it whenever needed similarly for OAuth i store the User details in the JWT token itself and decode the token every time to get the user information, also i need to hit the database anyway for custom claim verification such as JTI verification .
Everyone says JWT is for stateless application but with JDBC token store i'm holding all the token that is issued to each client. Also there is an additional overhead to purge the expired token which will be done automatically with Session. Also i'm using refresh token as the way to implement session timeout.
Therefore can anyone explain me, when should i use JSESSIONID and when to use JWT ? My application is running on AWS architecture.
From my experience, cookie-based authentication sufficiently complicates scaling and load-balancing. If you have authenticated via the first service replica, your cookie will be not appliable to another replica, cause all sessions are stored in memory. So, if you want to scale your service in the future, session-based authentication can make things much more complex.
I am implementing a Spring Boot application, in which the methods are calling third party REST endpoints. This REST API is accessible after OAuth2 authentication. That is why I retrieve tokens from the third party (various users can use my application and respectfully call the REST endpoints) and use these tokens for authorization in order to call the endpoints. But in the current implementation this happens before every call. That is why I would like to ask for advice how to cache these tokens and whether this is a good practice at all? Also the tokens expire in 1 hour.
You should not cache access tokens on the backend of a web application ,if you can store them client side and send them with each request.
In case you don't have possibility to store it at client side (possible case your API is talking to some message client like USSD,SMS etc),It will be expensive to get an OAuth access token, because it requires an HTTP request to the token endpoint. This case is a good example where you can cache tokens whenever possible.
You can make use of REDIS if you have multiple instances.
REMEMBER : Tokens are sensitive data, because they grant access to a user's resources. (Moreover, unlike a user's password, you can't just store a hash of the token.) Therefore, it's critical to protect tokens from being compromised. You can make use of encryption.Do check below links for more details :
https://auth0.com/docs/best-practices/token-best-practices.
https://github.com/auth0/express-openid-connect/blob/master/EXAMPLES.md#5-obtaining-and-storing-access-tokens-to-call-external-apis
https://learn.microsoft.com/en-us/azure/architecture/multitenant-identity/token-cache
As per Auth0 Token Best Practices
Store and reuse.
Reduce unnecessary roundtrips that extend your application's attack surface, and optimize plan token limits (where applicable) by storing access tokens obtained from the authorization server. Rather than requesting a new token, use the stored token during future calls until it expires. How you store tokens will depend on the characteristics of your application: typical solutions include databases (for apps that need to perform API calls regardless of the presence of a session) and HTTP sessions (for apps that have an activity window limited to an interactive session). For an example of server-side storage and token reuse, see Obtaining and Storing Access Tokens to Call External APIs in our Github repo
what is the best practices to handling JWT in server side
1) I saw lots of code.they are maintained in database .is it good practice?
2) can we maintain as session value?
How we should implement JWT in server side in spring boot
No. The whole point of a JWT is to contain everything in the JWT itself to be able to identify the user. There is no reason to store a JWT at server-side (unless you want to somehow maintain a list of blacklisted/revoked JWTs, but even then, an ID or something inside the JWT should be sufficient).
No. The whole point of a JWT is to contain everything in the JWT itself to be able to identify the user. And this is precisely what allows avoiding sessions, and to be completely stateless: you receive the JWT, and if you know the secret key used to sign it, you can know who the user is, and be sure the JWT hasn't been counterfeited.
I think you need to understand what a JWT is, and how they work. Why do you want to store JWTs?