View Javadoc

1   package com.atlassian.asap.core.server.springsecurity;
2   
3   import com.atlassian.asap.core.JwtConstants;
4   import org.apache.commons.lang3.StringUtils;
5   import org.apache.http.HttpHeaders;
6   import org.springframework.beans.factory.annotation.Autowired;
7   import org.springframework.security.authentication.AuthenticationManager;
8   import org.springframework.security.core.Authentication;
9   import org.springframework.security.core.AuthenticationException;
10  import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
11  import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
12  import org.springframework.security.web.util.matcher.RequestMatcher;
13  
14  import javax.servlet.FilterChain;
15  import javax.servlet.ServletException;
16  import javax.servlet.http.HttpServletRequest;
17  import javax.servlet.http.HttpServletResponse;
18  import java.io.IOException;
19  import java.util.Objects;
20  
21  /**
22   * Authentication processing filter that extracts the bearer token from the HTTP Authorization header. This filter
23   * must be added to the chain, e.g., before
24   * {@link org.springframework.security.web.authentication.www.BasicAuthenticationFilter}, and it works in coordination
25   * with {@link AsapAuthenticationProvider}.
26   */
27  public class BearerTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
28      private static final AuthenticationSuccessHandler NOOP_SUCCESS_HANDLER =
29              (httpServletRequest, httpServletResponse, authentication) -> { };
30      private static final RequestMatcher REQUEST_MATCHER = new BearerTokenRequestMatcher();
31  
32      private final AuthenticationManager authenticationManager;
33  
34      @Autowired
35      public BearerTokenAuthenticationProcessingFilter(AuthenticationManager authenticationManager) {
36          super(REQUEST_MATCHER);
37          this.authenticationManager = Objects.requireNonNull(authenticationManager);
38          this.setAuthenticationSuccessHandler(NOOP_SUCCESS_HANDLER);
39      }
40  
41      @Override
42      public Authentication attemptAuthentication(HttpServletRequest httpServletRequest,
43                                                  HttpServletResponse httpServletResponse)
44              throws AuthenticationException, IOException, ServletException {
45          // due to the request matcher, it is guaranteed that the request contains a bearer token
46          String authorizationHeader = httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION);
47          String serializedJwt = StringUtils.removeStart(authorizationHeader,
48                  JwtConstants.HTTP_AUTHORIZATION_HEADER_VALUE_PREFIX);
49          Authentication candidateAuthentication = new UnverifiedBearerToken(serializedJwt);
50          return authenticationManager.authenticate(candidateAuthentication);
51      }
52  
53      // the implementation from the parent delegates to a successHandler, which unfortunately cannot
54      // propagate the request down the filter chain, so we decorate the method
55      @Override
56      protected void successfulAuthentication(HttpServletRequest request,
57                                              HttpServletResponse response,
58                                              FilterChain chain,
59                                              Authentication authResult)
60              throws IOException, ServletException {
61          super.successfulAuthentication(request, response, chain, authResult);
62          chain.doFilter(request, response);
63      }
64  }