title: Return custom Spring security message from Rest API
body: <p>I want to create custom error message for Forbidden error. I tried this:</p>
  
  <p><strong><em>Spring Security Configuration:</em></strong></p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  
    @Autowired
    private JwtTokenProvider jwtTokenProvider;
  
    @Override
    protected void configure(HttpSecurity http) throws Exception {
  
      // Disable CSRF (cross site request forgery)
      http.csrf().disable();
  
      // No session will be created or used by spring security
      http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  
      // Entry points
      http.authorizeRequests()//
          .antMatchers("/users/signin").permitAll()//
          .antMatchers("/users/signup").permitAll()//
          .antMatchers("/h2-console/**/**").permitAll()
          // Disallow everything else..
          .anyRequest().authenticated();
  
      // If a user try to access a resource without having enough permissions
      http.exceptionHandling().accessDeniedHandler(accessDeniedHandler());
  
      // Apply JWT
      http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
  
      // Optional, if you want to test the API from a browser
      // http.httpBasic();
    }
  
    @Override
    public void configure(WebSecurity web) throws Exception {
      // Allow swagger to be accessed without authentication
      web.ignoring().antMatchers("/v2/api-docs")//
          .antMatchers("/swagger-resources/**")//
          .antMatchers("/swagger-ui.html")//
          .antMatchers("/configuration/**")//
          .antMatchers("/webjars/**")//
          .antMatchers("/public")
  
          // Un-secure H2 Database (for testing purposes, H2 console shouldn't be unprotected in production)
          .and()
          .ignoring()
          .antMatchers("/h2-console/**/**");
    }
  
    @Bean
    public PasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder(12);
    }
  
  //  @Override
  //  @Bean
  //  public AuthenticationManager authenticationManagerBean() throws Exception {
  //    return super.authenticationManagerBean();
  //  }
  
    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
      return new CustomAccessDeniedHandler();
    }
  
  }
  </code></pre>
  
  <p><strong><em>Custom handler:</em></strong></p>
  
  <pre><code>public class CustomAccessDeniedHandler implements AccessDeniedHandler {
  
      public static final Logger LOG = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);
  
      @Override
      public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc) throws IOException, ServletException {
          response.setStatus(HttpStatus.UNAUTHORIZED.value());
  
          String jsonPayload = "{\"messffffffage\" : \"%s\", \"timestamp\" : \"%s\" }";
          response.getOutputStream().println(String.format(jsonPayload, exc.getMessage(), Calendar.getInstance().getTime()));
      }
  }
  </code></pre>
  
  <p>But I get the default error message:</p>
  
  <pre><code>{
      "timestamp": "2020-06-09T21:23:32.528+00:00",
      "status": 403,
      "error": "Forbidden",
      "message": "",
      "path": "/engine/users/request"
  }
  </code></pre>
  
  <p>Do you know how I can implement the handler proprly?</p>