Call a secure Rest api from spring boot - spring

I have a spring boot application and i need to call a secure external api to retrieve data.
on below the steps I followed:
I generate the token with the username and password
I keep the token in a temporary variable
I use it on each resttemplate call
headers.add("Authorization", "Bearer " + token);
My questions are:
What is the best way to keep the generated token and use it for each connected user ?
Can we configure spring security to manage the call to the external api ?

As I figured, you want proxy a secure-rest-api and response to your own users.
But the secure-api needs authentication and you want to have a specific jwt per user.
You have two approaches to implement:
1- Use an in-memory token storage like Redis, with persistence mode enabled to be reliable and scalable. Follow these steps: [for each user check if the token is already generated and stored in storage] -> [If yes fetch and assign it to header of restTemplate request] -> [If not fetch the token from secure-api and store it and move to restart from first step]
Hint: you can identify each of your users by session or oauth]
2- Previous solution is not the best practice because you should have in-memory storage and it will be your bottle neck. (you should cluster it and verticaly increase the resources).
So the next solution is to store the tokens at client side for each user. you should follow these steps: [If your own user sent the token to your rest api, you should catch it, verify it, and forward to secure-api using restTemplate] -> [Otherwise it means that you havn't already sent the token to user, so you should fetch the token RESIGN it and respond to user]
Hint: you should resign the jwt-token fetched from secure-api by your security algorithm, because the token is sent to client and contents of token may have some vulnerabilities
The second solution is to forget about In-Memory db and it's IO/bound added letancy. But it adds a cpu-bound processs on your jwt tokens. Each user stores it's token in browser and you can use the token to identify your users instead of using sessions or something like that. So I highly recommend you to read about signing algorithms like sha(256,512,1024) or some other types of algs.

Related

Custom JWT token in springboot microservices

We have an application that loads information(user specific) from the external system upon successful authentication, to avoid round trips to the external system for each api call, we are planning create a custom JWT token with user specific information for the first time user authenticated, then the token is send to user in each response header using http interceptor and in the front-end we are including the custom token in every request along with authorization token. Is this correct approach? Do you have any alternative suggestions?
I have looked into other distributed caching techniques like redis but not so appealing for a small usecase. Our payload length does not exceed 4 to 5K hence inclined towards the JWT option
it is ok to include user information that allows you to handle the user authorization inside the access token. Just beware of the privacy implication and perhaps not include personal information like social security number or date-of-birth or other identifiable information.
Also, make sure the token size does not get to big. The other option is to lookup and cache the user information in the API's when it receives a new access token.
Some systems including ASP.NET Core do store the token inside the session cookie in an encrypted form, so that the end user can't see or access the stored tokens.
If you are developing a SPA application, the using the BFF pattern is one approach.

How to access a secured API in the frontend?

There is a lot of good content on the internet that explains how to secure a Spring API with Keycloak: Create a Client that represents the API Service in Keycloak and use a link like the one below to get the access and refresh token:
<Domain>/auth/realms/<realm>/protocol/openid-connect/auth/{some parameters}
This yields both tokens. So far so good.
Now, however, I am not sure how the flow for the frontend accessing the API should look like.
Should the frontend directly access this endpoint and, therefore, obtain the access and refresh token? That would mean that the API can only have the access-type public because there is no way to store the client (the API) secret securely.
Or should there be a third server that somehow stores the refresh token for each user, that the user can call if his access token is no longer valid. This server would then use the client's refresh token (and the client secret that could be stored securely, since it would be in the backend) to get a new access token from Keycloak and would forward it to the user.
I guess the main question that I am asking is, whether the client/user should get the refresh token.
If one needs to implement a logic according to the second option, I would be interested in a link or description of how something like this can be done in Spring.
I think, in either case you need to use the Authorization Code Flow. The implicit flow, which was recommended for SPAs (frontends without a backend server) in former versions of OAuth2 must not be used anymore.
The best option is to have a backend server, so the user retrieves the auth code via redirection and the backend server exchanges this auth code with the access and refresh tokens (and keep them without forwarding them to the frontend).
If there is no backend in place and your frontend needs to retrieve and hold the tokens directly, I would recommend to use the Authorization Code Flow with a public client and the PKCE extension (which - put simply - ensures that the entity asking for the auth code is the same as the entity asking for the tokens and that the auth code was not stolen and used by a foreign entity). There are several sources with more detailed explanations, which might help you, for example: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce
Hope this helps you with your architectural considerations.

JWT with JDBC token store vs JSESSION ID

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.

Session vs JWT Token in nodejs with large payload

I am working on a nodejs project and coming from a PHP background. I am pretty impressed with frontend and backend development separately and communicating with API calls.
# Issue: I need to authenticate the user and store some data of the user (which is always needed in the server), this user data which results in increased jwt payload size and jwt token will be large.
So I used JWT token mechanism, generated a token after successful login and send it to the client, then the client add that token as the header with every API call - then verifies token in server and gets the decoded payload data.
This is the process. But I have some user data that is needed always in nodejs, so the JWT payload size increases and JWT token size also large size. So client always sends with large size token everytime.
I was using sessions in php to maintain user data.
If I use sessions for authentication, it will be stateful, right?
# Doubts:
Is there any way to maintain the logged in user data in the server?
How to reduce the length of JWT token if I use large payload?
Updated:
Also if I am using sessions, it makes use of the database to store sessions So a DB call is needed.
What if I use small payload token (eg: userid) for authentication and after authentication make a DB call with userid to get details?
In both methods DB call is needed? Which method seems better?
Using sessions would introduce server state, but lets you keep user data and session data on the server. Only the session id has to be shared with the client.
You cannot reduce the length of the JWT token. Larger payload means a larger token. In theory you could use some kind of compression, but that would be a very high technical overhead and probably not worth it.
Saving sessions on the server would solve your problems.
It also gives the server complete control over the sessions. When the user logs out, the server can delete the session. When the client deletes his JWT token, you cannot be absolutely sure that the user is logged out. The token itself is still valid.
Using JWT as a sessions container is generally a bad idea. This just introduces several security issues, that you have to handle yourself. You have to make sure that 3rd party JavaScript does not read the token, just to name one issue. There are many blog posts, which explain these issues in detail (search for "Stop using JWT for sessions"), but I can only advise not to use JWT for sessions. Sessions are not a bad thing!

Blocking specific user JWT tokens?

Say a user logged in multiple times from different devices, and then they decide they want to logout of device a, we have no way of deleting the JWT which was provided to that device right?
Here is what I've implemented, I'm not sure if this is how other sites do it or if it's a decent way of doing it.
User logs in
I create a redis session token, which has the userId + device name associated to it
I store this redis token as the subject of the JWT
I pass back the JWT.
Now that the user has a JWT, they can now access secured api endpoints. Lets say the user wanted to remove this session, here is what I've done.
User fetches * redis session tokens for the particular userId (of course they need a valid jwt to fetch this data)
They choose the redis session token which they want to destroy.
They send that token to a /destroy/{token} endpoint
The jwt which uses that has that token as the subject will not work anymore.
Doing it this way means on each request, I'll have to decompile the jwt, grab the redis token, and see if it still exists. I guess this isn't expensive todo at all using redis, or any other in memory DB.
Is this a solid/efficient way of doing this? Are there any better/easier ways of doing this?
While implementing JWT authentication/authorization in several apps I also had this same question and reached the same solution if not a very similar one:
In my case, I would store the JWT + UserID + DeviceName in the database, and then I would have an HTTP Request
DELETE /logout/DeviceName with a header Authorization: JWTGoesHere.
This gives me two benefits:
I can now logout a user from any device using a valid JWT (it does not need to be exactly the same JWT, it only needs to be a JWT for that user).
Makes possible the implementation of "Logout all sessions except this one".
In terms of speed, the applications we've developed receive hundreds of requests per second.
More than 90% of these requests need to be authorized, which means checking that the JWT is syntactically valid, checking existence against the database and last but not least check if it's expired.
All these checks (using Redis as the database) take less than 10ms.
Bottom line is: Benchmark it, and if it doesn't take really long then it doesn't need any optimization.
Hope it helps!

Resources