Spring security - creating 403 Access denied custom response
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:
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.getWriter().write("Access Denied... Forbidden");
}
And add this custom access denied handler in your security config like this:
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint())
.accessDeniedHandler(accessDeniedHandler())
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:
@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.STATELESS)
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, REGISTER_URL).permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
.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 AuthenticationEntryPoint authenticationEntryPoint(){
return new CustomAuthenticationEntryPoint();
}
}
and the CustomAuthenticationEntryPoint:
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest req, HttpServletResponse res, AuthenticationException authException) throws IOException, ServletException {
res.setContentType("application/json;charset=UTF-8");
res.setStatus(403);
res.getWriter().write(JsonBuilder //my util class for creating json strings
.put("timestamp", DateGenerator.getDate())
.put("status", 403)
.put("message", "Access denied")
.build());
}
}
Now everything works as i wanted.