I have a spring boot rest api with jwt authentication. The problem is i cannot get rid of default 403 Access Denied rest response which looks like this:
{
"timestamp": 1516206966541,
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/api/items/2"
}
I created custom AccessDeniedHandler:
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest req,
HttpServletResponse res,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
ObjectMapper mapper = new ObjectMapper();
res.setContentType("application/json;charset=UTF-8");
res.setStatus(403);
res.getWriter().write(mapper.writeValueAsString(new JsonResponse()
.add("timestamp", System.currentTimeMillis())
.add("status", 403)
.add("message", "Access denied")));
}
}
and added it to WebConfig class
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
public WebSecurity(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, REGISTER_URL).permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler())
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager(), tokenProvider()))
.addFilter(new JWTAuthorizationFilter(authenticationManager(), tokenProvider()));
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
public TokenProvider tokenProvider(){
return new TokenProvider();
}
@Bean
public AccessDeniedHandler accessDeniedHandler(){
return new CustomAccessDeniedHandler();
}
}
Despite this i'm still getting the default Access Denied response. When debugging i realized that the handle
method from custom handler isn't even called. What is the case here?
I have the same problem & tried to resolve as per the right answer, but it doesn't solve the issue. The best way to handle this is to implement custom access denied handler. AuthenticationEntryPoint implementation is best to handle 401, UNAUTHORIZED access and AccessDeniedHandler implementation is there for 403, FORBIDDEN access.
Override AccessDeniedHandler's method in your implementation class as:
And add this custom access denied handler in your security config like this:
I think i resolved the problem. Instead of creating an implementation of AccessDeniedHandler i had to create a custom AuthenticationEntryPoint and set it in exception handling.
WebConfig now looks like this:
and the CustomAuthenticationEntryPoint:
Now everything works as i wanted.
According to this:
http://www.baeldung.com/spring-security-custom-access-denied-page
You also needed to add:
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
guessing that goes in "configure".
Here is a minimal security configuration that demonstrates a custom
AccessDeniedHandler
gets called on access denied (403) scenarios:Steps to reproduce:
user/password
http://localhost:8080/user/index
- access grantedhttp://localhost:8080/admin/index
- access denied and customAccessDeniedHandler
gets calledTry this
And make this configuration class for view page