[JAVA] Part 2: Understand (roughly) the process flow of OAuth 2.0 Login supported by Spring Security 5

Based on the demo application created last time in "Try using OAuth 2.0 Login supported by Spring Security 5 with Spring Boot" I would like to see if Spring Security 5 realizes OAuth 2.0 Login in the flow. (This time, we will limit the processing flow to the Servlet Filter particle size → Please look forward to the story of what class is used in each Servlet Filter for processing !!)

Prerequisite version

Enable Spring Security debug logging

When investigating the mechanism of Spring Security, enabling the debug log of Spring Secuirty makes it easier to understand the behavior of the Security Filters of Spring Security.

src/main/resources/application.properties


logging.level.org.springframework.security=debug

Application status of Servlet Filter

When you start the demo application, the following log is output, and you can confirm that the Spring Security Servlet Filter (springSecurityFilterChain) is applied to all requests (/ *).

2017-11-23 21:40:39.451  INFO 66053 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-11-23 21:40:39.451  INFO 66053 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-11-23 21:40:39.451  INFO 66053 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-11-23 21:40:39.451  INFO 66053 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
+2017-11-23 21:40:39.452  INFO 66053 --- [ost-startStop-1] .s.DelegatingFilterProxyRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*]

Application status of FilterChainProxy (springSecurityFilterChain)

If you start the demo application with the Spring Security debug log enabled, the following log will be output, and you can check the application status of the Spring Security Security Filter (actually Servlet Filter) for each path pattern. I will. (Although line breaks are made for readability, they are actually output on one line)

2017-11-23 21:40:40.691  INFO 66053 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1,
 [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3cae7b8b,
 org.springframework.security.web.context.SecurityContextPersistenceFilter@20e6c4dc,
 org.springframework.security.web.header.HeaderWriterFilter@327c7bea,
 org.springframework.security.web.csrf.CsrfFilter@5246a3b3,
 org.springframework.security.web.authentication.logout.LogoutFilter@151db587,
 org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@26f7cdf8,
 org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter@681adc8f,
 org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@4682eba5,
 org.springframework.security.web.savedrequest.RequestCacheAwareFilter@4d2a1da3,
 org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@68c87fc3,
 org.springframework.security.web.authentication.AnonymousAuthenticationFilter@184dbacc, 
 org.springframework.security.web.session.SessionManagementFilter@6c65860d,
 org.springframework.security.web.access.ExceptionTranslationFilter@3f672204,
 org.springframework.security.web.access.intercept.FilterSecurityInterceptor@18eec010]

Security Filter Overview

Let me briefly introduce the role of Security Filter (Servlet Filter) related to this entry (OAuth 2.0 Login).

Security Filter Description
SecurityContextPersistenceFilter SecurityContext(Area to hold authentication information)A Servlet Filter that provides a mechanism for sharing the data across requests. The default behavior is for sharing between requestsHttpSessionTo use.
OAuth2AuthorizationRequestRedirectFilter OAuth 2.0(OpenID Connect 1.0)Provider authorization endpoint(Endpoint to get permission to access user information of resource owner)A Servlet Filter that provides an endpoint for redirecting to. The default behavior is "/oauth2/authorization/{registrationId}Is the endpoint path.
OAuth2LoginAuthenticationFilter OAuth 2.0(OpenID Connect 1.0)The endpoint for logging in to the demo app (the endpoint used when returning to the demo app after authorization on the provider side) using the token endpoint (endpoint for acquiring the access token) of Provide Servlet Filter. The default behavior is "/login/oauth2/code/{registrationId}Is the endpoint path.
DefaultLoginPageGeneratingFilter A Servlet Filter that provides an endpoint to generate a default login page. The default behavior is "GET /loginIs the endpoint path. If the login page is specified, this Servlet Filter will not be applied.
ExceptionTranslationFilter Servlet Filter for handling authorization errors and providing error response. The default behavior is to redirect to the endpoint to display the login page when login is required, and respond "403 Forbidden" if logged in (AccessDeniedHandlerCan be customized to any error response).
FilterSecurityInterceptor Servlet Filter that performs authorization processing based on the specified access policy.

Note:

In this entry, I will omit the basic mechanism of Spring Secuirty, so if you want to know the basic mechanism of Spring Security, please read @ opengl-8080's "[Spring Security Usage Memo Series](https: /) /qiita.com/opengl-8080/items/032ed0fa27a239bdc1cc) ”is recommended! !!

Understand the flow of "Index screen display request-> Login screen display"

Here, we will look at the operation when a request to display a secure page ("index screen") is made without logging in.

image.png

Process flow
The resource owner makes a "index screen display request" via the user agent.(GET /)"I do.
FilterSecurityInterceptorPerforms authorization processing for the "index screen display request". In the demo application, the access policy of "authenticated" is defined for "request to display index screen", so a request from a user agent who is not logged in will result in an authorization error.
ExceptionTranslationFilterIs an authorization error(AccessDeniedException)And redirect to the login screen. Before redirecting, cache the request information that caused an authorization error (default implementation isHttpSessionBy storing it in (stored in), the index screen can be displayed after successful login.
The user agent requests "Login screen display request"(GET /login)"I do.
DefaultLoginPageGeneratingFilterResponds to the login screen for logging in via the provider (GitHub in the demo app).

Understand the flow of "Login request (authorization screen display request)-> authorization screen display"

Here, let's see the operation when a request to display the authorization screen provided by the provider is made from the login screen generated by DefaultLoginPageGeneratingFilter.

image.png

Process flow
The resource owner presses the link displayed on the login screen and clicks the "Authorization screen display request (GET /oauth2/authorization/{registrationId})"I do. The demo application uses GitHub as the provider, soregistrationIdIsgithubbecome.
OAuth2AuthorizationRequestRedirectFilterIs the client registration information(ClientRegistration)Refer to and redirect to the authorization endpoint provided by the provider.
GitHub displays the authorization screen after authenticating the resource owner.

Understand the flow of "Authorization request-> Index screen display"

Here, let's see the operation when an authorization request is made on the authorization screen of GitHub.

image.png

Process flow
The resource owner is allowed to log in to the demo application using the user information of the provider by pressing the "authorization button" displayed on the authorization screen.
GitHub assigns an authorization code to the transition destination (URL for accessing the endpoint that performs authentication processing) specified by the demo application and redirects.
The user agent is "Authentication processing request (GET /login/oauth2/code/{registrationId})"I do. The demo application uses GitHub as the provider, soregistrationIdIsgithubbecome.
OAuth2LoginAuthenticationFilterMakes a request to the token endpoint provided by the provider and obtains the access token corresponding to the authorization code received from the provider.
OAuth2LoginAuthenticationFilterUses the access token obtained from the provider to make a request to the user information endpoint and obtain the user information of the source owner.
OAuth2LoginAuthenticationFilterGenerates credentials using acquisition from token endpoints and user information endpoints,SecurityContextHolderSet to. (It will be authenticated here)
OAuth2LoginAuthenticationFilterRefers to the request information cached at the time of authorization error and makes an "index screen display request (redirect)".
SecurityContextPersistenceFilterWill generate the credentials when the authentication is successfulSecurityContextHolderTake out fromHttpSessionSave to.
The user agent requests "index screen display request (GET /)"I do.
SecurityContextPersistenceFilterIsHttpSessionGet credentials fromSecurityContextHolderSet to. By performing this process, the authentication information can be shared across requests (= the authenticated state can be maintained).
FilterSecurityInterceptorPerforms authorization processing for the "index screen display request". At this point, since it is in the authenticated state, authorization is OK and subsequent processing (index screen display processing) is executed.
DemoControllerPerforms a process corresponding to the "index screen display request" and responds to the index screen.

Summary

The mechanism of OAuth 2.0 Login provided by Spring Security 5 is realized by adding two Security Filters, ʻOAuth2AuthorizationRequestRedirectFilter and ʻOAuth2LoginAuthenticationFilter, to the Security Filter group provided before Spring Security 4. I think you understand.

ʻOAuth2AuthorizationRequestRedirectFilter is completely OAuth 2.0 Login's own Security Filter, but ʻOAuth2LoginAuthenticationFilter plays the same role as ʻUsernamePasswordAuthenticationFilter in forms authentication. ʻUsernamePasswordAuthenticationFilter uses the" username "and" password "entered on the login screen for authentication, while ʻOAuth2LoginAuthenticationFilter` uses the" authorization code "issued by the provider (authorization server) for authentication. The difference between these two Security Filters (authentication filters) is that

Next time, I would like to introduce what kind of classes ʻOAuth2AuthorizationRequestRedirectFilter and ʻOAuth2LoginAuthenticationFilter use for processing.

Reference site

Recommended Posts

Part 2: Understand (roughly) the process flow of OAuth 2.0 Login supported by Spring Security 5
Part 3: Understand (deeply) the process flow of OAuth 2.0 Login supported by Spring Security 5
Part 4: Customize the behavior of OAuth 2.0 Login supported by Spring Security 5
Part 1: Try using OAuth 2.0 Login supported by Spring Security 5 with Spring Boot
[Java / Spring Boot] Spring security ④ --Implementation of login process
Let's experience the authorization code grant flow with Spring Security OAuth-Part 1: Review of OAuth 2.0
I want to understand the flow of Spring processing request parameters
The process of understanding Gemfile by non-engineers
Login function implementation by Spring Security (securityConfig)
Until the use of Spring Data and JPA Part 2
Until the use of Spring Data and JPA Part 1
Roughly the flow of web application development with Rails.
Control the processing flow of Spring Batch with JavaConfig.
The story of raising Spring Boot from 1.5 series to 2.1 series part2
Login with HttpServletRequest # login in Spring Security of Servlet 3.x environment