title: How to handle different authentication exceptions in Spring security 3.1?
body: <p><strong>First I want to comment that I already checked the other questions in Stack Overflow and implemented my own approach based on the answers: <a href="https://stackoverflow.com/a/14425801/2487263">https://stackoverflow.com/a/14425801/2487263</a> and <a href="https://stackoverflow.com/a/16101649/2487263">https://stackoverflow.com/a/16101649/2487263</a></strong></p>
  
  <p>I am trying to secure a REST API using Spring security 3.1 in a Spring 3.2, Spring MVC application, I am using a basic authentication approach with a simple configuration:</p>
  
  <pre><code>&lt;http create-session="stateless" entry-point-ref="authenticationFailedEntryPoint"&gt;
      &lt;intercept-url pattern="/**" access="ROLE_USER"/&gt;
      &lt;http-basic /&gt;
  &lt;/http&gt;
  </code></pre>
  
  <p>As you can see I am using my custom entry point I have my own ErrorResponse object that I will add to the http response in json format, see the code below:</p>
  
  <pre><code>    @Component
  public class AuthenticationFailedEntryPoint implements AuthenticationEntryPoint {
      static Logger log = Logger.getLogger(AuthenticationFailedEntryPoint.class);
  
      @Override
      public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
          log.error(ExceptionUtils.getStackTrace(authException));
          ErrorResponse errorResponse = new ErrorResponse();  
  
              ... here I fill my errorResponse object ...
  
          ObjectMapper jsonMapper = new ObjectMapper();
  
          response.setContentType("application/json;charset=UTF-8");
          response.setStatus(status); 
  
          PrintWriter out = response.getWriter();
          out.print(jsonMapper.writeValueAsString(errorResponse));   
      }
  }
  </code></pre>
  
  <p>I tried the approach with two testing cases: </p>
  
  <ol>
  <li>Try to consume one service without providing basic authentication headers:</li>
  </ol>
  
  <p>This is the request/response:</p>
  
  <pre><code>GET http://localhost:8081/accounts/accounts?accountNumber=1013
  
  
   -- response --
  401 Unauthorized
  Server:  Apache-Coyote/1.1
  
  Content-Type:  application/json;charset=UTF-8
  
  Content-Length:  320
  
  Date:  Fri, 25 Oct 2013 17:11:15 GMT
  
  Proxy-Connection:  Keep-alive
  
  {"status":401,"messages":[{"code":"000011","message":"You are not authorized to reach this endpoint"}]}
  </code></pre>
  
  <p>2.- Try to consume the same service but now sending basic authentication headers with a wrong password:</p>
  
  <p>This is the request/response:</p>
  
  <pre><code>GET http://localhost:8081/accounts/accounts?accountNumber=1013
  Authorization: Basic bXl1c2VyOmdvb2RieWU=
  
  
   -- response --
  401 Unauthorized
  Server:  Apache-Coyote/1.1
  
  WWW-Authenticate:  Basic realm="Spring Security Application"
  
  Content-Type:  text/html;charset=utf-8
  
  Content-Length:  1053
  
  Date:  Fri, 25 Oct 2013 17:03:09 GMT
  
  Proxy-Connection:  Keep-alive
  
  &lt;html&gt; ... ugly html generated by tc server ... &lt;/html&gt;
  </code></pre>
  
  <p>As you can see in the first case the entry point was reached and the commence method was executed with the proper handling of the exception and the json response was returned. But that did not happen when the password was a wrong one.</p>
  
  <p>In the logs I found that both cases are producing a different flow:</p>
  
  <p>For case 1 (no auth headers):</p>
  
  <pre><code>...
  2013-10-25 13:11:15,830 DEBUG tomcat-http--13 org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /accounts?accountNumber=1013; Attributes: [ROLE_USER]
  2013-10-25 13:11:15,830 DEBUG tomcat-http--13 org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
  2013-10-25 13:11:15,830 DEBUG tomcat-http--13 org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@11da1f99, returned: -1
  2013-10-25 13:11:15,831 DEBUG tomcat-http--13 org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@7507ef7, returned: 0
  2013-10-25 13:11:15,831 DEBUG tomcat-http--13 org.springframework.security.web.access.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
  org.springframework.security.access.AccessDeniedException: Access is denied
  ...
  </code></pre>
  
  <p>For the case 2 (wrong password):</p>
  
  <pre><code>...
  2013-10-25 13:03:08,941 DEBUG tomcat-http--11 org.springframework.security.web.authentication.www.BasicAuthenticationFilter - Basic Authentication Authorization header found for user 'myuser'
  2013-10-25 13:03:08,941 DEBUG tomcat-http--11 org.springframework.security.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
  2013-10-25 13:03:09,544 DEBUG tomcat-http--11 org.springframework.security.authentication.dao.DaoAuthenticationProvider - Authentication failed: password does not match stored value
  2013-10-25 13:03:09,545 DEBUG tomcat-http--11 org.springframework.security.web.authentication.www.BasicAuthenticationFilter - Authentication request for failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
  2013-10-25 13:00:30,136 DEBUG tomcat-http--9 org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
  ...
  </code></pre>
  
  <p>The first case throws an AccessDeniedException which is being caught and sent to the commence method in my entry point, but the second case which throws a BadCredentialsException is not going to the entry point. </p>
  
  <p><strong>The weird thing</strong> here is that the commence method is supposed to receive an AuthenticationException, but AccessDeniedException is not an AuthenticationException but BadCredentialsException is, see the inheritance tree from the Spring security 3.1 API documentation:</p>
  
  <pre><code>java.lang.Object
    extended by java.lang.Throwable
        extended by java.lang.Exception
            extended by java.lang.RuntimeException
                extended by org.springframework.security.access.AccessDeniedException
  
  java.lang.Object
    extended by java.lang.Throwable
        extended by java.lang.Exception
            extended by java.lang.RuntimeException
                extended by org.springframework.security.core.AuthenticationException
                    extended by org.springframework.security.authentication.BadCredentialsException
  </code></pre>
  
  <p>Why is the commence method called with an exception that is not the correct type and why is not called when having the BadCredentialsException that is of the correct type ?</p>
  
  <p><strong>Edited --- Implemented the answer by @Luke</strong></p>
  
  <p>The two described solutions use the custom AuthenticationEntryPoint shown in the question, the configuration needs to be modified choosing one of the two following options:</p>
  
  <ol>
  <li><p>Adding a custom BASIC_AUTH_FILTER:</p>
  
  <pre><code>&lt;http create-session="stateless" entry-point-ref="authenticationFailedEntryPoint"&gt;
      &lt;intercept-url pattern="/**" access="ROLE_USER"/&gt;
      &lt;custom-filter position="BASIC_AUTH_FILTER" ref="authenticationFilter" /&gt; 
  &lt;/http&gt;
  
  &lt;beans:bean id="authenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter"&gt;
      &lt;beans:constructor-arg name="authenticationManager" ref="authenticationManager" /&gt;
      &lt;beans:constructor-arg name="authenticationEntryPoint" ref="authenticationFailedEntryPoint" /&gt;
  &lt;/beans:bean&gt;
  </code></pre></li>
  <li><p>OR Adding the entry point to the http-basic element, IMO is the cleanest solution:</p>
  
  <pre><code>&lt;http create-session="stateless" entry-point-ref="authenticationFailedEntryPoint"&gt;
      &lt;intercept-url pattern="/**" access="ROLE_USER"/&gt;
      &lt;http-basic entry-point-ref="authenticationFailedEntryPoint" /&gt;
  &lt;/http&gt;
  </code></pre></li>
  </ol>