how to separate password recovery from jwt authentication

155 Views Asked by At

In the process of implementing password recovery feature I tried to test the basic behavior before moving forward with the implementation but every time I try submit a HTTP request I get the error message :

JWT expired at 2023-07-19T13:31:51Z. Current time: 2023-07-23T10:31:30Z, a difference of 334779299 milliseconds. Allowed clock skew: 0 milliseconds.

I tried to add the password recovery endpoint as one that does not require any jwt authentication in the FilterChain method but still the same error occurs.

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http
                .csrf(csrf -> csrf.disable())
                .authorizeRequests(authorize -> authorize
                        .requestMatchers("/api/v1/auth/**").permitAll()
                        .requestMatchers("/user/**").permitAll()
                        .anyRequest().authenticated()
                )
                .sessionManagement(sessionManagement -> sessionManagement
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

and here's the the method for processing the email from the HTTP request:

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class ForgotPasswordController {

    @PostMapping("/password_recovery")
    public String processEmail(@RequestParam("email") String email) {

        String generatedToken = UUID.randomUUID().toString();
        System.out.println("Email: " + email);
        System.out.println("Token: " + generatedToken);
        return "Your password recovery token: " + generatedToken;
    }
}
1

There are 1 best solutions below

1
Ajaj Ali On

When the user hits an endpoint with expired JWT,the user gets 401 unauthorized as response from spring server. You can create two filters for that in Security Configurer. One tokenValidationFilter that will stand right before at addFilterBefore

And another filter,in your case it is jwtAuthFilter

  http.addFilterBefore(tokenValidationFilter, UsernamePasswordAuthenticationFilter.class);

  http.addFilterAfter(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

when user hits the endpoint with expired token and it is caught by tokenValidationFilter filter.

You can extract claims from that expired token and generate new token with new expiration time with same old claims.

You can get tons of libraries to decode your JWT Token.

For example you can extract user object from claims that was present in old token.

you can return that token as payload with 401 status.

for example in your tokenValidationFilter filter

response.getWriter().write(new ObjectMapper().writeValueAsString(Map.of("token", jwtTokenService.createJwtToken(user, false))))

when user interceptor receives unauthorized request with key "token". you can set it in header in your frontend side.

If you understand the flow of authentication,You can figure it out.