title: How to redirect UsernameNotFoundException from PreAuthenticatedAuthenticationProvider when using multiple AuthenticationProviders?
body: <p>Using Spring Security 4.02, can anyone help with some tips on how I can handle <code>UsernameNotFoundException</code> from <code>PreAuthenticatedAuthenticationProvider</code> when using multiple <code>AuthenticationProviders</code> so that authenticated requests, with the correct header, but which are unauthorized, are sent to a specific URL instead of the forms-login page?</p>
  
  <p>Let me explain further what I'm trying to accomplish for accessing a web app being secured by SSO behind a proxy. Not all users who are authenticated by SSO will have access to this app. So I need to account for 3 access scenarios:</p>
  
  <ol>
  <li>authenticated user (header is present) is authorized (username/roles are present in app's db)</li>
  <li>authenticated user (header is present) is unauthorized (username/roles are <strong>not</strong> present in app's db)</li>
  <li>unauthenticated user with username/roles present in app's db</li>
  </ol>
  
  <p>The actions when accessing the website should be:</p>
  
  <ol>
  <li>authenticated/authorized user proceeds directly to target URL</li>
  <li>authenticated/unauthorized user is redirected to error/info page</li>
  <li>unauthenticated user is redirected to forms-login page for authentication</li>
  </ol>
  
  <p>With my current configuration, scenarios 1 &amp; 3 appear to be working as desired. For scenario 2 I've tried setting <code>RequestHeaderAuthenticationFilter#setExceptionIfHeaderMissing</code> to both true and false. </p>
  
  <p>If <code>setExceptionIfHeaderMissing=false</code>, authenticated/unauthorized request is handled by <code>ExceptionTranslationFilter</code> where <code>AccessDeniedException</code> is thrown and user is redirected to forms-login page. </p>
  
  <p>If <code>setExceptionIfHeaderMissing=true</code>, authenticated/unauthorized request encounters <code>PreAuthenticatedCredentialsNotFoundException</code> from <code>AbstractPreAuthenticatedProcessingFilter.doAuthenticate</code> and HTTP 500 is returned.</p>
  
  <p>So I've read and reread the Spring Security reference and api documents and scoured the web and just can't quite figure out what I need to do. I think I somehow need to enable some kind of filter or handler to trap the <code>PreAuthenticatedCredentialsNotFoundException</code> with a redirected response. But I can't seem to wrap my head around how to implement that with all the spring tools available. Can someone please offer some specifics? Many thanks in advance!!</p>
  
  <p>Here is my configuration:</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(prePostEnabled=true)
  public class SecurityConfig extends WebSecurityConfigurerAdapter { 
  
      private static final String AUTHENTICATION_HEADER_NAME = "PKE_SUBJECT";
  
      @Autowired
      CustomUserDetailsServiceImpl customUserDetailsServiceImpl;
  
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          auth.authenticationProvider(preAuthenticatedAuthenticationProvider());
          auth.inMemoryAuthentication()
              .withUser("user").password("password").roles("USER").and()
              .withUser("admin").password("password").roles("USER", "ADMIN");
          auth.userDetailsService(customUserDetailsServiceImpl);
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http.csrf().and()
              .authorizeRequests()
                  .antMatchers("/javax.faces.resource/**", "/resources/**", "/templates/**", "/public/**").permitAll()                
                  .anyRequest().authenticated()
                  .and()
              .formLogin()
                  .permitAll()
                  .and()
              .logout()
                  .logoutSuccessUrl("/public/welcome.xhtml")
                  .and()
              .addFilter(requestHeaderAuthenticationFilter());    
      }
  
      @Bean PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider() throws Exception {
          PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
          provider.setPreAuthenticatedUserDetailsService(userDetailsServiceWrapper());
          return provider;
      }
  
      @Bean
      public RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter() throws Exception {
          RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
          filter.setPrincipalRequestHeader(AUTHENTICATION_HEADER_NAME);
          filter.setAuthenticationManager(authenticationManagerBean());
          filter.setExceptionIfHeaderMissing(true);
          return filter;
      }
  
      @Bean
      public UserDetailsByNameServiceWrapper&lt;PreAuthenticatedAuthenticationToken&gt; 
              userDetailsServiceWrapper() throws Exception {
  
          UserDetailsByNameServiceWrapper&lt;PreAuthenticatedAuthenticationToken&gt; wrapper 
                  = new UserDetailsByNameServiceWrapper&lt;PreAuthenticatedAuthenticationToken&gt;();
          wrapper.setUserDetailsService(customUserDetailsServiceImpl);
          return wrapper;
      }
  }
  </code></pre>
  
  <p>My customized UserDetailsService:</p>
  
  <pre><code>@Service("customUserDetailsService")
  public class CustomUserDetailsServiceImpl implements UserDetailsService {
  
      @Autowired
      UserRepo userRepo;
  
      @Override
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  
          UserDetailDO userDetail = userRepo.getUserDetailById(username);
          if(userDetail == null) {
              throw new UsernameNotFoundException("user is not authorized for this application");         
          }
  
          List&lt;UserRoleDO&gt; roles = userRepo.getRolesByUsername(username);
          List&lt;GrantedAuthority&gt; authorities = new ArrayList&lt;GrantedAuthority&gt;();
  
          if(CollectionUtils.isNotEmpty(roles)) {
              for(UserRoleDO role : roles) {
                  SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getRole());
                  authorities.add(authority);             
              }
          }
  
          UserDetails user = new User(username, "N/A", authorities);      
          return user;
      }
  }
  </code></pre>