title: PreAuthenticatedAuthenticationProvider UserDetailsService how to catch the right exception
body: <p>I am under Spring Boot 2.0.5 (Spring Security 5.0.8)</p>
  
  <p>I have setup a preauthentication filter chain, which works fine, only thing problematic is the exception handling, especially those thrown form my custom UserDetailsService. I also tried to return a User with "enabled = false" but still the same.</p>
  
  <p>See code below for my custom UserDetailsService:</p>
  
  <pre><code>@Component
  @Slf4j
  public class PreAuthenticatedUserDetailsService
          implements AuthenticationUserDetailsService&lt;PreAuthenticatedAuthenticationToken&gt; {
  
      @Autowired
      private AccessService accessService;
  
      @Override
      public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) throws AuthenticationException {
  
          String accessId = token.getCredentials() + "";
  
          try {
              AccessEntity accessEntity = accessService.getAccessByAccessId(accessId);
  
              if (accessEntity == null) {
                  throw new BadCredentialsException(String.format("Unknown access (AccessId=%s)", accessId));
              }
  
              List&lt;AccessRole&gt; accessRoles = accessEntity.getRoles();
  
              if (!accessEntity.getActive()) {                    
                  return new User(accessEntity.getUid(), accessEntity.getUid(), false, true, true, true, accessRoles.stream()
                          .map(role -&gt; new SimpleGrantedAuthority(role.getValue())).collect(Collectors.toList()));
                  //throw new AccessDeniedException(String.format("Inactive access (AccessId=%s)", accessId));
              }
  
              return new User(accessEntity.getUid(), accessEntity.getUid(), accessRoles.stream()
                      .map(role -&gt; new SimpleGrantedAuthority(role.getValue())).collect(Collectors.toList()));
          } catch (Exception e) {
              log.error("Exception in load user details", e);
              throw new BadCredentialsException(String.format("Authentication issue for accessId=%s", accessId));
          }
      }
  
  }
  </code></pre>
  
  <p>And my Security Configuration:</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
  public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  
      private static final String SPRING_ROLE_ANONYMOUS = "ANONYMOUS"; // ("ROLE_" is automatically inserted as prefix)
  
      @Autowired
      private AppConfigProperties appConfigProperties;
  
      @Autowired
      RESTAuthenticationEntryPoint restAuthenticationEntryPoint;
  
      @Autowired
      RESTAccessDeniedHandler accessDeniedHandler;
  
      @Autowired
      PreAuthenticatedUserDetailsService preAuthenticatedUserDetailsService;
  
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          auth.authenticationProvider(preauthAuthProvider());
      }
  
      @Bean
      public PreAuthenticatedAuthenticationProvider preauthAuthProvider() {
          PreAuthenticatedAuthenticationProvider preauthAuthProvider = new PreAuthenticatedAuthenticationProvider();
          preauthAuthProvider.setPreAuthenticatedUserDetailsService(preAuthenticatedUserDetailsService);
          return preauthAuthProvider;
      }
  
      @Bean
      public RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter() throws Exception {
          RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
          filter.setPrincipalRequestHeader(appConfigProperties.getSecurity().getRequestHeaderTokenKeyName());
          filter.setCredentialsRequestHeader(appConfigProperties.getSecurity().getRequestHeaderTokenKeyName());
          filter.setExceptionIfHeaderMissing(false);
          filter.setAuthenticationManager(authenticationManager());
          return filter;
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          RequestMatcher protected_urls = new OrRequestMatcher(new AntPathRequestMatcher(
                  appConfigProperties.getSecurity().getProtectedUrls()));
          http
          .sessionManagement()
              .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          .and()
              .addFilterBefore(requestHeaderAuthenticationFilter(), AnonymousAuthenticationFilter.class)
              .authorizeRequests()
              .antMatchers(HttpMethod.POST , appConfigProperties.getSecurity().getUserAuthenticatePath())
                  .hasRole(SPRING_ROLE_ANONYMOUS)
              .requestMatchers(protected_urls).authenticated()
          .and()
              .exceptionHandling()
                  .accessDeniedHandler(accessDeniedHandler)
                  .authenticationEntryPoint(restAuthenticationEntryPoint)
          .and()
              .csrf().disable()
              .formLogin().disable()
              .httpBasic().disable()
              .logout().disable(); // disable autoconfig
      }
  
      /**
       * Disable Spring boot automatic filter registration.
       */
      @Bean
      FilterRegistrationBean&lt;RequestHeaderAuthenticationFilter&gt; disableAutoRegistration(final RequestHeaderAuthenticationFilter filter) {
          final FilterRegistrationBean&lt;RequestHeaderAuthenticationFilter&gt; registration = new FilterRegistrationBean&lt;&gt;(filter);
          registration.setEnabled(false);
          return registration;
      }
  }
  
  @Component
  @Slf4j
  public class RESTAuthenticationEntryPoint implements AuthenticationEntryPoint {
  
      @Autowired
      private AppConfigProperties appConfigProperties;
  
      @Override
      public void commence(final HttpServletRequest request, final HttpServletResponse response,
              final AuthenticationException authException) throws IOException {
  
          log.error("********* Authentication Entry Point exception", authException);
  
          response.setContentType("application/json");
          response.setCharacterEncoding("UTF-8");
  
          String responseContentJson = null;
  
          response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
          responseContentJson = new Gson().toJson(GlobalExceptionHandler.createSWError(SWErrorCode.HTTP,
                  String.format("Failed authentication: missing request header '%s' or invalid value",
                          appConfigProperties.getSecurity().getRequestHeaderTokenKeyName())));
  
          PrintWriter out = response.getWriter();
          out.print(responseContentJson);
          out.flush();
          response.flushBuffer();
      }
  
  }
  </code></pre>
  
  <p>I also tried to use an "accessDeniedHandler" but it never goes through it.</p>
  
  <p>The issue is that for any exception thrown (either in my custom UserDetailsService or others), it goes through my custom "AuthenticationEntryPoint" with an always similar exception, see below:</p>
  
  <pre><code>org.springframework.security.authentication.InsufficientAuthenticationException: Full authentication is required to access this resource
      at org.springframework.security.web.access.ExceptionTranslationFilter.handleSpringSecurityException(ExceptionTranslationFilter.java:190)
      at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:141)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:121)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
      at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
      at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
      at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
      at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:155)
      at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:123)
      at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
      at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
      at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
      at java.lang.Thread.run(Thread.java:748)
  </code></pre>
  
  <p>Any idea would be great!</p>