Is there any way to throw AuthenticationException into AuthenticationEntryPoint?

Viewed 128

I have implemented JWT authorization system. It works fine, but I should notify client that their token is expired.

I configured my Spring Security:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
UserDetailsServiceImpl userDetailsService;

@Autowired
private JwtAuthEntryPoint unauthorizedHandler;

@Bean
public JwtAuthTokenFilter authenticationJwtTokenFilter() {
    return new JwtAuthTokenFilter();
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
    authenticationManagerBuilder
            .userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
}

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/login", "/signup", "/email-exist", "/username-exist", "/refresh-tokens", "/public/**").permitAll()
            .antMatchers("/api/trainer/default-config").hasRole(Role.ROLE_ADMIN.name().replace("ROLE_",""))
            .anyRequest().authenticated()
            .and()
            .exceptionHandling().authenticationEntryPoint(unauthorizedHandler);


    http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    http.addFilterAt(this.corsFilter(), CorsFilter.class);
}
}

So if I catch TokenExpiredException or SignatureVerificationException in my AuthFilter, I want notify clients with messages: Token is expired or Token is invalid

@Slf4j
public class JwtAuthTokenFilter extends OncePerRequestFilter {

@Autowired
private TokenProvider tokenProvider;

@Autowired
UserDetailsServiceImpl userDetailsService;

@Autowired
JwtAuthEntryPoint authenticationEntryPoint;

@Override
protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response,
                                FilterChain filterChain)
                                        throws ServletException, IOException {
    try {

        String actionToken = tokenProvider.getToken(request);
        if (actionToken !=null) {
            String username = tokenProvider.getUserNameFromJwtToken(actionToken);
            List<GrantedAuthority> authorities = tokenProvider.getAuthoritiesFromJwtToken(actionToken);

            UsernamePasswordAuthenticationToken authentication
                    = new UsernamePasswordAuthenticationToken(userDetailsService.loadUserByUsername(username), null, authorities);
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    } catch (IllegalArgumentException e) {
        logger.error("an error occured during getting username from token", e);
    } catch (TokenExpiredException e) {
        logger.warn("the token is expired and not valid anymore", e);
    } catch(SignatureVerificationException e){
        logger.error("Someone change the token!");
    } catch (Exception e) {
        log.error("Can NOT set user authentication -> Message: {}", e);
    }

    filterChain.doFilter(request, response);
}
}

Also I have an exceptionHandler for Authentication

@Component
@Slf4j
public class JwtAuthEntryPoint implements AuthenticationEntryPoint {

@Override
public void commence(HttpServletRequest request,
                     HttpServletResponse response,
                     AuthenticationException e) 
                             throws IOException, ServletException {

    log.error(e.getMessage());
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
}
}

If token is expired or invalid I always send message Full authentication is required to access this resource. But I must notify my client about expired tokens.

I tried to call commence method inside my JwtAuthTokenFilter but it doesn't work :

} catch (TokenExpiredException e) {
     authenticationEntryPoint.commence(request, response, new CredentialsExpiredException(e.getMessage()));
     logger.warn("the token is expired and not valid anymore", e);
} catch(SignatureVerificationException e){
     authenticationEntryPoint.commence(request, response, new BadCredentialsException(e.getMessage()));
     logger.error("Someone change the token!");
}

So is there any way to pass through my exceptions with messages about tokens into JwtAuthEntryPoint?

0 Answers
Related