2

My idea or my wish was to refresh the JWTToken on every successful request. At the moment the user gets back to the login mask if his token is expired and that should stay that way.

But in my opinion and as I have seen it in some applications it is nice to get a fresh token or at least the full length of time back after a sucessful request. Like you have a expiration time of 10 minutes and you send a request with a remaining token time of 3 minutes which succeeds, then the token should be valid for the next 10 minutes again.

How to it the best way? Currently I'm using the standard Spring Security libraries to validate, create and so on. I literally followed this guide https://bezkoder.com/spring-boot-jwt-authentication/.

I thought I could refresh the token with literally the same method:

public String generateJwtToken(Authentication authentication) {

    UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();

    return Jwts.builder().setSubject((userPrincipal.getUsername())).setIssuedAt(new Date())
            .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
            .signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
}

But to do so I need the authentication object which I can't create because I don't have a username and password given like here:

    Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
            loginRequest.getUsername().toLowerCase(), loginRequest.getPassword()));

    SecurityContextHolder.getContext().setAuthentication(authentication);
    String jwt = jwtUtil.generateJwtToken(authentication);+

Is there something instead of new UsernamePasswordAuthenticationToken() that I could use for that?

1 Answer 1

3

So on initial login you create and use

authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
            loginRequest.getUsername().toLowerCase(), loginRequest.getPassword()));

but after that you use your jwt in header of each request and check it for validity. So you would have something like

if (!jwtProvider.isTokenExpired(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) {
                UsernamePasswordAuthenticationToken usernameAndPasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(jwtProvider.extractUsername(jwt),
                        null, jwtProvider.extractUserAuthorities(jwt));
                usernameAndPasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernameAndPasswordAuthenticationToken);
            }

as you can see you can create UsernamePasswordAuthenticationToken with just username and authorities(if needed), because you already validated user with jwt, no need for his password again.

I guess after this you can use username and whatever you need from previous token, extract it and put it in new token to be generated.

I also suggest that you refactor your generateJwtToken to use UserDetails as parameter or even just username, cause you don't need whole Authentication. You are definitely not using password in token generation and as I can see you are not using authorities either.

P.S. Thx for the question, I was wondering how to do auto refresh of token on each request :*

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your answer but I'm not able to implement your advice. My second method in my answer is my signin method. I don't know where is should place your code and I have no method for expiration and neither for extractUserAuthorities. And I don't know how to implement the last one.
Take a look at this tutorial. medium.com/innoventes/spring-boot-with-jwt-7970e5be4540 Your second method is in some SignUpController probably, when user sends his credentials and you give him back jwt for all others requests user's gonna use. Then you have to create security filter for all other requests to check if they have jwt and if it is valid. IF it is valid, you can extract data from it, and use that to regenerate new token, and send it in response. @CptDayDreamer
does that mean the user gets a new token after every request if I understand this right? This would be bad with many users and generally not a good attempt in my opinion.
Isn't that what you asked for "Spring Boot refresh JWT Token on every request as long it's valid"
@CptDayDreamer Assume there is some administrating SYSTEM (admin page, some private part of the system or site) and 1 hour or more could not be a good idea. Additionally, this - user works 8 hours with this system, and every hour he needs to repeat typing their login+password, BCS JWT expired. Day by day ... Then renewing an expiration in the JWT is not such a stupid idea? And as was written above it could be done not for each request but only when the time and expiration is closer, assume 3 minutes, or 5 ..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.