Entry

http://localhost:8082/oauth2/authorization/gitee

Suppose the request URL above is the starting point for the client to perform third-party authentication, the default format is {baseUrl}/oauth2/authorization/{clientRegistrationId}, where clientRegistrationId represents a third-party identifier, which can be WeChat, Alipay and other open platforms. Alipay and other open platforms, in this case gitee. After the user clicks on the request, the authorization journey begins. Spring Security must have intercepted the /oauth2/authorization before enabling the OAuth2 related processing logic. So let’s start here and explore from the source code. The IDEA shortcut CTRL SHIFT R will allow you to search globally for results.

spring-security oauth2

Not surprisingly, I found three places, so I’ll write them down and look at them one by one!

OAuth2AuthorizationRequestRedirectWebFilter

First look at the first OAuth2AuthorizationRequestRedirectWebFilter, which implements Spring Webflux’s WebFilter interface, which is obviously a Webflux thing, and this will be useful if you use Webflux, but not what we use now.

DefaultOAuth2AuthorizationRequestResolver

The second is what it is, from the name looks like a default OAuth2 authorization request parser. Sometimes the name is a good way to know what this thing generally do, I have to say that the details of the excellent framework is very well designed. It implements the interface OAuth2AuthorizationRequestResolver .

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public interface OAuth2AuthorizationRequestResolver {

   /**
    * 从HttpServletRequest对象中解析封装 OAuth2AuthorizationRequest
    */
   OAuth2AuthorizationRequest resolve(HttpServletRequest request);

   /**
    * 从HttpServletRequest对象以及clientRegistrationId中解析封装 OAuth2AuthorizationRequest
    */
   OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId);

}

This means that when we request /oauth2/authorization, DefaultOAuth2AuthorizationRequestResolver will extract the data from the oauth2/authorization corresponding HttpServletRequest and wrap it in the OAuth2AuthorizationRequest request object for further use.

NOTE: /oauth2/authorization is also customizable as the default interception identifier.

OAuth2AuthorizationRequest

Here it is briefly mentioned that OAuth2AuthorizationRequest encapsulates some of the OAuth2 related conceptual parameters we described in the previous article, which we will use in the subsequent request classes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public final class OAuth2AuthorizationRequest implements Serializable {
    private static final long serialVersionUID = 520L;
    private String authorizationUri;
    private AuthorizationGrantType authorizationGrantType;
    private OAuth2AuthorizationResponseType responseType;
    private String clientId;
    private String redirectUri;
    private Set<String> scopes;
    private String state;
    private Map<String, Object> additionalParameters;
    private String authorizationRequestUri;
    private Map<String, Object> attributes;
    // 其它方法略
}

OAuth2AuthorizationRequestRedirectFilter

This was the only clue left, as soon as I saw that it inherited from OncePerRequestFilter I knew it had to be him. Even its member variables contain the OAuth2AuthorizationRequestResolver that is used to parse OAuth2 requests. Here we are on the right track and start analyzing this filter. Here is its core filtering logic, which is the logic we want to know how OAuth2 authorization requests are intercepted and processed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {

   try {
      OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestResolver.resolve(request);
      if (authorizationRequest != null) {
         this.sendRedirectForAuthorization(request, response, authorizationRequest);
         return;
      }
   } catch (Exception failed) {
      this.unsuccessfulRedirectForAuthorization(request, response, failed);
      return;
   }

   try {
      filterChain.doFilter(request, response);
   } catch (IOException ex) {
      throw ex;
   } catch (Exception ex) {
      // Check to see if we need to handle ClientAuthorizationRequiredException
      Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(ex);
      ClientAuthorizationRequiredException authzEx = (ClientAuthorizationRequiredException) this.throwableAnalyzer
         .getFirstThrowableOfType(ClientAuthorizationRequiredException.class, causeChain);
      if (authzEx != null) {
         try {
            OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestResolver.resolve(request, authzEx.getClientRegistrationId());
            if (authorizationRequest == null) {
               throw authzEx;
            }
            this.sendRedirectForAuthorization(request, response, authorizationRequest);
            this.requestCache.saveRequest(request, response);
         } catch (Exception failed) {
            this.unsuccessfulRedirectForAuthorization(request, response, failed);
         }
         return;
      }

      if (ex instanceof ServletException) {
         throw (ServletException) ex;
      } else if (ex instanceof RuntimeException) {
         throw (RuntimeException) ex;
      } else {
         throw new RuntimeException(ex);
      }
   }
}

The corresponding flow of doFilterInternal is as follows.

doFilterInternal

Based on this process, if you want to understand how Spring Security OAuth2 redirects to third parties, you need to delve into the sendRedirectForAuthorization method, which I will analyze in the next post for space reasons.

Summary

Today, we found the source of OAuth2 authorization processing portal step by step, and initially analyzed the role of several key components and the core interceptor interception logic. We will then go deeper and deeper to figure out its operation process step by step.

Reference https://felord.cn/oauth2-authorization.html