title: Spring Security Custom Authentication Filter and Authorization
body: <p>I've implemented a custom authentication filter, and it works great. I use an external identity provider and redirect to my originally requested URL after setting my session and adding my authentication object to my security context.</p>
  
  <p><strong>Security Config</strong></p>
  
  <pre><code>@EnableWebSecurity(debug = true)
  @Configuration
  class SecurityConfig extends WebSecurityConfigurerAdapter {
  
      // this is needed to pass the authentication manager into our custom security filter
      @Bean
      @Override
      AuthenticationManager authenticationManagerBean() throws Exception {
          return super.authenticationManagerBean()
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http
              .csrf().disable()
              .authorizeRequests()
                  //.antMatchers("/admin/test").hasRole("METADATA_CURATORZ")
                  .antMatchers("/**").permitAll()
              .anyRequest().authenticated()
              .and()
              .addFilterBefore(new CustomSecurityFilter(authenticationManagerBean()), UsernamePasswordAuthenticationFilter.class)
      }
  }
  </code></pre>
  
  <p><strong>Filter logic</strong></p>
  
  <p>For now, my custom filter (once identity is confirmed) simply hard codes a role:</p>
  
  <pre><code>SimpleGrantedAuthority myrole = new SimpleGrantedAuthority("METADATA_CURATORZ")
                  return new PreAuthenticatedAuthenticationToken(securityUser, null, [myrole])
  </code></pre>
  
  <p>That authentication object (returned above) is then added to my SecurityContext before redirecting to the desired endpoint:</p>
  
  <p><code>SecurityContextHolder.getContext().setAuthentication(authentication)</code></p>
  
  <p><strong>Controller Endpoint</strong></p>
  
  <pre><code>  @RequestMapping(path = '/admin/test', method = GET, produces = 'text/plain')
    String test(HttpServletRequest request) {
      Authentication auth = SecurityContextHolder.getContext().getAuthentication()
  
      String roles = auth.getAuthorities()
      return "roles: ${roles}"
    }
  </code></pre>
  
  <p>This endpoint then yields a response in the browser of:</p>
  
  <blockquote>
    <p>"roles: [METADATA_CURATORZ]"</p>
  </blockquote>
  
  <p>Great. So my authentication and applying a role to my user is working great.</p>
  
  <p>Now, if I uncomment this line from the security config:</p>
  
  <p><code>//.antMatchers("/admin/test").hasRole("METADATA_CURATORZ")</code></p>
  
  <p>I can no longer access that resource and get a 403 -- even though we've already proven the role was set.</p>
  
  <p>This seems totally nonsensical and broken to me, but I'm no Spring Security expert.  </p>
  
  <p>I'm probably missing something very simple. Any ideas?</p>
  
  <p>Some questions I have:</p>
  
  <ul>
  <li>Does my custom filter need to be placed before a specific built-in filter to ensure the authorization step occurs after that filter is executed?</li>
  <li>When in the request cycle is the antMatcher/hasRole check taking place?</li>
  <li>Do I need to change the order of what I am calling in my security configure chain, and how should I understand the config as I've currently written it? It's obviously not doing what I think it should be.</li>
  </ul>