title: How to add a custom OpenId Filter in a Spring boot application?
body: <p>I am trying to implement the backend side of an OpenId Connect authentication. It is a stateless API so I added a filter that handles the Bearer token. </p>
  
  <p>I have created the OpenIdConnect Filter that handles the Authentication and added it in a WebSecurityConfigurerAdapter.</p>
  
  <pre><code>public class OpenIdConnectFilter extends 
     AbstractAuthenticationProcessingFilter {
   @Value("${auth0.clientId}")
   private String clientId;
  
   @Value("${auth0.issuer}")
   private String issuer;
  
   @Value("${auth0.keyUrl}")
   private String jwkUrl;
  
  private TokenExtractor tokenExtractor = new BearerTokenExtractor();
  
  public OpenIdConnectFilter() {
      super("/connect/**");
      setAuthenticationManager(new NoopAuthenticationManager());
  }
  
  @Bean
  public FilterRegistrationBean registration(OpenIdConnectFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
  }
  
  @Override
  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
  
  
      try {
        Authentication authentication = tokenExtractor.extract(request);
  
        String accessToken = (String) authentication.getPrincipal();
          String kid = JwtHelper.headers(accessToken)
              .get("kid");
          final Jwt tokenDecoded = JwtHelper.decodeAndVerify(accessToken, verifier(kid));
          final Map&lt;String, Object&gt; authInfo = new ObjectMapper().readValue(tokenDecoded.getClaims(), Map.class);
          verifyClaims(authInfo);
          Set&lt;String&gt; scopes = new HashSet&lt;String&gt;(Arrays.asList(((String) authInfo.get("scope")).split(" ")));
          int expires = (Integer) authInfo.get("exp");
          OpenIdToken openIdToken = new OpenIdToken(accessToken, scopes, Long.valueOf(expires), authInfo);
          final OpenIdUserDetails user = new OpenIdUserDetails((String) authInfo.get("sub"), "Test", openIdToken);
  
          return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
      } catch (final Exception e) {
          throw new BadCredentialsException("Could not obtain user details from token", e);
      }
  
  }
  
  public void verifyClaims(Map claims) {
      int exp = (int) claims.get("exp");
      Date expireDate = new Date(exp * 1000L);
      Date now = new Date();
      if (expireDate.before(now) || !claims.get("iss").equals(issuer) || !claims.get("azp").equals(clientId)) {
          throw new RuntimeException("Invalid claims");
      }
  }
  
  
  private RsaVerifier verifier(String kid) throws Exception {
      JwkProvider provider = new UrlJwkProvider(new URL(jwkUrl));
      Jwk jwk = provider.get(kid);
      return new RsaVerifier((RSAPublicKey) jwk.getPublicKey());
  }
  </code></pre>
  
  <p>Here is security configuration:</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  public class OpenIdConnectWebServerConfig extends 
  WebSecurityConfigurerAdapter {
  
  @Bean
  public OpenIdConnectFilter myFilter() {
     final OpenIdConnectFilter filter = new OpenIdConnectFilter();
     return filter;
   }
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.cors();
    http.antMatcher("/connect/**").authorizeRequests() 
    .antMatchers(HttpMethod.GET, "/connect/public").permitAll()
    .antMatchers(HttpMethod.GET, "/connect/private").authenticated()
    .antMatchers(HttpMethod.GET, "/connect/private- 
         messages").hasAuthority("read:messages")
    .antMatchers(HttpMethod.GET, "/connect/private- 
        roles").hasAuthority("read:roles")
    .and()
      .addFilterBefore(myFilter(), 
         UsernamePasswordAuthenticationFilter.class);
  }
  </code></pre>
  
  <p>Rest endpoints looks like following: </p>
  
  <pre><code>  @RequestMapping(value = "/connect/public", method = RequestMethod.GET, 
       produces = "application/json")
    @ResponseBody
     public String publicEndpoint() throws JSONException {
      return new JSONObject()
            .put("message", "All good. You DO NOT need to be authenticated to 
           call /api/public.")
            .toString();
    }
  
     @RequestMapping(value = "/connect/private", method = RequestMethod.GET, 
        produces = "application/json")
       @ResponseBody
       public String privateEndpoint() throws JSONException {
        return new JSONObject()
            .put("message", "All good. You can see this because you are 
       Authenticated.")
            .toString();
  </code></pre>
  
  <p>}</p>
  
  <p>If I remove completely the filter for configuration and also the @Bean definition, the configuration works as expected:  /connect/public is accessible, while /connect/private is forbidden. </p>
  
  <p>If I keep the @Bean definition and add it in filter chain the response returns a Not Found status for requests both on /connect/public and /connect/private:</p>
  
  <pre><code>"timestamp": "18.01.2019 09:46:11",
  "status": 404,
  "error": "Not Found",
  "message": "No message available",
  "path": "/
  </code></pre>
  
  <p>When debugging I noticed that filter is processing the token and returns an implementation of Authentication.</p>
  
  <ol>
  <li>Is the filter properly added in filter chain and in correct position?</li>
  <li><p>Why is the filter invoked also on /connect/public path when this is supposed to be public. Is it applied to all paths matching super("/connect/**") call? </p></li>
  <li><p>Why is it returning the path as "/" when the request is made at /connect/private</p></li>
  </ol>
  
  <p>Seems that is something wrong with the filter, cause every time it is applied, the response is messed up. </p>