I'm implementing an Auth server using Spring Security Oauth2. What I noticed is that when spring security saves the access token (using JdbcTokenStore) , the OAuth2AccessToken is serialized as which means the access token is self is saved as plain text. I have a couple questions about this.
1.) The token is never actually retrieved using the access token value. It is retrieved using a token id. Why is that?
2.) Is it Ok to hash this token since it is never retrieved using it's value?
3.) Do we actually need to generate the token id? Can we pass an extra information from the resource server to the authentication server to retrieve the token and validate it against the hash?
By default Spring stores the token in plain text. If you make a request to get a token again in the same browser, you will notice that Spring will return the same token as long as it is still valid.
1) This is not entirely correct. On the resource server, the token is read from the header and a PreAuthenticatedAuthenticationToken is created. Through several steps the token value is used to create the OAuth2Authentication. The key is a intermediate step, but only after you have resolved the token to an OAuth2AccessToken (see TokenStore.readAccessToken())
2) Personally I would hash the token before storing it in the database! This does however require you to implement/extend a TokenStore, since you need to override TokenStore.storeAccessToken() to save the hashed value, and TokenStore.readAccessToken() to hash the incoming token and find the hash in the database.
3) Typically the authentication server and resource server read the same database, and both ends up with a OAuth2Authentication identifying the user. If you want to hash, you just need to implement the store/read methods as described above.
I have implemented a solution like this with Spring Oauth2 1½ ago, so hashing tokens and refresh tokens is diffidently possible. In our case we ended up not using the resource server implementation from Spring Oauth2, because we get 20K requests every minute, and we wanted to delay resolving the token until the request has been validated, and use several layers of caching to avoid hitting the database on every request.
Related
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.
please take this doubt away.
I have a Spring Boot application with spring security using JWT.
One question I always had is: How does Spring store the generated tokens?
Looking at the manager of my tomcat, I saw that this application has some open sessions, but it works exclusively with JWT. There is no point in it where I request to open a session.
So can I assume that Spring creates sessions to store the generated tokens?
you authenticate and then get issued a token from an issuer.
When this token is presented to a spring server, the resource server needs to do multiple validations before it will let you use the api.
A JWT is not encrypted, it is encoded, which means, everyone can see and read its contents. But it is also signed, so that you can not tamper with its contents without breaking the signage.
So the first thing a server does is to verify the signature to be sure it hasn't been temepered with. This can be done in multiple ways, one is to take the token and send it to the issuer and basically ask "hello is this token valid?" and the issuer says "YAY" or "NEY".
This generates a lot of extra network traffic if it needs to send jwts back and fourth for validation.
Since the signage of tokens are done with asymmetric encryption, the resource server can periodically (for instance each 30 mins) ask the issuer for the public key so it can verify the tokens itself without constantly needing to ask if they are valid or not.
This key is usually sent in a format called JWK (Json web key) and this key is then used to validate the integrity. If this validation passes it can trust the jwts content, and start checking the validation date, the scopes, and any extra claims in it etc.
And then if the token is valid has not expired, you can for instance choose to construct a UserDetails object from the data in the jwt.
As mentioned in the comments. If using JWTs you have no need for a session.
you should disable session creation.
You can read a lot more about sessions in this article here Spring Security Session
And here you can read about spring security Session Managment
I'm currently planning to use JWT to secure my API, I have read several tutorials, and find that generally, it's using username and password to generate token, while the UserDetail is got and constructed from a database.
Now I have a question, if I cannot get the UserDetail for some reason, can I use some random data, like UUID replacing username, to identify each request?
update:
I feel if I just use the token to distinguish per request, actually it's not so called oauth2, it's just JWT token.
Actually previously our solution is, we generate a token and store it in Redis before each request , then we verify if the token expires in Redis in each request.
As the customers don't need to login to purchase something, we don't have UserDetail info, Now I feel almost no difference between two solutions, and I'm even wondering if the JWT token alone gives better security.
^_^
I am working on a project with PHP and angular. For the user sign in, we're using JWT. Still can't understand why we should use JWT instead of Sessions if each time the user browse a component we need to send the token to server code to check if the user still signed in or not.
Username and password will be sent to server code, where the authentication process will happen, and then generate a token and send it back to angular then save at the local storage.
Any comment on how JWT should be properly used.
EDIT
My question is about the process of checking the JWT when user surf the site and go from component into another.
If you use session for your application... Then while horizontal scaling sharing the session data becomes a burden ....you either need a specialised server .. Jwt are stateless and have no such requirement. It contain following data
Header - information about the signing algorithm, the type of payload (JWT) and so on in JSON format
Signature - well... the signature
Payload - the actual data (or claims if you like) in JSON format
Your JWT already is a proof of your authentication. So you have to send it with each request but you can simplify the authentication logic on server-side.
While on the login you will have to check the credentials you can rely on the JWT's signature and expiryDate. If the signature is still correct the token is valid and you do not have to authenticate anymore.
So regarding your horizontal authentication.
If the called service needs to be authenticated you have to check the JWT for validity on each request (normally works reasonably fast). If there are open api calls you can of course ignore the JWT on server side.
At the end of the day there is no difference to your "session" which will also send some "secret" key which maps your session context. Therefore, it will also be validated.
For some backends you can also use the JWT as your session key to get both worlds involved.
Example:
lets say you have two api roots:
api/secured/*
api/open/*
(Note that the secured and open are only here for demonstrative purposes)
The secured part will contain all the services you want to be authenticated.
The open part can contain insensitive data as well as your login services:
api/open/login -> returns your token
api/open/token/* -> refresh, check re-issue whatever you might need
So now lets say the user accesses your site. You will want to provde an authentication error if he tries to access any api/secured/* URL without a proper JWT.
In this case you can then redirect him to your login and create a token after authenticating him.
Now when he calls an api/secured/* URL your client implementation has to provide the JWT (Cookie, Request header, etc...).
Depending on your framework, language etc. you can now provide an interceptor/filter/handler on server side which will check:
If the JWT is present
if the signature is valid (otherwise the token was faked)
if the JWT is still valid (expiryDate)
Then you can act accordingly.
So to sum up:
There is no need to "authenticate" unless you want to create a new token.
In all other cases it is enough to check the validity of your JWT
Consider we want to use JWT along with refresh tokens in Spring.
We have to use JWTTokenStore, right?
But if JWTTokenStore isn't a real database and doesn't store anything, where and how should we store refresh tokens?
(We prefer to store refresh tokens in database rather than store them in memory)
Refresh tokens are JWTs by default if the access tokens are. To change that you would have to modify the token services (possibly a custom TokenEnhancer would do it, and maybe also a custom TokenStore). Why not go with the default?
I faced the same problem. The explanation for me is that the tokens was set in the cookies.(No sessions on client side). And I don't want that my refresh token be used like an access token. (Modifying the access token cookie with the value of the refresh token)