Google์ OAuth 2.0 ์ธ์ฆ ์์คํ ์ ๋ก๊ทธ์ธ์ ์ฌ์ฉํ๋ ค๋ฉด Google API ์ฝ์์์ ํ๋ก์ ํธ๋ฅผ ์ค์ ํ์ฌ OAuth 2.0 credentials(ํด๋ผ์ด์ธํธ ID์ Secret)์ ์ป์ด์ผ ํจ
Google OAuth 2.0์ OIDC ์คํ์ ์ค์ํ๊ณ ์์ผ๋ฉฐ, Open ID ์ธ์ฆ์ ๋ฐ์
Redirect URI๋ ๊ธฐ๋ณธ์ ์ผ๋ก {baseUrl}/login/oauth2/code/{registrationId} ๋ก ์ ํด์ ธ์์
์ธ์ฆ ํ๋ฆ์ ์์ฑํ OAuth ํด๋ผ์ด์ธํธ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด application.yml ํ์ผ์ ํ๋กํผํฐ ์ค์ ์ ํด์ค์ผ ํจ
์ฌ์ฉ์๊ฐ Google ์ธ์ฆ์ ์๋ฃํ๋ฉด ์ฌ์ฉ์๋ Oauth ํด๋ผ์ด์ธํธ์ ์ ๊ทผ ๊ถํ์ ๋ถ์ฌํ๊ณ , OAuth ํด๋ผ์ด์ธํธ๋ UserInfo Endpoint์์ ์ด๋ฉ์ผ ์ฃผ์์ ๊ธฐ๋ณธ ํ๋กํ ์ ๋ณด ๋ฑ์ ๊ฐ์ ธ์ ์ธ์ฆ๋ ์ธ์ ์ ์ค์ ํจ
CommonOAuth2Provider๋ Google, GitHub, Facebook, Okta์ ๊ฐ์ ์ ์๋ ค์ง ์ ๊ณต์๋ค์ ๋ํ ๊ธฐ๋ณธ ํด๋ผ์ด์ธํธ ์์ฑ์ ๋ฏธ๋ฆฌ ์ ์ํด ๋์์.
์๋ฅผ ๋ค์ด, ์ ๊ณต์์ authorization-uri, token-uri, user-info-uri๋ ์์ฃผ ๋ณ๊ฒฝ๋์ง ์๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ ๊ฐ์ ์ ๊ณตํ์ฌ ํ์ํ ์ค์ ์ ์ค์ผ ์ ์์.
์ด๋ก ์ธํด, Google ํด๋ผ์ด์ธํธ๋ฅผ ์ค์ ํ ๋, client-id์ client-secret ์์ฑ๋ง ๊ฐ์ง๊ณ Google OAuth ํด๋ผ์ด์ธํธ๋ฅผ ์ฌ์ฉํ ์ ์์.
spring:
security:
oauth2:
client:
registration:
google:
client-id: google-client-id
client-secret: google-client-secret
OAuth ํด๋ผ์ด์ธํธ ์์ฑ์ ์๋ ๊ธฐ๋ณธ๊ฐ ์ค์ ์ registrationId(google)๊ฐ CommonOAuth2Provider์์ GOOGLE ์ด๊ฑฐํ(๋์๋ฌธ์ ๊ตฌ๋ถ ์์)๊ณผ ์ผ์นํ๊ธฐ ๋๋ฌธ์ ์ ๋์ํ๋ค.
registrationId๋ฅผ ๋ค๋ฅด๊ฒ ์ง์ ํ๊ณ ์ถ์ ๊ฒฝ์ฐ์๋, provider ์์ฑ์ ์ด๋ค ์ ๊ณต์์ ์ค์ ์ ์ฐธ์กฐํ๋๋ก ํ ์ง ์ค์ ํ์ฌ, OAuth ํด๋ผ์ด์ธํธ ์์ฑ์ ์๋ ๊ธฐ๋ณธ๊ฐ ์ค์ ์ ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์๋๋ก ํ ์ ์๋ค.
spring:
security:
oauth2:
client:
registration:
google-login:
provider: google
client-id: google-client-id
client-secret: google-client-secret
registrationId๋ google-login์ผ๋ก ์ค์ ๋์ด ์๋ค.
provider ์์ฑ์ google๋ก ์ค์ ๋์ด ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด CommonOAuth2Provider.GOOGLE.getBuilder()์์ ์ค์ ๋ ํด๋ผ์ด์ธํธ ์์ฑ์ ์๋ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ ์ ์๋ค.
OAuth ํด๋ผ์ด์ธํธ ์๋ ๊ตฌ์ฑ ํด๋์ค๋ OAuth2ClientAutoConfiguration์ด๋ค.
์๋ ๊ตฌ์ฑ ํด๋์ค์์ ํ๋ ์ผ์
@Bean์ผ๋ก ๋ฑ๋ก@Bean์ผ๋ก ๋ฑ๋กํ๊ณ , httpSecurity.oauth2Login()์ ํตํด OAuth 2.0 ๋ก๊ทธ์ธ์ ํ์ฑํํฉ๋๋ค.์๋ ๊ตฌ์ฑ์ ์ฌ์ ์ ํ๋ ค๋ฉด
์ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ ์๊ฐ ๊ฐ๋ฅํ๋ค.
๋ณดํต์ 2๋ฒ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด์ ์ธ์ฆ ๋ก์ง์ ์ปค์คํ ํ๋ ๊ฒ ๊ฐ๋ค.
HttpSecurity.oauth2Login()์ OAuth2 ๋ก๊ทธ์ธ์ ์ปค์คํ
ํ๊ธฐ ์ํ ๋ค์ํ ๊ตฌ์ฑ ์ต์
์ ์ ๊ณตํ๋ค.
์ฃผ์ ๊ตฌ์ฑ ์ต์ ์ ํ๋กํ ์ฝ ์๋ํฌ์ธํธ์ ํด๋นํ๋ ๊ทธ๋ฃน์ผ๋ก ๋๋๋ค.
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.authorizationEndpoint(authorization -> authorization
...
)
.redirectionEndpoint(redirection -> redirection
...
)
.tokenEndpoint(token -> token
...
)
.userInfoEndpoint(userInfo -> userInfo
...
)
);
return http.build();
}
}
OAuth ํด๋ผ์ด์ธํธ๊ฐ ์ฌ์ฉ์๋ฅผ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ๋ณด๋ด์ ๊ถํ์ ๋ถ์ฌ๋ฐ๋ ๋ฐ ์ฌ์ฉํ๋ ์๋ํฌ์ธํธ๋ค.
์ฌ์ฉ์๋ ์ฌ๊ธฐ์ ๋ก๊ทธ์ธํ๊ณ , ํด๋ผ์ด์ธํธ๊ฐ ์์ฒญํ ์ ๊ทผ ๊ถํ์ ์น์ธํ๋ค. ๊ทธ๋ฐ ๋ค์, ์ธ์ฆ์ด ์๋ฃ๋๋ฉด Redirection URL๋ก ์ด๋ํ๊ฒ ๋๋ค.
authorizationEndpoint์ baseUri() ๋ฉ์๋๋ก authorization endpoint์ ๊ธฐ๋ณธ ๊ฒฝ๋ก๋ฅผ ๋ฐ๊ฟ ์ ์๋ค.
๊ธฐ๋ณธ ๊ฒฝ๋ก๋ OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/{registrationId}" ๋ก ์ง์ ๋์ด ์๋ค.
์ด ๊ฐ์ ๊ธฐ๋ณธ๊ฐ์ /oauth2/authorization์ด๊ณ ,
{registrationId}๋ ๋ฑ๋กํ ๊ฐ OAuth ํด๋ผ์ด์ธํธ(์: google, github ๋ฑ)์ ๊ณ ์ ์๋ณ์๋ฅผ ๋งํ๋ค.
์๋ฅผ ๋ค์ด, Google OAuth ํด๋ผ์ด์ธํธ๋ฅผ ๋ฑ๋กํ์ผ๋ฉด ์ด ๊ฐ์ "google"์ด ๋๋ค.
ํด๋ผ์ด์ธํธ๊ฐ ๊ถํ ๋ถ์ฌ ์ฝ๋๋ฅผ ์ก์ธ์ค ํ ํฐ์ผ๋ก ๊ตํํ๊ธฐ ์ํด, ์ผ๋ฐ์ ์ผ๋ก ํด๋ผ์ด์ธํธ ์ธ์ฆ์ ํตํด ์ฌ์ฉํ๋ ์๋ํฌ์ธํธ๋ค.
์ธ์ฆ ์๋ฒ๊ฐ ๋ฆฌ์์ค ์์ ์(์ฌ์ฉ์) ์ฌ์ฉ์ ์์ด์ ํธ(๋ธ๋ผ์ฐ์ )๋ฅผ ํตํด ํด๋ผ์ด์ธํธ์๊ฒ ์ธ์ฆ ์๊ฒฉ์ ํฌํจํ ์๋ต์ ๋ฐํํ๋ ๋ฐ ์ฌ์ฉํ๋ ์๋ํฌ์ธํธ๋ค.
OAuth 2.0 ๋ก๊ทธ์ธ์ Authorization Code Grant ๋ฐฉ์์ ํ์ฉํ๋ฏ๋ก, ์ธ์ฆ ์๊ฒฉ ์ฆ๋ช ์ Authorization Code๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก Authorization Response์ baseUri(๋ฆฌ๋๋ ์
์๋ํฌ์ธํธ)๋ /login/oauth2/code/{registrationId}์ด๋ฉฐ, ์ด๋ OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI์ ์ ์๋์ด ์๋ค.
Authorization Response baseUri๋ฅผ ์ปค์คํฐ๋ง์ด์งํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ค์ ํ ์ ์๋ค.
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.redirectionEndpoint(redirection -> redirection
.baseUri("/login/oauth2/callback/*") // ์ปค์คํ
์๋ํฌ์ธํธ ์ค์
...
)
);
return http.build();
}
}
Authorization Respoinse BaseUri๋ฅผ ์ปค์คํ ํ๋ค๋ฉด, ClientRegistration.redirectUri๊ฐ ์ปค์คํฐ๋ง์ด์ง๋ Authorization Response baseUri์ ์ผ์นํ๋์ง๋ ํ์ธํด์ผ ํ๋ค.
OpenID Connect Core 1.0 ์ฌ์์์ UserInfo Endpoint๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ๊ณ ์๋ค
UserInfo ์๋ํฌ์ธํธ๋ ์ธ์ฆ๋ ์ต์ข ์ฌ์ฉ์์ ๋ํ ํด๋ ์(Claims)์ ๋ฐํํ๋ OAuth 2.0 ๋ณดํธ ๋ฆฌ์์ค๋ก,
์ธ์ฆ๋ ์ต์ข ์ฌ์ฉ์์ ๋ํ ํด๋ ์์ ๋ฐํํ๋ OAuth 2.0 ๋ณดํธ ๋ฆฌ์์ค๋ก, ํด๋ผ์ด์ธํธ๋ OpenID Connect ์ธ์ฆ์ ํตํด ์ป์ ์ก์ธ์ค ํ ํฐ์ ์ฌ์ฉํ์ฌ UserInfo Endpoint์ ์์ฒญ์ ๋ณด๋ธ๋ค.
์ด ํด๋ ์์ ์ผ๋ฐ์ ์ผ๋ก ํด๋ ์์ ๋ํ ์ด๋ฆ-๊ฐ ์ ์ปฌ๋ ์ ์ ํฌํจํ๋ JSON ๊ฐ์ฒด๋ก ํํ๋๋ค.
UserInfo ์๋ํฌ์ธํธ์์ ํต์ ์ ๋ฐ๋์ TLS๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.(์น์ 16.17์ ์ฐธ์กฐ)
UserInfo ์๋ํฌ์ธํธ๋ ๋ฐ๋์ RFC 7231 [RFC7231]์ ์ ์๋ HTTP GET ๋ฐ HTTP POST ๋ฉ์๋๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค.
UserInfo ์๋ํฌ์ธํธ๋ ๋ฐ๋์ OAuth 2.0 ๋ฒ ์ด๋ฌ ํ ํฐ ์ฌ์ฉ๋ฒ [RFC6750]์ ๋ฐ๋ผ ์ก์ธ์ค ํ ํฐ์ ๋ฐ์๋ค์ฌ์ผ ํฉ๋๋ค.
UserInfo ์๋ํฌ์ธํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ ํด๋ผ์ด์ธํธ์ ๊ธฐํ ๋ธ๋ผ์ฐ์ ๊ธฐ๋ฐ ํด๋ผ์ด์ธํธ๊ฐ ์ ๊ทผํ ์ ์๋๋ก CORS [CORS] ๋๋ ๊ธฐํ ์ ์ ํ ๋ฐฉ๋ฒ์ ์ง์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
UserInfo ์๋ํฌ์ธํธ๋ ๋ค์ ํ์ ์น์ ์์ ์ค๋ช ๋ ์ฌ๋ฌ ๊ตฌ์ฑ ์ต์ ์ ํฌํจํ๊ณ ์๋ค.
DefaultOAuth2UserService๋ ํ์ค OAuth 2.0 ์ ๊ณต์(Provider)๋ฅผ ์ง์ํ๋ OAuth2UserService์ ๊ตฌํ์ฒด๋ค.
OAuth2UserService๋ UserInfo ์๋ํฌ์ธํธ์์ ์ต์ข ์ฌ์ฉ์(๋ฆฌ์์ค ์์ ์)์ ์์ฑ์ ๋ฐ์์จ๋ค.(์ด๋ ํด๋ผ์ด์ธํธ๊ฐ ์ธ์ฆ ํ๋ฆ ์ค์ ๋ถ์ฌ๋ฐ์ ์ก์ธ์ค ํ ํฐ์ ์ฌ์ฉํ๋ค.) ๊ทธ๋ฆฌ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ก OAuth2User ํํ์ AuthenticatedPrincipal์ ๋ฐํํ๋ค.
DefaultOAuth2UserService๋ UserInfo ์๋ํฌ์ธํธ์ ์์ฒญํ ๋ RestOperations(์ธํฐํ์ด์ค) ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ๋ค.
DefaultOAuth2UserService๋ฅผ ์ปค์คํฐ๋ง์ด์งํ๊ฑฐ๋ OAuth2UserService์ ์์ฒด ๊ตฌํ์ ์ ๊ณตํ๋ ๊ฒฝ์ฐ, ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑํด์ผ ํ๋ค.
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(this.oauth2UserService())
...
)
);
return http.build();
}
private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() {
...
}
}
OidcUserService ์์ฒด ๊ตฌํ์ ์ ๊ณตํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑํด์ผ ํ๋ค.
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.oidcUserService(this.oidcUserService())
...
)
);
return http.build();
}
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
...
}
}
๋ค์ ์ฝ๋๋ oauth2Login() DSL์์ ์ฌ์ฉํ ์ ์๋ ์ ์ฒด ๊ตฌ์ฑ ์ต์
์ด๋ค. ์ฐธ๊ณ ๋ง ํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค. ๋ฌผ๋ก DSL์ธ์๋ xml ์ค์ ์ผ๋ก๋ ๊ฐ๋ฅํ๋ค. ๊ตณ์ด ์ดํด๋ณด์ง ์์๋ค.
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.clientRegistrationRepository(this.clientRegistrationRepository())
.authorizedClientRepository(this.authorizedClientRepository())
.authorizedClientService(this.authorizedClientService())
.loginPage("/login")
.authorizationEndpoint(authorization -> authorization
.baseUri(this.authorizationRequestBaseUri())
.authorizationRequestRepository(this.authorizationRequestRepository())
.authorizationRequestResolver(this.authorizationRequestResolver())
)
.redirectionEndpoint(redirection -> redirection
.baseUri(this.authorizationResponseBaseUri())
)
.tokenEndpoint(token -> token
.accessTokenResponseClient(this.accessTokenResponseClient())
)
.userInfoEndpoint(userInfo -> userInfo
.userAuthoritiesMapper(this.userAuthoritiesMapper())
.userService(this.oauth2UserService())
.oidcUserService(this.oidcUserService())
)
);
return http.build();
}
}
Spring Security๋ OAuth2 ์ธ์ฆ์ ์ํ ๊ธฐ๋ณธํ์ด์ง๋ฅผ ๊ตฌ์ฑํ๊ณ ์๋ค. loginPage() api๋ฅผ ํตํด ๋ก๊ทธ์ธ ํ์ด์ง ๊ฒฝ๋ก ์ค์ ์ด ๊ฐ๋ฅํ๋ค.
OAuth2 ๋ก๊ทธ์ธ ํ์ด์ง๋ DefaultLoginPageGeneratingFilter์ ์ํด ์๋์ผ๋ก ์์ฑ๋๋ค.
ํ๋ก ํธ๊ฐ ๋ฐ๋ก ๊ตฌ์ฑ๋์ด ์๋ค๋ฉด, ๋ก๊ทธ์ธ ํ์ด์ง ์ค์ ์ ๋นผ๋ ๋๋ค.
๋ก๊ทธ์ธ ํ์ด์ง ์ค์ ์ ๋นผ๋ ๊ธฐ๋ณธ ๋ก๊ทธ์ธ ํ์ด์ง๋ ์ ๊ณต๋๋ฉฐ ๊ธฐ๋ณธ ๊ฒฝ๋ก๋ "/login" ๊ฒฝ๋ก๊ฐ ๋๋ค. ํ๋ก ํธ๊ฐ ๋ฐ๋ก ๊ตฌ์ฑ๋์ด ์๋ค๋ฉด, ํด๋น ๊ฒฝ๋ก์ ์ ๊ทผํ์ง ๋ชปํ๋๋ก ์ค์ ํ ํ์๋ ์์ ๊ฒ ๊ฐ๋ค.
ClientRegistration์ OAuth 2.0 ๋๋ OpenID Connect 1.0 ๊ณต๊ธ์์ ๋ฑ๋ก๋ ํด๋ผ์ด์ธํธ๋ฅผ ๋ํ๋ธ๋ค.
ClientRegistration ๊ฐ์ฒด๋ ํด๋ผ์ด์ธํธ ID, ํด๋ผ์ด์ธํธ secret, ์ธ์ฆ ๋ถ์ฌ ๋ฐฉ์, ๋ฆฌ๋๋ ์ URI, ์ค์ฝํ(scope), ์ธ์ฆ URI, ํ ํฐ URI ๋ฐ ๊ธฐํ ์ธ๋ถ ์ ๋ณด๋ฅผ ํฌํจํ๋ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
ClientRegistration ๋ฐ ๊ทธ ์์ฑ๋ค์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์ด ์๋ค.
public final class ClientRegistration {
private String registrationId;
private String clientId;
private String clientSecret;
private ClientAuthenticationMethod clientAuthenticationMethod;
private AuthorizationGrantType authorizationGrantType;
private String redirectUri;
private Set<String> scopes;
private ProviderDetails providerDetails;
private String clientName;
public class ProviderDetails {
private String authorizationUri;
private String tokenUri;
private UserInfoEndpoint userInfoEndpoint;
private String jwkSetUri;
private String issuerUri;
private Map<String, Object> configurationMetadata;
public class UserInfoEndpoint {
private String uri;
private AuthenticationMethod authenticationMethod;
private String userNameAttributeName;
}
}
}
ClientRegistrationRepository๋ OAuth 2.0 / OpenID Connect 1.0์ ClientRegistration ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๋ ์ ์ฅ์ ์ญํ ์ ํ๋ค.
ํด๋ผ์ด์ธํธ ๋ฑ๋ก ์ ๋ณด๋ ๊ถ๊ทน์ ์ผ๋ก ๊ด๋ จ๋ ์ธ์ฆ ์๋ฒ(Authorization Server)์ ์ ์ฅ๋๊ณ ์์ ๋ฉ๋๋ค. ์ด ์ ์ฅ์๋ ์ธ์ฆ ์๋ฒ์ ์ ์ฅ๋ ๊ธฐ๋ณธ ํด๋ผ์ด์ธํธ ๋ฑ๋ก ์ ๋ณด ์ค ์ผ๋ถ๋ฅผ ๊ฒ์ํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
Spring Boot ์๋ ์ค์ ์ spring.security.oauth2.client.registration.[registrationId] ์์ฑ ์๋์ ์๋ ๊ฐ๊ฐ์ ํ๋กํผํฐ๋ค์ ClientRegistration ์ธ์คํด์ค๋ก ๋ฐ์ธ๋ฉํ๊ณ , ๊ฐ๊ฐ์ ClientRegistration ์ธ์คํด์ค๋ฅผ ClientRegistrationRepository ๋ด์ ๊ตฌ์ฑํฉ๋๋ค.
ClientRegistrationRepository์ ๊ธฐ๋ณธ ๊ตฌํ์ฒด๋ InMemoryClientRegistrationRepository์ ๋๋ค.
์๋ ์ค์ ์ ๋ํ ClientRegistrationRepository๋ฅผ @Bean์ผ๋ก ApplicationContext์ ๋ฑ๋กํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์์ ํ์ ์ ์์กด์ฑ ์ฃผ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋๋ก ํฉ๋๋ค.
๋ค์์ ์์์ ๋๋ค:
@Controller
public class OAuth2ClientController {
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@GetMapping("/")
public String index() {
ClientRegistration oktaRegistration =
this.clientRegistrationRepository.findByRegistrationId("okta");
...
return "index";
}
}
OAuth2AuthorizedClient๋ ์น์ธ๋ ํด๋ผ์ด์ธํธ๋ฅผ ๋ํ๋ ๋๋ค. ํด๋ผ์ด์ธํธ๊ฐ ์น์ธ๋์๋ค๊ณ ๊ฐ์ฃผ๋๋ ๊ฒฝ์ฐ๋ ์ต์ข ์ฌ์ฉ์(๋ฆฌ์์ค ์์ ์)๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ๋ณดํธ๋ ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์๋๋ก ๊ถํ์ ๋ถ์ฌํ์ ๋์ ๋๋ค.
OAuth2AuthorizedClient๋ OAuth2AccessToken(๋ฐ ์ ํ์ ์ผ๋ก OAuth2RefreshToken)์ ClientRegistration(ํด๋ผ์ด์ธํธ)๊ณผ ๊ถํ์ ๋ถ์ฌํ ์ต์ข ์ฌ์ฉ์(Principal)์๊ฒ ์ฐ๊ฒฐํ๋ ์ญํ ์ ํฉ๋๋ค.
OAuth2AuthorizedClientRepository์ OAuth2AuthorizedClientService
OAuth2AuthorizedClientRepository๋ ์น ์์ฒญ ๊ฐ์ OAuth2AuthorizedClient๋ฅผ ์ ์ฅํ๋ ์ญํ ์ ๋ด๋นํ๋ฉฐ, OAuth2AuthorizedClientService๋ ์ ํ๋ฆฌ์ผ์ด์
์์ค์์ OAuth2AuthorizedClient๋ฅผ ๊ด๋ฆฌํ๋ ์ฃผ์ ์ญํ ์ ํฉ๋๋ค.
๊ฐ๋ฐ์ ๊ด์ ์์ OAuth2AuthorizedClientRepository ๋๋ OAuth2AuthorizedClientService๋ ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ๋ OAuth2AccessToken์ ์กฐํํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ ๋ณดํธ๋ ๋ฆฌ์์ค ์์ฒญ์ ์์ํ ์ ์๋๋ก ํฉ๋๋ค.
๋ค์์ ์์์ ๋๋ค:
@Controller
public class OAuth2ClientController {
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;
@GetMapping("/")
public String index(Authentication authentication) {
OAuth2AuthorizedClient authorizedClient =
this.authorizedClientService.loadAuthorizedClient("okta", authentication.getName());
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
return "index";
}
}
Spring Boot ์๋ ์ค์ ์ OAuth2AuthorizedClientRepository ๋๋ OAuth2AuthorizedClientService๋ฅผ @Bean์ผ๋ก ApplicationContext์ ๋ฑ๋กํฉ๋๋ค. ํ์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์์ ๋ฐ๋ผ ์ปค์คํ OAuth2AuthorizedClientRepository ๋๋ OAuth2AuthorizedClientService๋ฅผ @Bean์ผ๋ก ๋ฑ๋กํ์ฌ ๊ธฐ๋ณธ ์ค์ ์ ๋ฎ์ด์ธ ์ ์์ต๋๋ค.
OAuth2AuthorizedClientService์ ๊ธฐ๋ณธ ๊ตฌํ์ InMemoryOAuth2AuthorizedClientService์ด๋ฉฐ, ์ด๋ OAuth2AuthorizedClient ๊ฐ์ฒด๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํฉ๋๋ค.
๋์์ผ๋ก, JdbcOAuth2AuthorizedClientService๋ฅผ ์ค์ ํ์ฌ OAuth2AuthorizedClient ์ธ์คํด์ค๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ ์ ์์ต๋๋ค.
JdbcOAuth2AuthorizedClientService๋ OAuth 2.0 ํด๋ผ์ด์ธํธ ์คํค๋ง์์ ์ค๋ช ๋ ํ ์ด๋ธ ์ ์์ ์์กดํฉ๋๋ค.