title: Spring MVC AccessDeniedException 500 error received instead of custom 401 error for @PreAuthorized unauth requests
body: <p>I'm writing a Java Spring MVC 4 REST app that'll sit between front-end devices (websites, mobile apps, etc) and a database. I have code below that will create a new session for each request (since REST is stateless), look at the Authorization header of the request, and will confirm the token is valid and request authenticated. </p>
  
  <p>When a user is requesting a secure method without a valid token, I'm looking to redirect unauthorized requests from a 500 Access Is Denied message to a 401 Unauthorized message.</p>
  
  <p>This is what I have so far.</p>
  
  <p>AccessDeniedHandler:</p>
  
  <pre><code>public class Unauthorized401AccessDeniedHandler implements AccessDeniedHandler {
      @Override
      public void handle(HttpServletRequest request, HttpServletResponse response,
                         AccessDeniedException accessDeniedException)
              throws IOException, ServletException {
  
          response.setStatus(401);
      }
  }
  </code></pre>
  
  <p>WebSecurityConfigurerAdapter:</p>
  
  <pre><code>@Configuration
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  @EnableWebSecurity
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http
                  .sessionManagement()
                  .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                  .and()
                  .exceptionHandling()
                  .accessDeniedHandler(new Unauthorized401AccessDeniedHandler());
  
      }
  }
  </code></pre>
  
  <p>Filter:</p>
  
  <pre><code>public class SecurityFilter implements Filter {
      final static Logger logger = Logger.getLogger(SecurityFilter.class);
  
      @Override
      public void doFilter(ServletRequest req, ServletResponse res,
                           FilterChain chain) throws IOException, ServletException {
  
          HttpServletRequest request = (HttpServletRequest) req;
          HttpServletResponse response = (HttpServletResponse) res;
          HttpSession session = request.getSession();
  
          String requestUri = request.getRequestURI();
  
          session.invalidate();
          SecurityContextHolder.clearContext();
  
          session = request.getSession(true); // create a new session
          SecurityContext ctx = SecurityContextHolder.createEmptyContext();
  
  
          boolean isLoggedIn = false;
  
          String token = null;
          String authorizationHeader = request.getHeader("authorization");
          if(authorizationHeader != null &amp;&amp; authorizationHeader.startsWith("bearer")) {
              String encryptedToken = authorizationHeader.split(" ")[1];
              token = StringUtils.newStringUtf8(Base64.decodeBase64(encryptedToken));
  
              // confirm user is logged in and authorized here TBD
  
              isLoggedIn = true;
          }
  
          PreAuthenticatedAuthenticationToken authentication = null;
          if(isLoggedIn) {
              SessionCredentialsModel authRequestModel = new SessionCredentialsModel();
              authRequestModel.employeeId = 323;
              authRequestModel.firstName = "Danny";
              authRequestModel.lastName = "Boy";
              authRequestModel.token = "this_is_a_test_token";
  
              authentication = new PreAuthenticatedAuthenticationToken(authRequestModel, token);
          } else {
              authentication = new PreAuthenticatedAuthenticationToken(new SessionCredentialsModel(), null);
          }
  
          authentication.setAuthenticated(true);
          ctx.setAuthentication(authentication);
  
          SecurityContextHolder.setContext(ctx);
          chain.doFilter(req, res);
      }
  </code></pre>
  
  <p>Security Model (aka Security Context Principal):</p>
  
  <pre><code>public class SessionCredentialsModel {
      public int employeeId;
      public String firstName;
      public String lastName;
      public String token;
  
      public boolean isAuthenticated() {
          if(employeeId &gt; 0 &amp;&amp; token != null) {
              return true;
          }
  
          return false;
      }
  }
  </code></pre>
  
  <p>and finally the controller:</p>
  
  <pre><code>  @RequestMapping(value = "/", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
      @PreAuthorize("principal.isAuthenticated()")
      public ResponseEntity&lt;LoginResponseModel&gt; create() {
          LoginResponseModel responseModel = new LoginResponseModel();
          responseModel.statusCode = 55;
          responseModel.token = "authorized model worked!";
  
          return new ResponseEntity&lt;LoginResponseModel&gt;(responseModel, HttpStatus.OK);
      }
  </code></pre>
  
  <p>When I run the method without an Authorization header I get this error (instead of the error I'm looking to get):</p>
  
  <pre><code>HTTP Status 500 - Request processing failed; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
  
  type Exception report
  
  message Request processing failed; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
  
  description The server encountered an internal error that prevented it from fulfilling this request.
  
  exception
  
  org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.security.access.AccessDeniedException: Access is denied
      org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
      org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
      javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
      org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
      javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
      org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
      net.pacificentertainment.middletier.app.security.SecurityFilter.doFilter(SecurityFilter.java:73)
  root cause
  
  org.springframework.security.access.AccessDeniedException: Access is denied
      org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84)
      org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
      org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65)
      org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
      net.pacificentertainment.middletier.app.controllers.EmployeeController$$EnhancerBySpringCGLIB$$b6765b64.create(&lt;generated&gt;)
      sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      java.lang.reflect.Method.invoke(Method.java:498)
      org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
      org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
      org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
      org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
      org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
      org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
      org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
      org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
      org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
      org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
      javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
      org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
      javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
      org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
      net.pacificentertainment.middletier.app.security.SecurityFilter.doFilter(SecurityFilter.java:73)
  note The full stack trace of the root cause is available in the Apache Tomcat/8.0.43 logs.
  
  Apache Tomcat/8.0.43
  </code></pre>
  
  <p>I'm at a loss to figure out why I can't get the unauthorized request to return a 401 -- or any other status code other than a 500.</p>
  
  <p>What do you think?</p>