๐ป[์คํ๋ง ์ํ๋ฆฌํฐ OAuth2] oauth2Login()
1. OAuth2LoginConfigurer
1-1). OAuth2LoginConfigurer ์ด๊ธฐํ ๋ฐ ์ค์
์ค์ ํด๋์ค ์์ฑ
@Configuration(proxyBeanMethods = false)
public class CustomOAuth2ClientConfig {
@Bean
SecurityFilterChain oauth2SecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
http.oauth2Login(Customizer.withDefaults());
http.oauth2Client();
return http.build();
}
}
- API ์ค์
- SecurityFilterChain ํ์ ์ ๋น์ ์์ฑํด์ ๋ณด์ ํํฐ๋ฅผ ๊ตฌ์ฑํ๋ค
- HttpSecurity ์ ์๋ oauth2Login() ๊ณผ oauth2Client() API ๋ฅผ ์ ์ํ๊ณ ๋น๋ํ๋ค
2. OAuth2 ๋ก๊ทธ์ธ ๊ตฌํ
2-1). OAuth 2.0 Login Page ์์ฑ
2-2). Authorization Code ์์ฒญํ๊ธฐ
์์ฒญ ๋งคํ Url
- AuthorizationRequestMatcher : /oauth2/authorization/{registrationId}*
- AuthorizationEndpointConfig. authorizationRequestBaseUri ๋ฅผ ํตํด ์ฌ์ ์๋ ์ ์๋ค
์ฃผ์ ํด๋์ค
- OAuth2AuthorizationRequestRedirectFilter
- ํด๋ผ์ด์ธํธ๋ ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ์ธ๊ฐ ์๋ฒ์ ๊ถํ ๋ถ์ฌ ์๋ํฌ์ธํธ๋ก ๋ฆฌ๋ค์ด๋ ์ ํ์ฌ ๊ถํ ์ฝ๋ ๋ถ์ฌ ํ๋ฆ์ ์์ํ๋ค.
- DefaultOAuth2AuthorizationRequestResolver
- ์น ์์ฒญ์ ๋ํ์ฌ OAuth2AuthorizationRequest ๊ฐ์ฒด๋ฅผ ์ต์ข ์์ฑํ๋ค
- /oauth2/authorization/{registrationId} ์ ์ผ์นํ๋์ง ํ์ธํด์ ์ผ์นํ๋ฉด registrationId๋ฅผ ์ถ์ถํ๊ณ ์ด๋ฅผ ์ฌ์ฉํด์ ClientRegistration์ ๊ฐ์ ธ์ OAuth2AuthorizationRequest ๋ฅผ ๋น๋ํ๋ค.
- OAuth2AuthorizationRequest
- ํ ํฐ ์๋ํฌ์ธํธ ์์ฒญ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ด์ ๊ฐ์ฒด๋ก์ ์ธ๊ฐ ์๋ต์ ์ฐ๊ณํ๊ณ ๊ฒ์ฆํ ๋ ์ฌ์ฉํ๋ค
- OAuth2AuthorizationRequestRepository
- ์ธ๊ฐ ์์ฒญ์ ์์ํ ์์ ๋ถํฐ ์ธ๊ฐ ์์ฒญ์ ๋ฐ๋ ์์ ๊น์ง (๋ฆฌ๋ค์ด๋ ํธ) OAuth2AuthorizationRequest ๋ฅผ ์ ์งํด์ค๋ค
Code๋ฅผ ๋ฐ์์ค๊ณ ๋ฆฌ๋ค์ด๋ ํธ ๋๋ ๊ณผ์
2-3). Access Token ๊ตํํ๊ธฐ
์์ฒญ ๋งคํ Url
- RequestMatcher : /login/oauth2/code/*
์ฃผ์ ํด๋์ค
- OAuth2LoginAuthenticationFilter
- ์ธ๊ฐ์๋ฒ๋ก๋ถํฐ ๋ฆฌ๋ค์ด๋ ํธ ๋๋ฉด์ ์ ๋ฌ๋ code ๋ฅผ ์ธ๊ฐ์๋ฒ์ Access Token ์ผ๋ก ๊ตํํ๊ณ Access Token ์ด ์ ์ฅ๋ OAuth2LoginAuthenticationToken์ AuthenticationManager์ ์์ํ์ฌ UserInfo ์ ๋ณด๋ฅผ ์์ฒญํด์ ์ต์ข ์ฌ์ฉ์์ ๋ก๊ทธ์ธํ๋ค.
- OAuth2AuthorizedClientRepository๋ฅผ ์ฌ์ฉํ์ฌ OAuth2AuthorizedClient ๋ฅผ ์ ์ฅํ๋ค.
- ์ธ์ฆ์ ์ฑ๊ณตํ๋ฉด OAuth2AuthenticationToken ์ด ์์ฑ๋๊ณ SecurityContext์ ์ ์ฅ๋์ด ์ธ์ฆ ์ฒ๋ฆฌ๋ฅผ ์๋ฃํ๋ค
- OAuth2LoginAuthenticationProvider
- ์ธ๊ฐ์๋ฒ๋ก๋ถํฐ ๋ฆฌ๋ค์ด๋ ํธ ๋ ์ดํ ํ๋ก์ธ์ค๋ฅผ ์ฒ๋ฆฌํ๋ฉฐ Access Token ์ผ๋ก ๊ตํํ๊ณ ์ด ํ ํฐ์ ์ฌ์ฉํ์ฌ UserInfo ์ฒ๋ฆฌ๋ฅผ ๋ด๋นํ๋ค
- Scope ์ openid ๊ฐ ํฌํจ๋์ด ์์ผ๋ฉด OidcAuthorizationCodeAuthenticationProvider ๋ฅผ ํธ์ถํ๊ณ ์๋๋ฉด OAuth2AuthorizationCodeAuthenticationProvider๋ฅผ ํธ์ถํ๋๋ก ์ ์ดํ๋ค
- OAuth2AuthorizationCodeAuthenticationProvider
- ๊ถํ ์ฝ๋ ๋ถ์ฌ ํ๋ฆ์ ์ฒ๋ฆฌํ๋ AuthenticationProvider
- ์ธ๊ฐ์๋ฒ์ Authorization Code ์ AccessToken ์ ๊ตํ์ ๋ด๋นํ๋ ํด๋์ค
- OidcAuthorizationCodeAuthenticationProvider
- OpenID Connect Core 1.0 ๊ถํ ์ฝ๋ ๋ถ์ฌ ํ๋ฆ์ ์ฒ๋ฆฌํ๋ AuthenticationProvider ์ด๋ฉฐ ์์ฒญ Scope ์ openid ๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ ์คํ๋๋ค
- DefaultAuthorizationCodeTokenResponseClient
- ์ธ๊ฐ์๋ฒ์ token ์๋ ํฌ์ธํธ๋ก ํต์ ์ ๋ด๋นํ๋ฉฐ AccessToken ์ ๋ฐ์ ํ OAuth2AccessTokenResponse ์ ์ ์ฅํ๊ณ ๋ฐํํ๋ค
๊ตฌ์กฐ
ํ๋ฆ
2-4). Oauth 2.0 User ๋ชจ๋ธ ์๊ฐ
2-4-1). OAuth2UserService
- ์ก์ธ์ค ํ ํฐ์ ์ฌ์ฉํด์ UserInfo ์๋ํฌ์ธํธ ์์ฒญ์ผ๋ก ์ต์ข ์ฌ์ฉ์์ (๋ฆฌ์์ค ์์ ์) ์์ฑ์ ๊ฐ์ ธ์ค๋ฉฐ OAuth2User ํ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฆฌํดํ๋ค
-
๊ตฌํ์ฒด๋ก DefaultOAuth2UserService ์ OidcUserService ๊ฐ ์ ๊ณต๋๋ค
-
DefaultOAuth2UserService
- ํ์ค OAuth 2.0 Provider๋ฅผ ์ง์ํ๋ OAuth2UserService ๊ตฌํ์ฒด๋ค
- OAuth2UserRequest ์ Access Token ์ ๋ด์ ์ธ๊ฐ์๋ฒ์ ํต์ ํ ์ฌ์ฉ์์ ์์ฑ์ ๊ฐ์ง๊ณ ์จ๋ค
- ์ต์ข OAuth2User ํ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
-
OidcUserService
- OpenID Connect 1.0 Provider๋ฅผ ์ง์ํ๋ OAuth2UserService ๊ตฌํ์ฒด๋ค
- OidcUserRequest ์ ์๋ ID Token ์ ํตํด ์ธ์ฆ ์ฒ๋ฆฌ๋ฅผ ํ๋ฉฐ ํ์์ DefaultOAuth2UserService ๋ฅผ ์ฌ์ฉํด์ UserInfo ์๋ํฌ์ธํธ์ ์ฌ์ฉ์ ์์ฑ์ ์์ฒญํ๋ค
- ์ต์ข OidcUser ํ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
- ํ๋ฆ
- ๊ตฌ์กฐ
- DefaultOAuth2UserService ์ OAuth2User ํ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
- OidcUserService ์ OidcUser ํ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
- OidcUserRequest ์ ์น์ธ๋ ํ ํฐ์ ํฌํจ๋์ด ์๋ scope ๊ฐ์ด accessibleScopes ์ ๊ฐ ๋ค์ค ํ๋ ์ด์ ํฌํจ๋์ด ์์ ๊ฒฝ์ฐ UserInfo ์๋ ํฌ์ธํธ๋ฅผ ์์ฒญํ๋ค
2-4-2). OAuth2User & OidcUser
-
์ํ๋ฆฌํฐ๋ UserAttributes ๋ฐ ID Token Claims ์ ์ง๊ณ & ๊ตฌ์ฑํ์ฌ OAuth2User ์ OidcUser ํ์ ์ ํด๋์ค๋ฅผ ์ ๊ณตํ๋ค
-
OAuth2User
- OAuth 2.0 Provider ์ ์ฐ๊ฒฐ๋ ์ฌ์ฉ์ ์ฃผ์ฒด๋ฅผ ๋ํ๋ธ๋ค
- ์ต์ข ์ฌ์ฉ์์ ์ธ์ฆ์ ๋ํ ์ ๋ณด์ธ Attributes ๋ฅผ ํฌํจํ๊ณ ์์ผ๋ฉฐ first name, middle name, last name, email, phone number, address ๋ฑ์ผ๋ก ๊ตฌ์ฑ๋๋ค
- ๊ธฐ๋ณธ ๊ตฌํ์ฒด๋ DefaultOAuth2User ์ด๋ฉฐ ์ธ์ฆ ์ดํ Authentication ์ principal ์์ฑ์ ์ ์ฅ๋๋ค
-
OidcUser
- OAuth2User ๋ฅผ ์์ํ ์ธํฐํ์ด์ค์ด๋ฉฐ OIDC Provider ์ ์ฐ๊ฒฐ๋ ์ฌ์ฉ์ ์ฃผ์ฒด๋ฅผ ๋ํ๋ธ๋ค
- ์ต์ข ์ฌ์ฉ์์ ์ธ์ฆ์ ๋ํ ์ ๋ณด์ธ Claims ๋ฅผ ํฌํจํ๊ณ ์์ผ๋ฉฐ OidcIdToken ๋ฐ OidcUserInfo ์์ ์ง๊ณ ๋ฐ ๊ตฌ์ฑ๋๋ค
- ๊ธฐ๋ณธ ๊ตฌํ์ฒด๋ DefaultOidcUser ์ด๋ฉฐ DefaultOAuth2User ๋ฅผ ์์ํ๊ณ ์์ผ๋ฉฐ ์ธ์ฆ ์ดํ Authentication ์ principal ์์ฑ์ ์ ์ฅ๋๋ค
- ํ๋ฆ
- ๊ตฌ์กฐ
- OAuth 2.0 ๋ก๊ทธ์ธ์ ํตํด ์ธ์ฆ๋ฐ์ ์ต์ข ์ฌ์ฉ์์ Principal ์๋OAuth2User ํน์ OidcUser ํ์ ์ ๊ฐ์ฒด๊ฐ ์ ์ฅ๋๋ค
- ๊ถํ ๋ถ์ฌ ์์ฒญ ์ scope ํ๋ผ๋ฏธํฐ์ openid ๋ฅผ ํฌํจํ๋ค๋ฉด OidcUser ํ์ ์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ฉฐ OidcUser ๋ OidcUserInfo ์ idToken ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ์ต์ข ์ฌ์ฉ์์ ๋ํ Claims ์ ๋ณด๋ฅผ ํฌํจํ๊ณ ์๋ค
- OAuth2UserAuthority ๋ ์ธ๊ฐ์๋ฒ๋ก๋ถํฐ ์์ ํ scope ์ ๋ณด๋ฅผ ์ง๊ณํด์ ๊ถํ์ ๋ณด๋ฅผ ๊ตฌ์ฑํ๋ค
- OidcUser ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ID ํ ํฐ์ด ํ์ํ๋ฐ ์ด ๋ JSON ์น ํ ํฐ (JWT)์ผ๋ก ๋ ID ํ ํฐ์ JSON Web Signature (JWS)๋ก ์๋ช ์ด ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ฐ๋์ ์ ํด์ง ์๊ณ ๋ฆฌ์ฆ์ ์ํ ๊ฒ์ฆ์ด ์ฑ๊ณตํ๋ฉด OidcUser ๊ฐ์ฒด๋ฅผ ์์ฑ ํด์ผ ํ๋ค.
2-5). Oauth 2.0 Provider UserInfo ์๋ํฌ์ธํธ ์์ฒญํ๊ธฐ
์์ฒญ Uri
- POST /userinfo
์ฃผ์ ํด๋์ค
- DefaultOAuth2UserService
- public OAuth2User loadUser(OAuth2UserRequest userRequest)
- OAuth2UserRequestEntityConverter
- OAuth2UserRequest ๋ฅผ RequestEntity ๋ก ์ปจ๋ฒํฐ ํ๋ค
- RestOperations
- RequestEntity ๋ก ์ธ๊ฐ์๋ฒ์ ์์ฒญํ๊ณ ResponseEntity ๋ก ์๋ต๋ฐ๋๋ค
- OAuth2User ํ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
ํ๋ฆ
2-6). OpenID Connect Provider OidcUserInfo ์๋ํฌ์ธํธ ์์ฒญํ๊ธฐ
์์ฒญ Uri
- POST /userinfo
์ฃผ์ ํด๋์ค
- OidcUserService
- public OidcUser loadUser(OidcUserRequest userRequest)
- ๋ด๋ถ์ DefaultOAuth2UserService ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ OIDC ์ฌ์์ ๋ถํฉํ ๊ฒฝ์ฐ OidcUserRequest ๋ฅผ ๋๊ฒจ ์ฃผ์ด ์ธ๊ฐ์๋ฒ์ ํต์ ํ๋ค
- OidcUser ํ์ ์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค
- public OidcUser loadUser(OidcUserRequest userRequest)
ํ๋ฆ
2-7). OpenID Connect ๋ก๊ทธ์์
๊ฐ๋
- ํด๋ผ์ด์ธํธ๋ ๋ก๊ทธ์์ ์๋ํฌ์ธํธ๋ฅผ ์ฌ์ฉํ์ฌ ์น ๋ธ๋ผ์ฐ์ ์ ๋ํ ์ธ์ ๊ณผ ์ฟ ํค๋ฅผ ์ง์ด๋ค.
- ํด๋ผ์ด์ธํธ ๋ก๊ทธ์์ ์ฑ๊ณต ํ OidcClientInitiatedLogoutSuccessHandler ๋ฅผ ํธ์ถํ์ฌ OpenID Provider ์ธ์ ๋ก๊ทธ์์ ์์ฒญํ๋ค
- OpenID Provider ๋ก๊ทธ์์์ด ์ฑ๊ณตํ๋ฉด ์ง์ ๋ ์์น๋ก ๋ฆฌ๋ค์ด๋ ํธ ํ๋ค
- ์ธ๊ฐ์๋ฒ ๋ฉํ๋ฐ์ดํฐ ์ฌ์์ ์๋ ๋ก๊ทธ์์ ์๋ ํฌ์ธํธ๋ end_session_endpoint ๋ก ์ ์๋์ด ์๋ค
- endSessionEndpoint = http://localhost:8080/realms/oauth2/protocol/openid-connect/logout
API ์ค์
http
.logout()
.logoutSuccessHandler(oidcLogoutSuccessHandler())
.invalidateHttpSession(true)
.clearAuthentication(true)
.deleteCookies("JSESSIONID");
private OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() {
OidcClientInitiatedLogoutSuccessHandler successHandler =
new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
successHandler.setPostLogoutRedirectUri("http://localhost:8081/login");
return successHandler;
}
2-8). Spring MVC ์ธ์ฆ ๊ฐ์ฒด ์ฐธ์กฐํ๊ธฐ
Authentication
- public void dashboard(Authentication authentication) {}
- oauth2Login() ๋ก ์ธ์ฆ์ ๋ฐ๊ฒ ๋๋ฉด Authentication ์ OAuth2AuthenticationToken ํ์ ์ ๊ฐ์ฒด๋ก ๋ฐ์ธ๋ฉ ๋๋ค
- principal ์๋ OAuth2User ํ์ ํน์ OidcUser ํ์ ์ ๊ตฌํ์ฒด๊ฐ ์ ์ฅ ๋๋ค.
- DefaultOAuth2User ๋ /userInfo ์๋ํฌ์ธํธ ์์ฒญ์ผ๋ก ๋ฐ์ User ํด๋ ์ ์ ๋ณด๋ก ์์ฑ๋ ๊ฐ์ฒด์ด๋ค
- DefaultOidcUser ๋ OpenID Connect ์ธ์ฆ์ ํตํด ID Token ๋ฐ ํด๋ ์ ์ ๋ณด๊ฐ ํฌํจ๋ ๊ฐ์ฒด์ด๋ค
@AuthenticationPrincipal
- public void dashboard(@AuthenticationPrincipal OAuth2User principal or OidcUser principal) {}
- AuthenticationPrincipalArgumentResolver ํด๋์ค์์ ์์ฒญ์ ๊ฐ๋ก์ฑ์ด ๋ฐ์ธ๋ฉ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
- Authentication ๋ฅผ SecurityContex ๋ก๋ถํฐ ๊บผ๋ด์ด ์์ Principal ์์ฑ์ OAuth2User ํน์ OidcUser ํ์ ์ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๋ค
3. API ์ปค์คํ ์ค์
3-1). Authorization BaseUrl & Redirection BaseUrl
http
.oauth2Login(oauth2 -> oauth2
.loginPage("/login")
.loginProcessingUrl("/login/v1/oauth2/code/*")
.authorizationEndpoint(authorizationEndpointConfig ->
authorizationEndpointConfig.baseUri("/oauth2/v1/authorization"))
.redirectionEndpoint(redirectionEndpointConfig ->
redirectionEndpointConfig.baseUri("/login/v1/oauth2/code/*"))
)
;
- authorizationEndpoint().baseUrl(โ/oauth2/v1/authorizationโ) ์ ๊ถํ ๋ถ์ฌ ์์ฒญ BaseUri ๋ฅผ ์ปค์คํ
ํ๋ค
- 1๋จ๊ณ ๊ถํ ๋ถ์ฌ ์์ฒญ์ ์ฒ๋ฆฌํ๋ OAuth2AuthorizationRequestRedirectFilter ์์ ์์ฒญ์ ๋ํ ๋งค์นญ์ฌ๋ถ๋ฅผ ํ๋จํ๋ค
- ์ค์ ์์ ๋ณ๊ฒฝํ ๊ฐ์ด ํด๋ผ์ด์ธํธ์ ๋งํฌ ์ ๋ณด์ ์ผ์นํ๋๋ก ๋ง์ถ์ด์ผ ํ๋ค
- redirectionEndpoint.baseUri(โ/login/v1/oauth2/code/*โ) ์ ์ธ๊ฐ ์๋ต์ baseUri ๋ฅผ ์ปค์คํ
ํ๋ค
- Token ์์ฒญ์ ์ฒ๋ฆฌํ๋ OAuth2LoginAuthenticationFilter ์์ ์์ฒญ์ ๋ํ ๋งค์นญ์ฌ๋ถ๋ฅผ ํ๋จํ๋ค
- application.yml ์ค์ ํ์ผ์์ registration ์์ฑ์ redirectUri ์ค์ ์๋ ๋ณ๊ฒฝ๋ ๊ฐ์ ์ ์ฉํด์ผ ํ๋ค
- ์ธ๊ฐ์๋ฒ์ redirectUri ์ค์ ์๋ ๋ณ๊ฒฝ๋ ๊ฐ์ ์ ์ฉํด์ผ ํ๋ค
- loginProcessingUrl(โ/login/v1/oauth2/code/*โ) ๋ฅผ ์ค์ ํด๋ ๊ฒฐ๊ณผ๋ ๋์ผํ์ง๋ง redirectionEndpoint.baseUri ๊ฐ ๋ ์ฐ์ ์ด๋ค
- Token ์์ฒญ์ ์ฒ๋ฆฌํ๋ OAuth2LoginAuthenticationFilter ์์ ์์ฒญ์ ๋ํ ๋งค์นญ์ฌ๋ถ๋ฅผ ํ๋จํ๋ค
3-2). OAuth2AuthorizationRequestResolver
- Authorization Code Grant ๋ฐฉ์์์ ํด๋ผ์ด์ธํธ๊ฐ ์ธ๊ฐ์๋ฒ๋ก ๊ถํ๋ถ์ฌ ์์ฒญํ ๋ ์คํ๋๋ ํด๋์ค
- OAuth2AuthorizationRequestResolver ๋ OAuth 2.0 ์ธ๊ฐ ํ๋ ์์ํฌ์ ์ ์๋ ํ์ค ํ๋ผ๋ฏธํฐ ์ธ์ ๋ค๋ฅธ ํ๋ผ๋ฏธํฐ๋ฅผ ์ถ๊ฐํ๋ ์์ผ๋ก ์ธ๊ฐ ์์ฒญ์ ํ ๋ ์ฌ์ฉํ๋ค
- DefaultOAuth2AuthorizationRequestResolver ๊ฐ ๋ํดํธ ๊ตฌํ์ฒด๋ก ์ ๊ณต ๋๋ฉฐ Consumer
์์ฑ์ ์ปค์คํ ํ ๋ด์ฉ์ ๊ตฌํํ๋ค
@Bean
SecurityFilterChain oauth2SecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) -> requests.antMatchers("/home").permitAll()
.anyRequest().authenticated());
http.oauth2Login(authLogin ->
authLogin.authorizationEndpoint(authEndpoint ->
authEndpoint.authorizationRequestResolver(customOAuth2AuthenticationRequestResolver())));
return http.build();
}
private OAuth2AuthorizationRequestResolver customOAuth2AuthenticationRequestResolver() {
return new CustomOAuth2AuthorizationRequestResolver(clientRegistrationRepository, "/oauth2/authorization");
}
๋๊ธ๋จ๊ธฐ๊ธฐ