Reputation: 75
I have an authentication provider, that throwing my custom exception. This provider validating token on every request to controllers. Exceptions in controllers handling by controller advice, but provider works before controller, so controller advice cant handle exceptions that provider throws. How can i handle exception from provider?
Provider
@Component
@RequiredArgsConstructor
public class BearerTokenAuthenticationProvider implements AuthenticationProvider {
private final Wso2TokenVerificationClient client;
@Override
public Authentication authenticate( Authentication authentication ) {
BearerTokenAuthenticationToken token = (BearerTokenAuthenticationToken) authentication;
Map<String, String> requestBody = new HashMap<>();
requestBody.put( "token", token.getToken() );
Wso2TokenValidationResponse tokenValidationResponse = client.introspectToken( requestBody );
if( !Boolean.parseBoolean( tokenValidationResponse.getActive() ) ) {
throw new AuthenticationException(
"Token not valid", HttpStatus.UNAUTHORIZED
);
}
DecodedJWT jwt = JWT.decode(token.getToken());
UserDetails details = new UserDetails();
details.setId( Long.parseLong(jwt.getClaim( OidcUserClaims.USER_ID ).asString()) );
details.setEmail( jwt.getClaim( OidcUserClaims.EMAIL ).asString() );
token.setDetails( details );
return token;
}
@Override
public boolean supports( Class<?> aClass ) {
return BearerTokenAuthenticationToken.class.equals( aClass );
}
Security Config
@Configuration
@RequiredArgsConstructor
public class CommonWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private final BearerTokenAuthenticationProvider bearerTokenProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().contentSecurityPolicy("script-src 'self'");
http
.csrf().disable()
.authorizeRequests(auth -> auth
.antMatchers("/public/**").not().hasAuthority("ROLE_ANONYMOUS")
)
.and()
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
}
@Override
protected void configure( AuthenticationManagerBuilder auth ) throws Exception {
auth.authenticationProvider( bearerTokenProvider );
}
}
Upvotes: 3
Views: 1743
Reputation: 1
Security exceptions are thrown by authentication filters behind the dispatcherServlet and before invoking the controller methods. You can use the a customized AuthenticationEntryPoint and HandlerExceptionResolver to handle AuthenticationExceptions ,then your exceptionHandler will be able to handle your security exceptions and throw them,
Custom AuthEntryPoint
public class AuthEntryPoint implements AuthenticationEntryPoint {
@Qualifier("handlerExceptionResolver")
@Autowired
private HandlerExceptionResolver resolver;
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
resolver.resolveException(request, response, null, authException);
}
}
Upvotes: 0
Reputation: 918
I support the accepted answer here but want to highlight key tricky part of it:
I had same structure but instead of throwing my custom exception, I used AuthenticationServiceException and that was simply not working.
To be able to handle exception in your custom AuthenticationEntryPoint
you MUST extend AuthenticationException with your own implementation as it is done in accepted answer.
Upvotes: 2
Reputation: 1248
You can add an authenticationEntryPoint
to handle custom exception.
@Configuration
@RequiredArgsConstructor
static class CommonWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private final BearerTokenAuthenticationProvider bearerTokenProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.contentSecurityPolicy("script-src 'self'");
http
.csrf().disable()
.authorizeRequests(auth -> auth
.antMatchers("/public/**").not().hasAuthority("ROLE_ANONYMOUS")
)
.oauth2ResourceServer(c -> c.jwt()
.and()
.authenticationEntryPoint((request, response, authException) -> {
//handle CustomAuthenticationException
}
)
);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(bearerTokenProvider);
}
}
public class CustomAuthenticationException extends AuthenticationException {
HttpStatus status;
public CustomAuthenticationException(String message, HttpStatus status) {
super(message);
this.status = status;
}
}
Upvotes: 4