コアインターフェース / クラス
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)
}
}
public static final class ClientSettings {
private boolean requireProofKey; (17)
}
}| 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 プロパティ spring.security.oauth2.client.provider.[providerId].issuerUri が構成されている場合にのみ利用できます。 |
| 14 | (userInfoEndpoint)uri: 認証されたエンドユーザーのクレーム / 属性にアクセスするために使用される UserInfo エンドポイント URI。 |
| 15 | (userInfoEndpoint)authenticationMethod: アクセストークンを UserInfo エンドポイントに送信するときに使用される認証方法。サポートされる値は、header、form、および query です。 |
| 16 | userNameAttributeName: エンドユーザーの名前または識別子を参照する UserInfo レスポンスで返される属性の名前。 |
| 17 | requireProofKey: true の場合、または authorizationGrantType が none の場合、PKCE はデフォルトで有効になります。 |
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 自動構成は、spring.security.oauth2.client.registration.[registrationId] の各プロパティを ClientRegistration のインスタンスにバインドし、ReactiveClientRegistrationRepository 内の各 ClientRegistration インスタンスを構成します。
|
また、自動構成は、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 自動構成は、 |
ReactiveOAuth2AuthorizedClientService のデフォルトの実装は InMemoryReactiveOAuth2AuthorizedClientService であり、OAuth2AuthorizedClient をメモリに保存します。
あるいは、R2DBC 実装 R2dbcReactiveOAuth2AuthorizedClientService は、データベースに OAuth2AuthorizedClient を永続化するように構成することもできます。
|
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
}