最新の安定バージョンについては、Spring Security 6.3.1 を使用してください! |
コアインターフェース / クラス
ClientRegistration
ClientRegistration
は、OAuth 2.0 または OpenID Connect 1.0 プロバイダーに登録されたクライアントの表現です。
クライアント登録には、クライアント ID、クライアントシークレット、認可付与型、リダイレクト URI、スコープ、認可 URI、トークン URI、その他の詳細などの情報が保持されます。
ClientRegistration
とそのプロパティは次のように定義されています。
public final class ClientRegistration {
private String registrationId; (1)
private String clientId; (2)
private String clientSecret; (3)
private ClientAuthenticationMethod clientAuthenticationMethod; (4)
private AuthorizationGrantType authorizationGrantType; (5)
private String redirectUri; (6)
private Set<String> scopes; (7)
private ProviderDetails providerDetails;
private String clientName; (8)
public class ProviderDetails {
private String authorizationUri; (9)
private String tokenUri; (10)
private UserInfoEndpoint userInfoEndpoint;
private String jwkSetUri; (11)
private String issuerUri; (12)
private Map<String, Object> configurationMetadata; (13)
public class UserInfoEndpoint {
private String uri; (14)
private AuthenticationMethod authenticationMethod; (15)
private String userNameAttributeName; (16)
}
}
}
1 | registrationId : ClientRegistration を一意に識別する ID。 |
2 | clientId : クライアント識別子。 |
3 | clientSecret : クライアントのシークレット。 |
4 | clientAuthenticationMethod : プロバイダーでクライアントを認証するために使用される方法。サポートされている値は、client_secret_basic、client_secret_post、private_key_jwt、client_secret_jwt、および none (パブリッククライアント) [IETF] (英語) です。 |
5 | authorizationGrantType : OAuth 2.0 認証フレームワークは、4 つの認可付与 [IETF] (英語) 型を定義します。サポートされている値は、authorization_code 、client_credentials 、password 、拡張認可型 urn:ietf:params:oauth:grant-type:jwt-bearer です。 |
6 | redirectUri : エンドユーザーがクライアントへのアクセスを認証および認可した後に、認可サーバーがエンドユーザーのユーザーエージェントをリダイレクトするクライアントの登録済みリダイレクト URI。 |
7 | scopes : 認可リクエストフロー中にクライアントがリクエストしたスコープ(openid、メール、プロファイルなど)。 |
8 | clientName : クライアントに使用される説明的な名前。この名前は、自動生成されたログインページにクライアントの名前を表示するときなど、特定のシナリオで使用される場合があります。 |
9 | authorizationUri : 認可サーバーの認可エンドポイント URI。 |
10 | tokenUri : 認可サーバーのトークンエンドポイント URI。 |
11 | jwkSetUri : 認可サーバーから JSON Web キー (JWK) [IETF] (英語) セットを取得するために使用される URI。ID トークンの JSON Web 署名 (JWS) [IETF] (英語) およびオプションで UserInfo レスポンスを検証するために使用される暗号化キーが含まれます。 |
12 | issuerUri : OpenID Connect 1.0 プロバイダーまたは OAuth 2.0 Authorization Server の発行者識別子 uri を返します。 |
13 | configurationMetadata : OpenID プロバイダーの構成情報 (英語) 。この情報は、Spring Boot 2.x プロパティ spring.security.oauth2.client.provider.[providerId].issuerUri が構成されている場合にのみ利用できます。 |
14 | (userInfoEndpoint)uri : 認証されたエンドユーザーのクレーム / 属性にアクセスするために使用される UserInfo エンドポイント URI。 |
15 | (userInfoEndpoint)authenticationMethod : アクセストークンを UserInfo エンドポイントに送信するときに使用される認証方法。サポートされる値は、header、form、および query です。 |
16 | userNameAttributeName : エンドユーザーの名前または識別子を参照する UserInfo レスポンスで返される属性の名前。 |
ClientRegistration
は、OpenID Connect プロバイダーの構成エンドポイント (英語) または認可サーバーのメタデータエンドポイント [IETF] (英語) の検出を使用して最初に構成できます。
ClientRegistrations
は、次の例に見られるように、このメソッドで ClientRegistration
を構成するための便利なメソッドを提供します。
Java
Kotlin
ClientRegistration clientRegistration =
ClientRegistrations.fromIssuerLocation("https://idp.example.com/issuer").build();
val clientRegistration = ClientRegistrations.fromIssuerLocation("https://idp.example.com/issuer").build()
上記のコードは、シリーズ idp.example.com/issuer/.well-known/openid-configuration (英語)
、次に idp.example.com/.well-known/openid-configuration/issuer (英語)
、最後に idp.example.com/.well-known/oauth-authorization-server/issuer (英語)
で照会し、最初に停止して 200 レスポンスを返します。
別の方法として、ClientRegistrations.fromOidcIssuerLocation()
を使用して、OpenID Connect プロバイダーの構成エンドポイントのみを照会できます。
ReactiveClientRegistrationRepository
ReactiveClientRegistrationRepository
は、OAuth 2.0/OpenID Connect 1.0 ClientRegistration
のリポジトリとして機能します。
クライアント登録情報は最終的に保存され、関連する認可サーバーによって所有されます。このリポジトリは、認可サーバーに保存されているプライマリクライアント登録情報のサブセットを取得する機能を提供します。 |
Spring Boot 2.x 自動構成は、spring.security.oauth2.client.registration.[registrationId]
の各プロパティを ClientRegistration
のインスタンスにバインドし、ReactiveClientRegistrationRepository
内の各 ClientRegistration
インスタンスを構成します。
ReactiveClientRegistrationRepository のデフォルトの実装は InMemoryReactiveClientRegistrationRepository です。 |
また、自動構成は、ReactiveClientRegistrationRepository
を ApplicationContext
の @Bean
として登録し、アプリケーションで必要な場合に依存関係の注入に使用できるようにします。
次のリストに例を示します。
Java
Kotlin
@Controller
public class OAuth2ClientController {
@Autowired
private ReactiveClientRegistrationRepository clientRegistrationRepository;
@GetMapping("/")
public Mono<String> index() {
return this.clientRegistrationRepository.findByRegistrationId("okta")
...
.thenReturn("index");
}
}
@Controller
class OAuth2ClientController {
@Autowired
private lateinit var clientRegistrationRepository: ReactiveClientRegistrationRepository
@GetMapping("/")
fun index(): Mono<String> {
return this.clientRegistrationRepository.findByRegistrationId("okta")
...
.thenReturn("index")
}
}
OAuth2AuthorizedClient
OAuth2AuthorizedClient
は、認可クライアントの表現です。エンドユーザー(リソース所有者)がクライアントに保護されたリソースにアクセスする認可を与えた場合、クライアントは認可されたと見なされます。
OAuth2AuthorizedClient
は、OAuth2AccessToken
(およびオプションの OAuth2RefreshToken
)を、認可を認可した Principal
エンドユーザーである ClientRegistration
(クライアント)およびリソース所有者に関連付ける目的に役立ちます。
ServerOAuth2AuthorizedClientRepository/ReactiveOAuth2AuthorizedClientService
ServerOAuth2AuthorizedClientRepository
は、Web リクエスト間で OAuth2AuthorizedClient
を保持するロールを果たします。一方、ReactiveOAuth2AuthorizedClientService
の主なロールは、アプリケーションレベルで OAuth2AuthorizedClient
を管理することです。
開発者の観点から、ServerOAuth2AuthorizedClientRepository
または ReactiveOAuth2AuthorizedClientService
は、クライアントに関連付けられた OAuth2AccessToken
をルックアップする機能を提供し、保護されたリソースリクエストを開始するために使用できるようにします。
次のリストに例を示します。
Java
Kotlin
@Controller
public class OAuth2ClientController {
@Autowired
private ReactiveOAuth2AuthorizedClientService authorizedClientService;
@GetMapping("/")
public Mono<String> index(Authentication authentication) {
return this.authorizedClientService.loadAuthorizedClient("okta", authentication.getName())
.map(OAuth2AuthorizedClient::getAccessToken)
...
.thenReturn("index");
}
}
@Controller
class OAuth2ClientController {
@Autowired
private lateinit var authorizedClientService: ReactiveOAuth2AuthorizedClientService
@GetMapping("/")
fun index(authentication: Authentication): Mono<String> {
return this.authorizedClientService.loadAuthorizedClient<OAuth2AuthorizedClient>("okta", authentication.name)
.map { it.accessToken }
...
.thenReturn("index")
}
}
Spring Boot 2.x 自動構成は、ServerOAuth2AuthorizedClientRepository および / または ReactiveOAuth2AuthorizedClientService @Bean を ApplicationContext に登録します。ただし、アプリケーションは、カスタム ServerOAuth2AuthorizedClientRepository または ReactiveOAuth2AuthorizedClientService @Bean をオーバーライドして登録することを選択できます。 |
ReactiveOAuth2AuthorizedClientService
のデフォルトの実装は InMemoryReactiveOAuth2AuthorizedClientService
であり、OAuth2AuthorizedClient
をメモリに保存します。
あるいは、R2DBC 実装 R2dbcReactiveOAuth2AuthorizedClientService
は、データベースに OAuth2AuthorizedClient
を永続化するように構成することもできます。
R2dbcReactiveOAuth2AuthorizedClientService は、 OAuth 2.0 クライアントスキーマで説明されているテーブル定義に依存します。 |
ReactiveOAuth2AuthorizedClientManager/ReactiveOAuth2AuthorizedClientProvider
ReactiveOAuth2AuthorizedClientManager
は、OAuth2AuthorizedClient
の全体的な管理を担当します。
主な責務は次のとおりです。
ReactiveOAuth2AuthorizedClientProvider
を使用して、OAuth 2.0 クライアントを承認(または再承認)します。通常は
ReactiveOAuth2AuthorizedClientService
またはServerOAuth2AuthorizedClientRepository
を使用して、OAuth2AuthorizedClient
の永続性を委譲します。OAuth 2.0 クライアントが正常に承認(または再承認)されたときに
ReactiveOAuth2AuthorizationSuccessHandler
に委譲します。OAuth 2.0 クライアントが承認(または再承認)に失敗した場合の
ReactiveOAuth2AuthorizationFailureHandler
への委譲。
ReactiveOAuth2AuthorizedClientProvider
は、OAuth 2.0 クライアントを認可(または再認可)するための戦略を実装します。実装は通常、認可付与型を実装します。authorization_code
、client_credentials
など。
ReactiveOAuth2AuthorizedClientManager
のデフォルトの実装は DefaultReactiveOAuth2AuthorizedClientManager
です。これは、委譲ベースのコンポジットを使用して複数の認可付与型をサポートする可能性のある ReactiveOAuth2AuthorizedClientProvider
に関連付けられています。ReactiveOAuth2AuthorizedClientProviderBuilder
は、委譲ベースのコンポジットを構成および構築するために使用できます。
次のコードは、authorization_code
、refresh_token
、client_credentials
、password
認可付与型のサポートを提供する ReactiveOAuth2AuthorizedClientProvider
コンポジットを構成および構築する方法の例を示しています。
Java
Kotlin
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken()
.clientCredentials()
.password()
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ReactiveClientRegistrationRepository,
authorizedClientRepository: ServerOAuth2AuthorizedClientRepository): ReactiveOAuth2AuthorizedClientManager {
val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken()
.clientCredentials()
.password()
.build()
val authorizedClientManager = DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}
認可の試みが成功すると、DefaultReactiveOAuth2AuthorizedClientManager
は ReactiveOAuth2AuthorizationSuccessHandler
に委譲し、ReactiveOAuth2AuthorizationSuccessHandler
は(デフォルトで) ServerOAuth2AuthorizedClientRepository
を介して OAuth2AuthorizedClient
を保存します。再認証の失敗の場合、たとえばリフレッシュトークンは無効になり、以前に保存された OAuth2AuthorizedClient
は RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler
を介して ServerOAuth2AuthorizedClientRepository
から削除されます。デフォルトの動作は、setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler)
および setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)
を介してカスタマイズできます。
DefaultReactiveOAuth2AuthorizedClientManager
は、型 Function<OAuth2AuthorizeRequest, Mono<Map<String, Object>>>
の contextAttributesMapper
にも関連付けられています。これは、OAuth2AuthorizeRequest
から OAuth2AuthorizationContext
に関連付けられる属性の Map
への属性のマッピングを担当します。これは、必要な(サポートされている)属性を ReactiveOAuth2AuthorizedClientProvider
に提供する必要がある場合に役立ちます。PasswordReactiveOAuth2AuthorizedClientProvider
では、リソース所有者の username
および password
が OAuth2AuthorizationContext.getAttributes()
で使用可能である必要があります。
次のコードは、contextAttributesMapper
の例を示しています。
Java
Kotlin
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.password()
.refreshToken()
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Assuming the `username` and `password` are supplied as `ServerHttpRequest` parameters,
// map the `ServerHttpRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper());
return authorizedClientManager;
}
private Function<OAuth2AuthorizeRequest, Mono<Map<String, Object>>> contextAttributesMapper() {
return authorizeRequest -> {
Map<String, Object> contextAttributes = Collections.emptyMap();
ServerWebExchange exchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName());
ServerHttpRequest request = exchange.getRequest();
String username = request.getQueryParams().getFirst(OAuth2ParameterNames.USERNAME);
String password = request.getQueryParams().getFirst(OAuth2ParameterNames.PASSWORD);
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
contextAttributes = new HashMap<>();
// `PasswordReactiveOAuth2AuthorizedClientProvider` requires both attributes
contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
}
return Mono.just(contextAttributes);
};
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ReactiveClientRegistrationRepository,
authorizedClientRepository: ServerOAuth2AuthorizedClientRepository): ReactiveOAuth2AuthorizedClientManager {
val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.password()
.refreshToken()
.build()
val authorizedClientManager = DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
// Assuming the `username` and `password` are supplied as `ServerHttpRequest` parameters,
// map the `ServerHttpRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper())
return authorizedClientManager
}
private fun contextAttributesMapper(): Function<OAuth2AuthorizeRequest, Mono<MutableMap<String, Any>>> {
return Function { authorizeRequest ->
var contextAttributes: MutableMap<String, Any> = mutableMapOf()
val exchange: ServerWebExchange = authorizeRequest.getAttribute(ServerWebExchange::class.java.name)!!
val request: ServerHttpRequest = exchange.request
val username: String? = request.queryParams.getFirst(OAuth2ParameterNames.USERNAME)
val password: String? = request.queryParams.getFirst(OAuth2ParameterNames.PASSWORD)
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
contextAttributes = hashMapOf()
// `PasswordReactiveOAuth2AuthorizedClientProvider` requires both attributes
contextAttributes[OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME] = username!!
contextAttributes[OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME] = password!!
}
Mono.just(contextAttributes)
}
}
DefaultReactiveOAuth2AuthorizedClientManager
は、ServerWebExchange
のコンテキストである以内にを使用するように設計されています。ServerWebExchange
コンテキストの外側を操作する場合は、代わりに AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
を使用してください。
サービスアプリケーションは、AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
をいつ使用するかの一般的な使用例です。サービスアプリケーションは多くの場合、ユーザーの操作なしでバックグラウンドで実行され、通常はユーザーアカウントではなくシステムレベルのアカウントで実行されます。client_credentials
許可型で構成された OAuth 2.0 クライアントは、サービスアプリケーションの型と見なすことができます。
次のコードは、client_credentials
付与型のサポートを提供する AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
を構成する方法の例を示しています。
Java
Kotlin
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ReactiveOAuth2AuthorizedClientService authorizedClientService) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ReactiveClientRegistrationRepository,
authorizedClientService: ReactiveOAuth2AuthorizedClientService): ReactiveOAuth2AuthorizedClientManager {
val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build()
val authorizedClientManager = AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}