コア構成
Spring Boot サンプル
Spring Boot は、OAuth 2.0 ログインの完全な自動構成機能を提供します。
このセクションでは、Google を 認証プロバイダーとして使用して OAuth 2.0 ログイン WebFlux サンプル [GitHub] (英語) を構成する方法を示し、次のトピックについて説明します。
初期設定
ログインに Google の OAuth 2.0 認証システムを使用するには、Google API コンソールでプロジェクトを設定し、OAuth 2.0 資格情報を取得する必要があります。
認証用の Google の OAuth 2.0 実装 (英語) は OpenID Connect 1.0 (英語) 仕様に準拠しており、OpenID 認定 (英語) です。 |
「OAuth 2.0 のセットアップ」セクションから始めて、OpenID Connect (英語) ページの指示に従います。
「OAuth 2.0 資格情報の取得」の手順を完了すると、クライアント ID とクライアントシークレットで構成される資格情報を持つ新しい OAuth クライアントが作成されます。
リダイレクト URI の設定
リダイレクト URI は、エンドユーザーのユーザーエージェントが Google で認証され、同意ページで OAuth クライアント ( 前の手順で作成された ) へのアクセスが許可された後にリダイレクトされるアプリケーション内のパスです。
「リダイレクト URI の設定」サブセクションで、承認されたリダイレクト URI フィールドが localhost:8080/login/oauth2/code/google
に設定されていることを確認します。
デフォルトのリダイレクト URI テンプレートは |
OAuth クライアントがプロキシサーバーの背後で実行されている場合は、プロキシサーバー構成をチェックして、アプリケーションが正しく構成されていることを確認することをお勧めします。また、 |
application.yml
を構成する
Google を使用した新しい OAuth クライアントが作成されたため、認証フローに OAuth クライアントを使用するようにアプリケーションを構成する必要があります。そうするために:
application.yml
に移動して、次の構成を設定します。例 1: OAuth クライアントのプロパティspring: security: oauth2: client: registration: (1) google: (2) client-id: google-client-id client-secret: google-client-secret
1 spring.security.oauth2.client.registration
は、OAuth クライアントプロパティの基本プロパティプレフィックスです。2 ベースプロパティプレフィックスの後には、google などの ClientRegistration
の ID が続きます。client-id
およびclient-secret
プロパティの値を、前に作成した OAuth 2.0 資格情報に置き換えます。
アプリケーションを起動します
Spring Boot サンプルを起動し、localhost:8080
に移動します。次に、デフォルトの自動生成ログインページにリダイレクトされ、Google へのリンクが表示されます。
Google リンクをクリックすると、認証のために Google にリダイレクトされます。
Google アカウントの資格情報で認証した後、次のページに 同意 画面が表示されます。同意 画面では、前に作成した OAuth クライアントへのアクセスを認可するか拒否するかを尋ねられます。許可をクリックして、OAuth クライアントがメールアドレスと基本的なプロファイル情報にアクセスすることを承認します。
この時点で、OAuth クライアントは UserInfo エンドポイント (英語) からメールアドレスと基本プロファイル情報を取得し、認証済みセッションを確立します。
Spring Boot プロパティマッピング
次の表に、Spring Boot OAuth クライアントプロパティの ClientRegistration プロパティへのマッピングの概要を示します。
Spring Boot | ClientRegistration |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ClientRegistration は、spring.security.oauth2.client.provider.[providerId].issuer-uri プロパティを指定することにより、OpenID Connect プロバイダーの構成エンドポイント (英語) または認可サーバーのメタデータエンドポイント [IETF] (英語) の検出を使用して最初に構成できます。 |
CommonOAuth2Provider
CommonOAuth2Provider
は、Google、GitHub、Facebook、Okta などの多くのよく知られたプロバイダーのデフォルトのクライアントプロパティのセットを事前定義します。
例: authorization-uri
、token-uri
、user-info-uri
は、プロバイダーでは頻繁に変更されません。必要な構成を減らすためにデフォルト値を提供することは理にかなっています。
前に示したように、Google クライアントを構成する場合、client-id
プロパティと client-secret
プロパティのみが必要です。
次のリストに例を示します。
spring:
security:
oauth2:
client:
registration:
google:
client-id: google-client-id
client-secret: google-client-secret
registrationId (google )は CommonOAuth2Provider の GOOGLE enum (大文字と小文字を区別しない)と一致するため、クライアントプロパティの自動デフォルト設定はここでシームレスに機能します。 |
google-login
など、別の registrationId
を指定する場合は、provider
プロパティを構成することにより、クライアントプロパティの自動デフォルト設定を活用できます。
次のリストに例を示します。
spring:
security:
oauth2:
client:
registration:
google-login: (1)
provider: google (2)
client-id: google-client-id
client-secret: google-client-secret
1 | registrationId は google-login に設定されます。 |
2 | provider プロパティは google に設定され、CommonOAuth2Provider.GOOGLE.getBuilder() で設定されたクライアントプロパティの自動デフォルト設定を活用します。 |
カスタムプロバイダープロパティの構成
マルチテナンシーをサポートする OAuth 2.0 プロバイダーがいくつかあります。これにより、テナント(またはサブドメイン)ごとに異なるプロトコルエンドポイントが作成されます。
例: Okta に登録された OAuth クライアントは特定のサブドメインに割り当てられ、独自のプロトコルエンドポイントを持ちます。
これらの場合のために、Spring Boot はカスタムプロバイダープロパティを構成するための次の基本プロパティを提供します: spring.security.oauth2.client.provider.[providerId]
。
次のリストに例を示します。
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
provider:
okta: (1)
authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize
token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token
user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo
user-name-attribute: sub
jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys
1 | 基本プロパティ(spring.security.oauth2.client.provider.okta )により、プロトコルエンドポイントの場所をカスタム構成できます。 |
Spring Boot 自動構成のオーバーライド
OAuth クライアントをサポートするための Spring Boot 自動構成クラスは ReactiveOAuth2ClientAutoConfiguration
です。
次のタスクを実行します。
構成された OAuth クライアントプロパティからの
ClientRegistration
で構成されるReactiveClientRegistrationRepository
@Bean
を登録します。SecurityWebFilterChain
@Bean
を登録し、serverHttpSecurity.oauth2Login()
を介して OAuth 2.0 ログインを有効にします。
特定の要件に基づいて自動構成をオーバーライドする必要がある場合、次の方法でオーバーライドできます。
ReactiveClientRegistrationRepository @Bean を登録する
次の例は、ReactiveClientRegistrationRepository
@Bean
を登録する方法を示しています。
Java
Kotlin
@Configuration
public class OAuth2LoginConfig {
@Bean
public ReactiveClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryReactiveClientRegistrationRepository(this.googleClientRegistration());
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
}
}
@Configuration
class OAuth2LoginConfig {
@Bean
fun clientRegistrationRepository(): ReactiveClientRegistrationRepository {
return InMemoryReactiveClientRegistrationRepository(googleClientRegistration())
}
private fun googleClientRegistration(): ClientRegistration {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build()
}
}
SecurityWebFilterChain @Bean を登録する
次の例は、SecurityWebFilterChain
@Bean
を @EnableWebFluxSecurity
に登録し、serverHttpSecurity.oauth2Login()
を介して OAuth 2.0 ログインを有効にする方法を示しています。
Java
Kotlin
@Configuration
@EnableWebFluxSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(authorize -> authorize
.anyExchange().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
}
@Configuration
@EnableWebFluxSecurity
class OAuth2LoginSecurityConfig {
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
http {
authorizeExchange {
authorize(anyExchange, authenticated)
}
oauth2Login { }
}
return http.build()
}
}
自動構成を完全にオーバーライドする
次の例は、ReactiveClientRegistrationRepository
@Bean
と SecurityWebFilterChain
@Bean
を登録することにより、自動構成を完全にオーバーライドする方法を示しています。
Java
Kotlin
@Configuration
@EnableWebFluxSecurity
public class OAuth2LoginConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(authorize -> authorize
.anyExchange().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public ReactiveClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryReactiveClientRegistrationRepository(this.googleClientRegistration());
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
}
}
@Configuration
@EnableWebFluxSecurity
class OAuth2LoginConfig {
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
http {
authorizeExchange {
authorize(anyExchange, authenticated)
}
oauth2Login { }
}
return http.build()
}
@Bean
fun clientRegistrationRepository(): ReactiveClientRegistrationRepository {
return InMemoryReactiveClientRegistrationRepository(googleClientRegistration())
}
private fun googleClientRegistration(): ClientRegistration {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build()
}
}
Spring Boot を使用しない Java 構成
Spring Boot を使用できず、CommonOAuth2Provider
の事前定義プロバイダーの 1 つ (Google など) を構成したい場合は、次の構成を適用します。
Java
Kotlin
@Configuration
@EnableWebFluxSecurity
public class OAuth2LoginConfig {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange(authorize -> authorize
.anyExchange().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public ReactiveClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryReactiveClientRegistrationRepository(this.googleClientRegistration());
}
@Bean
public ReactiveOAuth2AuthorizedClientService authorizedClientService(
ReactiveClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository);
}
@Bean
public ServerOAuth2AuthorizedClientRepository authorizedClientRepository(
ReactiveOAuth2AuthorizedClientService authorizedClientService) {
return new AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService);
}
private ClientRegistration googleClientRegistration() {
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.build();
}
}
@Configuration
@EnableWebFluxSecurity
class OAuth2LoginConfig {
@Bean
fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
http {
authorizeExchange {
authorize(anyExchange, authenticated)
}
oauth2Login { }
}
return http.build()
}
@Bean
fun clientRegistrationRepository(): ReactiveClientRegistrationRepository {
return InMemoryReactiveClientRegistrationRepository(googleClientRegistration())
}
@Bean
fun authorizedClientService(
clientRegistrationRepository: ReactiveClientRegistrationRepository
): ReactiveOAuth2AuthorizedClientService {
return InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository)
}
@Bean
fun authorizedClientRepository(
authorizedClientService: ReactiveOAuth2AuthorizedClientService
): ServerOAuth2AuthorizedClientRepository {
return AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository(authorizedClientService)
}
private fun googleClientRegistration(): ClientRegistration {
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.build()
}
}