認可付与サポート
このセクションでは、Spring Security による認可付与のサポートについて説明します。
認証コード
認証コード [IETF] (英語) 付与の詳細については、OAuth 2.0 認証フレームワークを参照してください。 |
認可の取得
認可コードの付与については、認可リクエスト / レスポンス [IETF] (英語) プロトコルフローを参照してください。 |
認可リクエストの開始
OAuth2AuthorizationRequestRedirectFilter は OAuth2AuthorizationRequestResolver を使用して OAuth2AuthorizationRequest を解決し、エンドユーザーのユーザーエージェントを認可サーバーの認可エンドポイントにリダイレクトすることで認可コード付与フローを開始します。
OAuth2AuthorizationRequestResolver の主なロールは、提供された Web リクエストから OAuth2AuthorizationRequest を解決することです。デフォルトの実装 DefaultOAuth2AuthorizationRequestResolver は、(デフォルトの)パス /oauth2/authorization/{registrationId} で一致し、registrationId を抽出し、それを使用して、関連付けられた ClientRegistration の OAuth2AuthorizationRequest を構築します。
OAuth 2.0 クライアント登録の次の Spring Boot プロパティを検討してください。
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/authorized/okta"
scope: read, write
provider:
okta:
authorization-uri: https://dev-1234.oktapreview.com/oauth2/v1/authorize
token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token 上記のプロパティを指定すると、ベースパス /oauth2/authorization/okta を使用したリクエストは、OAuth2AuthorizationRequestRedirectFilter による認証リクエストリダイレクトを開始し、最終的に認証コード付与フローを開始します。
|
OAuth 2.0 クライアントがパブリッククライアント [IETF] (英語) の場合、OAuth 2.0 クライアントの登録を次のように構成します。
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-authentication-method: none
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/authorized/okta"
# ...パブリッククライアントは、コード交換用の証明キー [IETF] (英語) (PKCE)を使用してサポートされます。クライアントが信頼できない環境(ネイティブアプリケーションや Web ブラウザーベースのアプリケーションなど)で実行されているため、資格情報の機密性を維持できない場合、次の条件が満たされると PKCE が自動的に使用されます。
client-secretは省略(または空)されておりclient-authentication-methodはnoneに設定されます (ClientAuthenticationMethod.NONE)
または
ClientRegistration.clientSettings.requireProofKeyがtrueの場合 (この場合、ClientRegistration.authorizationGrantTypeはauthorization_codeである必要があります。)
OAuth 2.0 プロバイダーが機密クライアント [IETF] (英語) の PKCE をサポートしている場合は、(オプションで) |
次の構成では、サポートされているすべての URI テンプレート変数を使用します。
spring:
security:
oauth2:
client:
registration:
okta:
# ...
redirect-uri: "{baseScheme}://{baseHost}{basePort}{basePath}/authorized/{registrationId}"
# ...
|
URI テンプレート変数を使用して redirect-uri を構成すると、OAuth 2.0 クライアントがプロキシサーバーの背後で実行されている場合に特に役立ちます。そうすることで、redirect-uri を展開するときに X-Forwarded-* ヘッダーが使用されるようになります。
認可リクエストのカスタマイズ
OAuth2AuthorizationRequestResolver が実現できる主な使用例の 1 つは、OAuth 2.0 認可フレームワークで定義された標準パラメーターを超える追加パラメーターで認可リクエストをカスタマイズする機能です。
例: OpenID Connect は、OAuth 2.0 認証フレームワーク [IETF] (英語) で定義された標準パラメーターから拡張された、認証コードフロー (英語) の追加の OAuth 2.0 リクエストパラメーターを定義します。これらの拡張パラメーターの 1 つは prompt パラメーターです。
|
以下の例は、リクエストパラメーター prompt=consent を含めることにより、oauth2Login() の認可リクエストをカスタマイズする Consumer<OAuth2AuthorizationRequest.Builder> で DefaultOAuth2AuthorizationRequestResolver を構成する方法を示しています。
Java
Kotlin
@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
.oauth2Login((oauth2) -> oauth2
.authorizationEndpoint((authorization) -> authorization
.authorizationRequestResolver(
authorizationRequestResolver(this.clientRegistrationRepository)
)
)
);
return http.build();
}
private OAuth2AuthorizationRequestResolver authorizationRequestResolver(
ClientRegistrationRepository clientRegistrationRepository) {
DefaultOAuth2AuthorizationRequestResolver authorizationRequestResolver =
new DefaultOAuth2AuthorizationRequestResolver(
clientRegistrationRepository, "/oauth2/authorization");
authorizationRequestResolver.setAuthorizationRequestCustomizer(
authorizationRequestCustomizer());
return authorizationRequestResolver;
}
private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer() {
return customizer -> customizer
.additionalParameters((params) -> params.put("prompt", "consent"));
}
}
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Autowired
private lateinit var customClientRegistrationRepository: ClientRegistrationRepository
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeHttpRequests {
authorize(anyRequest, authenticated)
}
oauth2Login {
authorizationEndpoint {
authorizationRequestResolver = authorizationRequestResolver(customClientRegistrationRepository)
}
}
}
return http.build()
}
private fun authorizationRequestResolver(
clientRegistrationRepository: ClientRegistrationRepository?): OAuth2AuthorizationRequestResolver {
val authorizationRequestResolver = DefaultOAuth2AuthorizationRequestResolver(
clientRegistrationRepository, "/oauth2/authorization")
authorizationRequestResolver.setAuthorizationRequestCustomizer(
authorizationRequestCustomizer())
return authorizationRequestResolver
}
private fun authorizationRequestCustomizer(): Consumer<OAuth2AuthorizationRequest.Builder> {
return Consumer { customizer ->
customizer
.additionalParameters { params -> params["prompt"] = "consent" }
}
}
}
追加のリクエストパラメーターが特定のプロバイダーで常に同じであるという単純なユースケースの場合、authorization-uri プロパティに直接追加できます。
例: リクエストパラメーター prompt の値がプロバイダー okta の常に consent である場合、次のように構成できます。
spring:
security:
oauth2:
client:
provider:
okta:
authorization-uri: https://dev-1234.oktapreview.com/oauth2/v1/authorize?prompt=consent 上記の例は、標準パラメーターの上にカスタムパラメーターを追加する一般的なユースケースを示しています。または、要件がより高度な場合は、OAuth2AuthorizationRequest.authorizationRequestUri プロパティをオーバーライドすることで、認可リクエスト URI の構築を完全に制御できます。
|
次の例は、前の例からの authorizationRequestCustomizer() のバリエーションを示しており、代わりに OAuth2AuthorizationRequest.authorizationRequestUri プロパティをオーバーライドします。
Java
Kotlin
private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer() {
return customizer -> customizer
.authorizationRequestUri((uriBuilder) -> uriBuilder
.queryParam("prompt", "consent").build());
}
private fun authorizationRequestCustomizer(): Consumer<OAuth2AuthorizationRequest.Builder> {
return Consumer { customizer: OAuth2AuthorizationRequest.Builder ->
customizer
.authorizationRequestUri { uriBuilder: UriBuilder ->
uriBuilder
.queryParam("prompt", "consent").build()
}
}
}
認証リクエストの保存
AuthorizationRequestRepository は、認可リクエストが開始されてから認可レスポンスが受信されるまで(コールバック)、OAuth2AuthorizationRequest の永続化を担当します。
|
AuthorizationRequestRepository のデフォルトの実装は HttpSessionOAuth2AuthorizationRequestRepository で、HttpSession に OAuth2AuthorizationRequest を格納します。
AuthorizationRequestRepository のカスタム実装がある場合は、次のように構成できます。
Java
Kotlin
XML
@Configuration
@EnableWebSecurity
public class OAuth2ClientSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Client((oauth2) -> oauth2
.authorizationCodeGrant((codeGrant) -> codeGrant
.authorizationRequestRepository(this.authorizationRequestRepository())
// ...
)
)
.oauth2Login((oauth2) -> oauth2
.authorizationEndpoint((endpoint) -> endpoint
.authorizationRequestRepository(this.authorizationRequestRepository())
// ...
)
);
return http.build();
}
@Bean
public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
return new CustomOAuth2AuthorizationRequestRepository();
}
}
@Configuration
@EnableWebSecurity
class OAuth2ClientSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Client {
authorizationCodeGrant {
authorizationRequestRepository = authorizationRequestRepository()
}
}
}
return http.build()
}
}
<http>
<oauth2-client>
<authorization-code-grant authorization-request-repository-ref="authorizationRequestRepository"/>
</oauth2-client>
</http>
アクセストークンのリクエスト
認可コードの付与については、アクセストークンリクエスト / レスポンス [IETF] (英語) プロトコルフローを参照してください。 |
認証コード付与の OAuth2AccessTokenResponseClient のデフォルトの実装は RestClientAuthorizationCodeTokenResponseClient です。これは、RestClient インスタンスを使用して、認証サーバーのトークンエンドポイントでアクセストークンの認証コードを交換します。
RestClientAuthorizationCodeTokenResponseClient は非常に柔軟性が高く、認可コード付与に対する OAuth 2.0 アクセストークンのリクエストとレスポンスをカスタマイズするためのオプションをいくつか提供します。詳細については、次のユースケースから選択してください。
アクセストークンリクエストのカスタマイズ
RestClientAuthorizationCodeTokenResponseClient は、OAuth 2.0 アクセストークンリクエストの HTTP ヘッダーとリクエストパラメーターをカスタマイズするためのフックを提供します。
リクエストヘッダーのカスタマイズ
HTTP ヘッダーをカスタマイズするには、次の 2 つのオプションがあります。
addHeadersConverter()を呼び出して追加のヘッダーを追加するsetHeadersConverter()を呼び出してヘッダーを完全にカスタマイズする
addHeadersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのヘッダーに影響を与えずに、追加のヘッダーを含めることができます。次の例では、registrationId が spring の場合にリクエストに User-Agent ヘッダーを追加します。
Java
Kotlin
RestClientAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new RestClientAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.addHeadersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
HttpHeaders headers = new HttpHeaders();
if (clientRegistration.getRegistrationId().equals("spring")) {
headers.set(HttpHeaders.USER_AGENT, "my-user-agent");
}
return headers;
});
val accessTokenResponseClient = RestClientAuthorizationCodeTokenResponseClient()
accessTokenResponseClient.addHeadersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val headers = HttpHeaders()
if (clientRegistration.getRegistrationId() == "spring") {
headers[HttpHeaders.USER_AGENT] = "my-user-agent"
}
headers
}
DefaultOAuth2TokenRequestHeadersConverter を再利用するか、setHeadersConverter() を使用してカスタム実装を提供することで、ヘッダーを完全にカスタマイズできます。次の例では、DefaultOAuth2TokenRequestHeadersConverter を再利用し、encodeClientCredentials を無効にして、HTTP 基本認証情報が application/x-www-form-urlencoded でエンコードされないようにしています。
Java
Kotlin
DefaultOAuth2TokenRequestHeadersConverter headersConverter =
new DefaultOAuth2TokenRequestHeadersConverter();
headersConverter.setEncodeClientCredentials(false);
RestClientAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new RestClientAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.setHeadersConverter(headersConverter);
val headersConverter = DefaultOAuth2TokenRequestHeadersConverter()
headersConverter.setEncodeClientCredentials(false)
val accessTokenResponseClient = RestClientAuthorizationCodeTokenResponseClient()
accessTokenResponseClient.setHeadersConverter(headersConverter)
リクエストパラメーターのカスタマイズ
リクエストパラメーターをカスタマイズするには、次の 3 つのオプションがあります。
addParametersConverter()を呼び出して追加のパラメーターを追加するsetParametersConverter()を呼び出してパラメーターを上書きするsetParametersCustomizer()を呼び出してパラメーターを完全にカスタマイズする
|
addParametersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのパラメーターに影響を与えずに、追加のパラメーターを含めることができます。次の例では、registrationId が keycloak の場合に、リクエストに audience パラメーターを追加します。
Java
Kotlin
RestClientAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new RestClientAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.addParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
if (clientRegistration.getRegistrationId().equals("keycloak")) {
parameters.set(OAuth2ParameterNames.AUDIENCE, "my-audience");
}
return parameters;
});
val accessTokenResponseClient = RestClientAuthorizationCodeTokenResponseClient()
accessTokenResponseClient.addParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "keycloak") {
parameters[OAuth2ParameterNames.AUDIENCE] = "my-audience"
}
parameters
}
setParametersConverter() を使用してデフォルトのパラメーターを上書きできます。次の例では、registrationId が okta の場合に client_id パラメーターを上書きします。
Java
Kotlin
RestClientAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new RestClientAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.setParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
LinkedMultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
if (clientRegistration.getRegistrationId().equals("okta")) {
parameters.set(OAuth2ParameterNames.CLIENT_ID, "my-client");
}
return parameters;
});
val parametersConverter = DefaultOAuth2TokenRequestParametersConverter<OAuth2AuthorizationCodeGrantRequest>()
parametersConverter.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
val accessTokenResponseClient = RestClientAuthorizationCodeTokenResponseClient()
accessTokenResponseClient.setParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "okta") {
parameters[OAuth2ParameterNames.CLIENT_ID] = "my-client"
}
parameters
}
setParametersCustomizer() を使用すると、パラメーターを完全にカスタマイズできます (デフォルトパラメーターの省略を含む)。次の例では、リクエストに client_assertion パラメーターが存在する場合に client_id パラメーターを省略します。
Java
Kotlin
RestClientAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new RestClientAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.setParametersCustomizer(parameters -> {
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID);
}
});
val accessTokenResponseClient = RestClientAuthorizationCodeTokenResponseClient()
accessTokenResponseClient.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
アクセストークンレスポンスのカスタマイズ
RestClientAuthorizationCodeTokenResponseClient は、OAuth 2.0 アクセストークンレスポンスのレスポンスパラメーターとエラー処理をカスタマイズするためのフックを提供します。
RestClient のカスタマイズ
事前設定された RestClient を setRestClient() に提供することで、トークンレスポンスをカスタマイズできます。デフォルトの RestClient は次のように設定されています。
RestClient 構成 Java
Kotlin
RestClient restClient = RestClient.builder()
.messageConverters(messageConverters -> {
messageConverters.clear();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
})
.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
.build();
RestClientAuthorizationCodeTokenResponseClient accessTokenResponseClient =
new RestClientAuthorizationCodeTokenResponseClient();
accessTokenResponseClient.setRestClient(restClient);
val restClient = RestClient.builder()
.messageConverters { messageConverters ->
messageConverters.clear()
messageConverters.add(FormHttpMessageConverter())
messageConverters.add(OAuth2AccessTokenResponseHttpMessageConverter())
}
.defaultStatusHandler(OAuth2ErrorResponseErrorHandler())
.build()
val accessTokenResponseClient = RestClientAuthorizationCodeTokenResponseClient()
accessTokenResponseClient.setRestClient(restClient)
OAuth2AccessTokenResponseHttpMessageConverter は、OAuth 2.0 アクセストークンレスポンスの HttpMessageConverter です。setAccessTokenResponseConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2AccessTokenResponse への変換をカスタマイズできます。デフォルトの実装は DefaultMapOAuth2AccessTokenResponseConverter です。
OAuth2ErrorResponseErrorHandler は、400 Bad Request などの OAuth 2.0 エラーを処理できる ResponseErrorHandler です。OAuth2ErrorHttpMessageConverter を使用して、OAuth 2.0 エラーパラメーターを OAuth2Error に変換します。setErrorConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2Error への変換をカスタマイズできます。
Spring MVC |
レスポンスパラメーターのカスタマイズ
次の例は、トークンレスポンスパラメーターを OAuth2AccessTokenResponse に変換することをカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
accessTokenResponseMessageConverter.setAccessTokenResponseConverter(parameters -> {
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build();
});
val accessTokenResponseMessageConverter = OAuth2AccessTokenResponseHttpMessageConverter()
accessTokenResponseMessageConverter.setAccessTokenResponseConverter { parameters ->
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build()
}
エラー処理のカスタマイズ
次の例は、Error パラメーターから OAuth2Error への変換をカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2ErrorHttpMessageConverter errorConverter =
new OAuth2ErrorHttpMessageConverter();
errorConverter.setErrorConverter(parameters -> {
// ...
return new OAuth2Error("custom-error", "custom description", "custom-uri");
});
OAuth2ErrorResponseErrorHandler errorHandler =
new OAuth2ErrorResponseErrorHandler();
errorHandler.setErrorConverter(errorConverter);
val errorConverter = OAuth2ErrorHttpMessageConverter()
errorConverter.setErrorConverter { parameters ->
// ...
return OAuth2Error("custom-error", "custom description", "custom-uri")
}
val errorHandler = OAuth2ErrorResponseErrorHandler()
errorHandler.setErrorConverter(errorConverter)
DSL を使用してカスタマイズする
RestClientAuthorizationCodeTokenResponseClient をカスタマイズする場合でも、独自の OAuth2AccessTokenResponseClient 実装を提供する場合でも、次のように DSL を使用して構成できます ( Bean を公開する代わりに)。
Java
Kotlin
XML
@Configuration
@EnableWebSecurity
public class OAuth2ClientSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Client((oauth2) -> oauth2
.authorizationCodeGrant((codeGrant) -> codeGrant
.accessTokenResponseClient(this.accessTokenResponseClient())
// ...
)
);
return http.build();
}
}
@Configuration
@EnableWebSecurity
class OAuth2ClientSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Client {
authorizationCodeGrant {
accessTokenResponseClient = accessTokenResponseClient()
}
}
}
return http.build()
}
}
<http>
<oauth2-client>
<authorization-code-grant access-token-response-client-ref="accessTokenResponseClient"/>
</oauth2-client>
</http>
リフレッシュトークン
リフレッシュトークン [IETF] (英語) の詳細については、OAuth 2.0 認証フレームワークを参照してください。 |
アクセストークンのリフレッシュ
リフレッシュトークンの付与については、アクセストークンリクエスト / レスポンス [IETF] (英語) プロトコルフローを参照してください。 |
リフレッシュトークン付与の OAuth2AccessTokenResponseClient のデフォルト実装は RestClientRefreshTokenTokenResponseClient です。これは、RestClient インスタンスを使用して、認可サーバーのトークンエンドポイントでアクセストークンを取得します。
RestClientRefreshTokenTokenResponseClient は非常に柔軟性が高く、リフレッシュトークン付与に対する OAuth 2.0 アクセストークンのリクエストとレスポンスをカスタマイズするためのオプションをいくつか提供します。詳細については、次のユースケースから選択してください。
アクセストークンリクエストのカスタマイズ
RestClientRefreshTokenTokenResponseClient は、OAuth 2.0 アクセストークンリクエストの HTTP ヘッダーとリクエストパラメーターをカスタマイズするためのフックを提供します。
リクエストヘッダーのカスタマイズ
HTTP ヘッダーをカスタマイズするには、次の 2 つのオプションがあります。
addHeadersConverter()を呼び出して追加のヘッダーを追加するsetHeadersConverter()を呼び出してヘッダーを完全にカスタマイズする
addHeadersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのヘッダーに影響を与えずに、追加のヘッダーを含めることができます。次の例では、registrationId が spring の場合にリクエストに User-Agent ヘッダーを追加します。
Java
Kotlin
RestClientRefreshTokenTokenResponseClient accessTokenResponseClient =
new RestClientRefreshTokenTokenResponseClient();
accessTokenResponseClient.addHeadersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
HttpHeaders headers = new HttpHeaders();
if (clientRegistration.getRegistrationId().equals("spring")) {
headers.set(HttpHeaders.USER_AGENT, "my-user-agent");
}
return headers;
});
val accessTokenResponseClient = RestClientRefreshTokenTokenResponseClient()
accessTokenResponseClient.addHeadersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val headers = HttpHeaders()
if (clientRegistration.getRegistrationId() == "spring") {
headers[HttpHeaders.USER_AGENT] = "my-user-agent"
}
headers
}
DefaultOAuth2TokenRequestHeadersConverter を再利用するか、setHeadersConverter() を使用してカスタム実装を提供することで、ヘッダーを完全にカスタマイズできます。次の例では、DefaultOAuth2TokenRequestHeadersConverter を再利用し、encodeClientCredentials を無効にして、HTTP 基本認証情報が application/x-www-form-urlencoded でエンコードされないようにしています。
Java
Kotlin
DefaultOAuth2TokenRequestHeadersConverter headersConverter =
new DefaultOAuth2TokenRequestHeadersConverter();
headersConverter.setEncodeClientCredentials(false);
RestClientRefreshTokenTokenResponseClient accessTokenResponseClient =
new RestClientRefreshTokenTokenResponseClient();
accessTokenResponseClient.setHeadersConverter(headersConverter);
val headersConverter = DefaultOAuth2TokenRequestHeadersConverter()
headersConverter.setEncodeClientCredentials(false)
val accessTokenResponseClient = RestClientRefreshTokenTokenResponseClient()
accessTokenResponseClient.setHeadersConverter(headersConverter)
リクエストパラメーターのカスタマイズ
リクエストパラメーターをカスタマイズするには、次の 3 つのオプションがあります。
addParametersConverter()を呼び出して追加のパラメーターを追加するsetParametersConverter()を呼び出してパラメーターを上書きするsetParametersCustomizer()を呼び出してパラメーターを完全にカスタマイズする
|
addParametersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのパラメーターに影響を与えずに、追加のパラメーターを含めることができます。次の例では、registrationId が keycloak の場合に、リクエストに audience パラメーターを追加します。
Java
Kotlin
RestClientRefreshTokenTokenResponseClient accessTokenResponseClient =
new RestClientRefreshTokenTokenResponseClient();
accessTokenResponseClient.addParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
if (clientRegistration.getRegistrationId().equals("keycloak")) {
parameters.set(OAuth2ParameterNames.AUDIENCE, "my-audience");
}
return parameters;
});
val accessTokenResponseClient = RestClientRefreshTokenTokenResponseClient()
accessTokenResponseClient.addParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "keycloak") {
parameters[OAuth2ParameterNames.AUDIENCE] = "my-audience"
}
parameters
}
setParametersConverter() を使用してデフォルトのパラメーターを上書きできます。次の例では、registrationId が okta の場合に client_id パラメーターを上書きします。
Java
Kotlin
RestClientRefreshTokenTokenResponseClient accessTokenResponseClient =
new RestClientRefreshTokenTokenResponseClient();
accessTokenResponseClient.setParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
LinkedMultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
if (clientRegistration.getRegistrationId().equals("okta")) {
parameters.set(OAuth2ParameterNames.CLIENT_ID, "my-client");
}
return parameters;
});
val parametersConverter = DefaultOAuth2TokenRequestParametersConverter<OAuth2RefreshTokenGrantRequest>()
parametersConverter.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
val accessTokenResponseClient = RestClientRefreshTokenTokenResponseClient()
accessTokenResponseClient.setParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "okta") {
parameters[OAuth2ParameterNames.CLIENT_ID] = "my-client"
}
parameters
}
setParametersCustomizer() を使用すると、パラメーターを完全にカスタマイズできます (デフォルトパラメーターの省略を含む)。次の例では、リクエストに client_assertion パラメーターが存在する場合に client_id パラメーターを省略します。
Java
Kotlin
RestClientRefreshTokenTokenResponseClient accessTokenResponseClient =
new RestClientRefreshTokenTokenResponseClient();
accessTokenResponseClient.setParametersCustomizer(parameters -> {
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID);
}
});
val accessTokenResponseClient = RestClientRefreshTokenTokenResponseClient()
accessTokenResponseClient.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
アクセストークンレスポンスのカスタマイズ
RestClientRefreshTokenTokenResponseClient は、OAuth 2.0 アクセストークンレスポンスのレスポンスパラメーターとエラー処理をカスタマイズするためのフックを提供します。
RestClient のカスタマイズ
事前設定された RestClient を setRestClient() に提供することで、トークンレスポンスをカスタマイズできます。デフォルトの RestClient は次のように設定されています。
RestClient 構成 Java
Kotlin
RestClient restClient = RestClient.builder()
.messageConverters(messageConverters -> {
messageConverters.clear();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
})
.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
.build();
RestClientRefreshTokenTokenResponseClient accessTokenResponseClient =
new RestClientRefreshTokenTokenResponseClient();
accessTokenResponseClient.setRestClient(restClient);
val restClient = RestClient.builder()
.messageConverters { messageConverters ->
messageConverters.clear()
messageConverters.add(FormHttpMessageConverter())
messageConverters.add(OAuth2AccessTokenResponseHttpMessageConverter())
}
.defaultStatusHandler(OAuth2ErrorResponseErrorHandler())
.build()
val accessTokenResponseClient = RestClientRefreshTokenTokenResponseClient()
accessTokenResponseClient.setRestClient(restClient)
OAuth2AccessTokenResponseHttpMessageConverter は、OAuth 2.0 アクセストークンレスポンスの HttpMessageConverter です。setAccessTokenResponseConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2AccessTokenResponse への変換をカスタマイズできます。デフォルトの実装は DefaultMapOAuth2AccessTokenResponseConverter です。
OAuth2ErrorResponseErrorHandler は、400 Bad Request などの OAuth 2.0 エラーを処理できる ResponseErrorHandler です。OAuth2ErrorHttpMessageConverter を使用して、OAuth 2.0 エラーパラメーターを OAuth2Error に変換します。setErrorConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2Error への変換をカスタマイズできます。
Spring MVC |
レスポンスパラメーターのカスタマイズ
次の例は、トークンレスポンスパラメーターを OAuth2AccessTokenResponse に変換することをカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
accessTokenResponseMessageConverter.setAccessTokenResponseConverter(parameters -> {
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build();
});
val accessTokenResponseMessageConverter = OAuth2AccessTokenResponseHttpMessageConverter()
accessTokenResponseMessageConverter.setAccessTokenResponseConverter { parameters ->
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build()
}
エラー処理のカスタマイズ
次の例は、Error パラメーターから OAuth2Error への変換をカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2ErrorHttpMessageConverter errorConverter =
new OAuth2ErrorHttpMessageConverter();
errorConverter.setErrorConverter(parameters -> {
// ...
return new OAuth2Error("custom-error", "custom description", "custom-uri");
});
OAuth2ErrorResponseErrorHandler errorHandler =
new OAuth2ErrorResponseErrorHandler();
errorHandler.setErrorConverter(errorConverter);
val errorConverter = OAuth2ErrorHttpMessageConverter()
errorConverter.setErrorConverter { parameters ->
// ...
return OAuth2Error("custom-error", "custom description", "custom-uri")
}
val errorHandler = OAuth2ErrorResponseErrorHandler()
errorHandler.setErrorConverter(errorConverter)
ビルダーを使用してカスタマイズする
RestClientRefreshTokenTokenResponseClient をカスタマイズするか、独自の OAuth2AccessTokenResponseClient 実装を提供するかにかかわらず、次のように OAuth2AuthorizedClientProviderBuilder を使用して構成できます ( Bean を公開する代わりに)。
Java
Kotlin
// Customize
OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenTokenResponseClient = ...
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken((configurer) -> configurer.accessTokenResponseClient(refreshTokenTokenResponseClient))
.build();
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Customize
val refreshTokenTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> = ...
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken { it.accessTokenResponseClient(refreshTokenTokenResponseClient) }
.build()
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
|
OAuth2RefreshToken は、authorization_code 付与型のアクセストークンレスポンスでオプションとして返されます。OAuth2AuthorizedClient.getRefreshToken() が利用可能で、OAuth2AuthorizedClient.getAccessToken() が期限切れの場合、RefreshTokenOAuth2AuthorizedClientProvider によって自動的にリフレッシュされます。
クライアント資格情報
クライアント資格情報 [IETF] (英語) 付与の詳細については、OAuth 2.0 認可フレームワークを参照してください。 |
アクセストークンのリクエスト
クライアント資格情報の付与については、アクセストークンリクエスト / レスポンス [IETF] (英語) プロトコルフローを参照してください。 |
クライアント資格情報付与の OAuth2AccessTokenResponseClient のデフォルト実装は RestClientClientCredentialsTokenResponseClient です。これは、RestClient インスタンスを使用して、認可サーバーのトークンエンドポイントでアクセストークンを取得します。
RestClientClientCredentialsTokenResponseClient は非常に柔軟性が高く、クライアント資格情報の付与に対する OAuth 2.0 アクセストークンのリクエストとレスポンスをカスタマイズするためのオプションをいくつか提供します。詳細については、次のユースケースから選択してください。
アクセストークンリクエストのカスタマイズ
RestClientClientCredentialsTokenResponseClient は、OAuth 2.0 アクセストークンリクエストの HTTP ヘッダーとリクエストパラメーターをカスタマイズするためのフックを提供します。
リクエストヘッダーのカスタマイズ
HTTP ヘッダーをカスタマイズするには、次の 2 つのオプションがあります。
addHeadersConverter()を呼び出して追加のヘッダーを追加するsetHeadersConverter()を呼び出してヘッダーを完全にカスタマイズする
addHeadersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのヘッダーに影響を与えずに、追加のヘッダーを含めることができます。次の例では、registrationId が spring の場合にリクエストに User-Agent ヘッダーを追加します。
Java
Kotlin
RestClientClientCredentialsTokenResponseClient accessTokenResponseClient =
new RestClientClientCredentialsTokenResponseClient();
accessTokenResponseClient.addHeadersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
HttpHeaders headers = new HttpHeaders();
if (clientRegistration.getRegistrationId().equals("spring")) {
headers.set(HttpHeaders.USER_AGENT, "my-user-agent");
}
return headers;
});
val accessTokenResponseClient = RestClientClientCredentialsTokenResponseClient()
accessTokenResponseClient.addHeadersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val headers = HttpHeaders()
if (clientRegistration.getRegistrationId() == "spring") {
headers[HttpHeaders.USER_AGENT] = "my-user-agent"
}
headers
}
DefaultOAuth2TokenRequestHeadersConverter を再利用するか、setHeadersConverter() を使用してカスタム実装を提供することで、ヘッダーを完全にカスタマイズできます。次の例では、DefaultOAuth2TokenRequestHeadersConverter を再利用し、encodeClientCredentials を無効にして、HTTP 基本認証情報が application/x-www-form-urlencoded でエンコードされないようにしています。
Java
Kotlin
DefaultOAuth2TokenRequestHeadersConverter headersConverter =
new DefaultOAuth2TokenRequestHeadersConverter();
headersConverter.setEncodeClientCredentials(false);
RestClientClientCredentialsTokenResponseClient accessTokenResponseClient =
new RestClientClientCredentialsTokenResponseClient();
accessTokenResponseClient.setHeadersConverter(headersConverter);
val headersConverter = DefaultOAuth2TokenRequestHeadersConverter()
headersConverter.setEncodeClientCredentials(false)
val accessTokenResponseClient = RestClientClientCredentialsTokenResponseClient()
accessTokenResponseClient.setHeadersConverter(headersConverter)
リクエストパラメーターのカスタマイズ
リクエストパラメーターをカスタマイズするには、次の 3 つのオプションがあります。
addParametersConverter()を呼び出して追加のパラメーターを追加するsetParametersConverter()を呼び出してパラメーターを上書きするsetParametersCustomizer()を呼び出してパラメーターを完全にカスタマイズする
|
addParametersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのパラメーターに影響を与えずに、追加のパラメーターを含めることができます。次の例では、registrationId が keycloak の場合に、リクエストに audience パラメーターを追加します。
Java
Kotlin
RestClientClientCredentialsTokenResponseClient accessTokenResponseClient =
new RestClientClientCredentialsTokenResponseClient();
accessTokenResponseClient.addParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
if (clientRegistration.getRegistrationId().equals("keycloak")) {
parameters.set(OAuth2ParameterNames.AUDIENCE, "my-audience");
}
return parameters;
});
val accessTokenResponseClient = RestClientClientCredentialsTokenResponseClient()
accessTokenResponseClient.addParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "keycloak") {
parameters[OAuth2ParameterNames.AUDIENCE] = "my-audience"
}
parameters
}
setParametersConverter() を使用してデフォルトのパラメーターを上書きできます。次の例では、registrationId が okta の場合に client_id パラメーターを上書きします。
Java
Kotlin
RestClientClientCredentialsTokenResponseClient accessTokenResponseClient =
new RestClientClientCredentialsTokenResponseClient();
accessTokenResponseClient.setParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
LinkedMultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
if (clientRegistration.getRegistrationId().equals("okta")) {
parameters.set(OAuth2ParameterNames.CLIENT_ID, "my-client");
}
return parameters;
});
val parametersConverter = DefaultOAuth2TokenRequestParametersConverter<OAuth2ClientCredentialsGrantRequest>()
parametersConverter.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
val accessTokenResponseClient = RestClientClientCredentialsTokenResponseClient()
accessTokenResponseClient.setParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "okta") {
parameters[OAuth2ParameterNames.CLIENT_ID] = "my-client"
}
parameters
}
setParametersCustomizer() を使用すると、パラメーターを完全にカスタマイズできます (デフォルトパラメーターの省略を含む)。次の例では、リクエストに client_assertion パラメーターが存在する場合に client_id パラメーターを省略します。
Java
Kotlin
RestClientClientCredentialsTokenResponseClient accessTokenResponseClient =
new RestClientClientCredentialsTokenResponseClient();
accessTokenResponseClient.setParametersCustomizer(parameters -> {
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID);
}
});
val accessTokenResponseClient = RestClientClientCredentialsTokenResponseClient()
accessTokenResponseClient.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
アクセストークンレスポンスのカスタマイズ
RestClientClientCredentialsTokenResponseClient は、OAuth 2.0 アクセストークンレスポンスのレスポンスパラメーターとエラー処理をカスタマイズするためのフックを提供します。
RestClient のカスタマイズ
事前設定された RestClient を setRestClient() に提供することで、トークンレスポンスをカスタマイズできます。デフォルトの RestClient は次のように設定されています。
RestClient 構成 Java
Kotlin
RestClient restClient = RestClient.builder()
.messageConverters(messageConverters -> {
messageConverters.clear();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
})
.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
.build();
RestClientClientCredentialsTokenResponseClient accessTokenResponseClient =
new RestClientClientCredentialsTokenResponseClient();
accessTokenResponseClient.setRestClient(restClient);
val restClient = RestClient.builder()
.messageConverters { messageConverters ->
messageConverters.clear()
messageConverters.add(FormHttpMessageConverter())
messageConverters.add(OAuth2AccessTokenResponseHttpMessageConverter())
}
.defaultStatusHandler(OAuth2ErrorResponseErrorHandler())
.build()
val accessTokenResponseClient = RestClientClientCredentialsTokenResponseClient()
accessTokenResponseClient.setRestClient(restClient)
OAuth2AccessTokenResponseHttpMessageConverter は、OAuth 2.0 アクセストークンレスポンスの HttpMessageConverter です。setAccessTokenResponseConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2AccessTokenResponse への変換をカスタマイズできます。デフォルトの実装は DefaultMapOAuth2AccessTokenResponseConverter です。
OAuth2ErrorResponseErrorHandler は、400 Bad Request などの OAuth 2.0 エラーを処理できる ResponseErrorHandler です。OAuth2ErrorHttpMessageConverter を使用して、OAuth 2.0 エラーパラメーターを OAuth2Error に変換します。setErrorConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2Error への変換をカスタマイズできます。
Spring MVC |
レスポンスパラメーターのカスタマイズ
次の例は、トークンレスポンスパラメーターを OAuth2AccessTokenResponse に変換することをカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
accessTokenResponseMessageConverter.setAccessTokenResponseConverter(parameters -> {
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build();
});
val accessTokenResponseMessageConverter = OAuth2AccessTokenResponseHttpMessageConverter()
accessTokenResponseMessageConverter.setAccessTokenResponseConverter { parameters ->
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build()
}
エラー処理のカスタマイズ
次の例は、Error パラメーターから OAuth2Error への変換をカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2ErrorHttpMessageConverter errorConverter =
new OAuth2ErrorHttpMessageConverter();
errorConverter.setErrorConverter(parameters -> {
// ...
return new OAuth2Error("custom-error", "custom description", "custom-uri");
});
OAuth2ErrorResponseErrorHandler errorHandler =
new OAuth2ErrorResponseErrorHandler();
errorHandler.setErrorConverter(errorConverter);
val errorConverter = OAuth2ErrorHttpMessageConverter()
errorConverter.setErrorConverter { parameters ->
// ...
return OAuth2Error("custom-error", "custom description", "custom-uri")
}
val errorHandler = OAuth2ErrorResponseErrorHandler()
errorHandler.setErrorConverter(errorConverter)
ビルダーを使用してカスタマイズする
RestClientClientCredentialsTokenResponseClient をカスタマイズするか、独自の OAuth2AccessTokenResponseClient 実装を提供するかにかかわらず、次のように OAuth2AuthorizedClientProviderBuilder を使用して構成できます ( Bean を公開する代わりに)。
Java
Kotlin
// Customize
OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsTokenResponseClient = ...
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials((configurer) -> configurer.accessTokenResponseClient(clientCredentialsTokenResponseClient))
.build();
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Customize
val clientCredentialsTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> = ...
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials { it.accessTokenResponseClient(clientCredentialsTokenResponseClient) }
.build()
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
|
アクセストークンの使用
OAuth 2.0 クライアント登録の次の Spring Boot プロパティを検討してください。
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
authorization-grant-type: client_credentials
scope: read, write
provider:
okta:
token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token さらに、次の OAuth2AuthorizedClientManager @Bean を検討してください。
Java
Kotlin
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build()
val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}
上記のプロパティと Bean を指定すると、次のように OAuth2AccessToken を取得できます。
Java
Kotlin
@Controller
public class OAuth2ClientController {
@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;
@GetMapping("/")
public String index(Authentication authentication,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) {
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(authentication)
.attributes(attrs -> {
attrs.put(HttpServletRequest.class.getName(), servletRequest);
attrs.put(HttpServletResponse.class.getName(), servletResponse);
})
.build();
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
// ...
return "index";
}
}
class OAuth2ClientController {
@Autowired
private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
@GetMapping("/")
fun index(authentication: Authentication?,
servletRequest: HttpServletRequest,
servletResponse: HttpServletResponse): String {
val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(authentication)
.attributes(Consumer { attrs: MutableMap<String, Any> ->
attrs[HttpServletRequest::class.java.name] = servletRequest
attrs[HttpServletResponse::class.java.name] = servletResponse
})
.build()
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
// ...
return "index"
}
}
|
JWT ベアラー
JWT ベアラー [IETF] (英語) 付与の詳細については、OAuth 2.0 クライアント認証および認可付与の JSON Web トークン(JWT)プロファイルを参照してください。 |
アクセストークンのリクエスト
JWT Bearer Grant については、アクセストークンリクエスト / レスポンス [IETF] (英語) プロトコルフローを参照してください。 |
JWT ベアラー付与の OAuth2AccessTokenResponseClient のデフォルト実装は RestClientJwtBearerTokenResponseClient です。これは、RestClient インスタンスを使用して、認可サーバーのトークンエンドポイントでアクセストークンを取得します。
RestClientJwtBearerTokenResponseClient は非常に柔軟性が高く、JWT ベアラー付与の OAuth 2.0 アクセストークンリクエストとレスポンスをカスタマイズするためのオプションをいくつか提供します。詳細については、次のユースケースから選択してください。
アクセストークンリクエストのカスタマイズ
RestClientJwtBearerTokenResponseClient は、OAuth 2.0 アクセストークンリクエストの HTTP ヘッダーとリクエストパラメーターをカスタマイズするためのフックを提供します。
リクエストヘッダーのカスタマイズ
HTTP ヘッダーをカスタマイズするには、次の 2 つのオプションがあります。
addHeadersConverter()を呼び出して追加のヘッダーを追加するsetHeadersConverter()を呼び出してヘッダーを完全にカスタマイズする
addHeadersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのヘッダーに影響を与えずに、追加のヘッダーを含めることができます。次の例では、registrationId が spring の場合にリクエストに User-Agent ヘッダーを追加します。
Java
Kotlin
RestClientJwtBearerTokenResponseClient accessTokenResponseClient =
new RestClientJwtBearerTokenResponseClient();
accessTokenResponseClient.addHeadersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
HttpHeaders headers = new HttpHeaders();
if (clientRegistration.getRegistrationId().equals("spring")) {
headers.set(HttpHeaders.USER_AGENT, "my-user-agent");
}
return headers;
});
val accessTokenResponseClient = RestClientJwtBearerTokenResponseClient()
accessTokenResponseClient.addHeadersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val headers = HttpHeaders()
if (clientRegistration.getRegistrationId() == "spring") {
headers[HttpHeaders.USER_AGENT] = "my-user-agent"
}
headers
}
DefaultOAuth2TokenRequestHeadersConverter を再利用するか、setHeadersConverter() を使用してカスタム実装を提供することで、ヘッダーを完全にカスタマイズできます。次の例では、DefaultOAuth2TokenRequestHeadersConverter を再利用し、encodeClientCredentials を無効にして、HTTP 基本認証情報が application/x-www-form-urlencoded でエンコードされないようにしています。
Java
Kotlin
DefaultOAuth2TokenRequestHeadersConverter headersConverter =
new DefaultOAuth2TokenRequestHeadersConverter();
headersConverter.setEncodeClientCredentials(false);
RestClientJwtBearerTokenResponseClient accessTokenResponseClient =
new RestClientJwtBearerTokenResponseClient();
accessTokenResponseClient.setHeadersConverter(headersConverter);
val headersConverter = DefaultOAuth2TokenRequestHeadersConverter()
headersConverter.setEncodeClientCredentials(false)
val accessTokenResponseClient = RestClientJwtBearerTokenResponseClient()
accessTokenResponseClient.setHeadersConverter(headersConverter)
リクエストパラメーターのカスタマイズ
リクエストパラメーターをカスタマイズするには、次の 3 つのオプションがあります。
addParametersConverter()を呼び出して追加のパラメーターを追加するsetParametersConverter()を呼び出してパラメーターを上書きするsetParametersCustomizer()を呼び出してパラメーターを完全にカスタマイズする
|
addParametersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのパラメーターに影響を与えずに、追加のパラメーターを含めることができます。次の例では、registrationId が keycloak の場合に、リクエストに audience パラメーターを追加します。
Java
Kotlin
RestClientJwtBearerTokenResponseClient accessTokenResponseClient =
new RestClientJwtBearerTokenResponseClient();
accessTokenResponseClient.addParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
if (clientRegistration.getRegistrationId().equals("keycloak")) {
parameters.set(OAuth2ParameterNames.AUDIENCE, "my-audience");
}
return parameters;
});
val accessTokenResponseClient = RestClientJwtBearerTokenResponseClient()
accessTokenResponseClient.addParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "keycloak") {
parameters[OAuth2ParameterNames.AUDIENCE] = "my-audience"
}
parameters
}
setParametersConverter() を使用してデフォルトのパラメーターを上書きできます。次の例では、registrationId が okta の場合に client_id パラメーターを上書きします。
Java
Kotlin
RestClientJwtBearerTokenResponseClient accessTokenResponseClient =
new RestClientJwtBearerTokenResponseClient();
accessTokenResponseClient.setParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
LinkedMultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
if (clientRegistration.getRegistrationId().equals("okta")) {
parameters.set(OAuth2ParameterNames.CLIENT_ID, "my-client");
}
return parameters;
});
val parametersConverter = DefaultOAuth2TokenRequestParametersConverter<JwtBearerGrantRequest>()
parametersConverter.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
val accessTokenResponseClient = RestClientJwtBearerTokenResponseClient()
accessTokenResponseClient.setParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "okta") {
parameters[OAuth2ParameterNames.CLIENT_ID] = "my-client"
}
parameters
}
setParametersCustomizer() を使用すると、パラメーターを完全にカスタマイズできます (デフォルトパラメーターの省略を含む)。次の例では、リクエストに client_assertion パラメーターが存在する場合に client_id パラメーターを省略します。
Java
Kotlin
RestClientJwtBearerTokenResponseClient accessTokenResponseClient =
new RestClientJwtBearerTokenResponseClient();
accessTokenResponseClient.setParametersCustomizer(parameters -> {
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID);
}
});
val accessTokenResponseClient = RestClientJwtBearerTokenResponseClient()
accessTokenResponseClient.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
アクセストークンレスポンスのカスタマイズ
RestClientJwtBearerTokenResponseClient は、OAuth 2.0 アクセストークンレスポンスのレスポンスパラメーターとエラー処理をカスタマイズするためのフックを提供します。
RestClient のカスタマイズ
事前設定された RestClient を setRestClient() に提供することで、トークンレスポンスをカスタマイズできます。デフォルトの RestClient は次のように設定されています。
RestClient 構成 Java
Kotlin
RestClient restClient = RestClient.builder()
.messageConverters(messageConverters -> {
messageConverters.clear();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
})
.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
.build();
RestClientJwtBearerTokenResponseClient accessTokenResponseClient =
new RestClientJwtBearerTokenResponseClient();
accessTokenResponseClient.setRestClient(restClient);
val restClient = RestClient.builder()
.messageConverters { messageConverters ->
messageConverters.clear()
messageConverters.add(FormHttpMessageConverter())
messageConverters.add(OAuth2AccessTokenResponseHttpMessageConverter())
}
.defaultStatusHandler(OAuth2ErrorResponseErrorHandler())
.build()
val accessTokenResponseClient = RestClientJwtBearerTokenResponseClient()
accessTokenResponseClient.setRestClient(restClient)
OAuth2AccessTokenResponseHttpMessageConverter は、OAuth 2.0 アクセストークンレスポンスの HttpMessageConverter です。setAccessTokenResponseConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2AccessTokenResponse への変換をカスタマイズできます。デフォルトの実装は DefaultMapOAuth2AccessTokenResponseConverter です。
OAuth2ErrorResponseErrorHandler は、400 Bad Request などの OAuth 2.0 エラーを処理できる ResponseErrorHandler です。OAuth2ErrorHttpMessageConverter を使用して、OAuth 2.0 エラーパラメーターを OAuth2Error に変換します。setErrorConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2Error への変換をカスタマイズできます。
Spring MVC |
レスポンスパラメーターのカスタマイズ
次の例は、トークンレスポンスパラメーターを OAuth2AccessTokenResponse に変換することをカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
accessTokenResponseMessageConverter.setAccessTokenResponseConverter(parameters -> {
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build();
});
val accessTokenResponseMessageConverter = OAuth2AccessTokenResponseHttpMessageConverter()
accessTokenResponseMessageConverter.setAccessTokenResponseConverter { parameters ->
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build()
}
エラー処理のカスタマイズ
次の例は、Error パラメーターから OAuth2Error への変換をカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2ErrorHttpMessageConverter errorConverter =
new OAuth2ErrorHttpMessageConverter();
errorConverter.setErrorConverter(parameters -> {
// ...
return new OAuth2Error("custom-error", "custom description", "custom-uri");
});
OAuth2ErrorResponseErrorHandler errorHandler =
new OAuth2ErrorResponseErrorHandler();
errorHandler.setErrorConverter(errorConverter);
val errorConverter = OAuth2ErrorHttpMessageConverter()
errorConverter.setErrorConverter { parameters ->
// ...
return OAuth2Error("custom-error", "custom description", "custom-uri")
}
val errorHandler = OAuth2ErrorResponseErrorHandler()
errorHandler.setErrorConverter(errorConverter)
ビルダーを使用してカスタマイズする
RestClientJwtBearerTokenResponseClient をカスタマイズするか、独自の OAuth2AccessTokenResponseClient 実装を提供するかにかかわらず、次のように OAuth2AuthorizedClientProviderBuilder を使用して構成できます ( Bean を公開する代わりに)。
Java
Kotlin
// Customize
OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerTokenResponseClient = ...
JwtBearerOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider = new JwtBearerOAuth2AuthorizedClientProvider();
jwtBearerAuthorizedClientProvider.setAccessTokenResponseClient(jwtBearerTokenResponseClient);
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build();
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Customize
val jwtBearerTokenResponseClient: OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> = ...
val jwtBearerAuthorizedClientProvider = JwtBearerOAuth2AuthorizedClientProvider()
jwtBearerAuthorizedClientProvider.setAccessTokenResponseClient(jwtBearerTokenResponseClient)
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build()
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
アクセストークンの使用
OAuth 2.0 クライアント登録用の次の Spring Boot プロパティがあるとします。
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
authorization-grant-type: urn:ietf:params:oauth:grant-type:jwt-bearer
scope: read
provider:
okta:
token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token …そして OAuth2AuthorizedClientManager @Bean:
Java
Kotlin
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
JwtBearerOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider =
new JwtBearerOAuth2AuthorizedClientProvider();
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
val jwtBearerAuthorizedClientProvider = JwtBearerOAuth2AuthorizedClientProvider()
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build()
val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}
OAuth2AccessToken は次のようにして入手できます。
Java
Kotlin
@RestController
public class OAuth2ResourceServerController {
@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;
@GetMapping("/resource")
public String resource(JwtAuthenticationToken jwtAuthentication) {
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(jwtAuthentication)
.build();
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
// ...
}
}
class OAuth2ResourceServerController {
@Autowired
private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
@GetMapping("/resource")
fun resource(jwtAuthentication: JwtAuthenticationToken?): String {
val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(jwtAuthentication)
.build()
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
// ...
}
}
|
別のソースから |
トークン取引所
トークン交換 [IETF] (英語) 付与の詳細については、「OAuth 2.0 トークン交換」を参照してください。 |
アクセストークンのリクエスト
トークン交換の付与については、トークン交換のリクエストとレスポンス [IETF] (英語) プロトコルフローを参照してください。 |
トークン交換認可の OAuth2AccessTokenResponseClient のデフォルト実装は RestClientTokenExchangeTokenResponseClient です。これは、RestClient インスタンスを使用して、認可サーバーのトークンエンドポイントでアクセストークンを取得します。
RestClientTokenExchangeTokenResponseClient は非常に柔軟性が高く、トークン交換許可に対する OAuth 2.0 アクセストークンのリクエストとレスポンスをカスタマイズするためのオプションをいくつか提供します。詳細については、次のユースケースから選択してください。
アクセストークンリクエストのカスタマイズ
RestClientTokenExchangeTokenResponseClient は、OAuth 2.0 アクセストークンリクエストの HTTP ヘッダーとリクエストパラメーターをカスタマイズするためのフックを提供します。
リクエストヘッダーのカスタマイズ
HTTP ヘッダーをカスタマイズするには、次の 2 つのオプションがあります。
addHeadersConverter()を呼び出して追加のヘッダーを追加するsetHeadersConverter()を呼び出してヘッダーを完全にカスタマイズする
addHeadersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのヘッダーに影響を与えずに、追加のヘッダーを含めることができます。次の例では、registrationId が spring の場合にリクエストに User-Agent ヘッダーを追加します。
Java
Kotlin
RestClientTokenExchangeTokenResponseClient accessTokenResponseClient =
new RestClientTokenExchangeTokenResponseClient();
accessTokenResponseClient.addHeadersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
HttpHeaders headers = new HttpHeaders();
if (clientRegistration.getRegistrationId().equals("spring")) {
headers.set(HttpHeaders.USER_AGENT, "my-user-agent");
}
return headers;
});
val accessTokenResponseClient = RestClientTokenExchangeTokenResponseClient()
accessTokenResponseClient.addHeadersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val headers = HttpHeaders()
if (clientRegistration.getRegistrationId() == "spring") {
headers[HttpHeaders.USER_AGENT] = "my-user-agent"
}
headers
}
DefaultOAuth2TokenRequestHeadersConverter を再利用するか、setHeadersConverter() を使用してカスタム実装を提供することで、ヘッダーを完全にカスタマイズできます。次の例では、DefaultOAuth2TokenRequestHeadersConverter を再利用し、encodeClientCredentials を無効にして、HTTP 基本認証情報が application/x-www-form-urlencoded でエンコードされないようにしています。
Java
Kotlin
DefaultOAuth2TokenRequestHeadersConverter headersConverter =
new DefaultOAuth2TokenRequestHeadersConverter();
headersConverter.setEncodeClientCredentials(false);
RestClientTokenExchangeTokenResponseClient accessTokenResponseClient =
new RestClientTokenExchangeTokenResponseClient();
accessTokenResponseClient.setHeadersConverter(headersConverter);
val headersConverter = DefaultOAuth2TokenRequestHeadersConverter()
headersConverter.setEncodeClientCredentials(false)
val accessTokenResponseClient = RestClientTokenExchangeTokenResponseClient()
accessTokenResponseClient.setHeadersConverter(headersConverter)
リクエストパラメーターのカスタマイズ
リクエストパラメーターをカスタマイズするには、次の 3 つのオプションがあります。
addParametersConverter()を呼び出して追加のパラメーターを追加するsetParametersConverter()を呼び出してパラメーターを上書きするsetParametersCustomizer()を呼び出してパラメーターを完全にカスタマイズする
|
addParametersConverter() を使用すると、すべてのリクエストに追加されるデフォルトのパラメーターに影響を与えずに、追加のパラメーターを含めることができます。次の例では、registrationId が keycloak の場合に、リクエストに audience パラメーターを追加します。
Java
Kotlin
RestClientTokenExchangeTokenResponseClient accessTokenResponseClient =
new RestClientTokenExchangeTokenResponseClient();
accessTokenResponseClient.addParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
if (clientRegistration.getRegistrationId().equals("keycloak")) {
parameters.set(OAuth2ParameterNames.AUDIENCE, "my-audience");
}
return parameters;
});
val accessTokenResponseClient = RestClientTokenExchangeTokenResponseClient()
accessTokenResponseClient.addParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "keycloak") {
parameters[OAuth2ParameterNames.AUDIENCE] = "my-audience"
}
parameters
}
setParametersConverter() を使用してデフォルトのパラメーターを上書きできます。次の例では、registrationId が okta の場合に client_id パラメーターを上書きします。
Java
Kotlin
RestClientTokenExchangeTokenResponseClient accessTokenResponseClient =
new RestClientTokenExchangeTokenResponseClient();
accessTokenResponseClient.setParametersConverter(grantRequest -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
LinkedMultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
if (clientRegistration.getRegistrationId().equals("okta")) {
parameters.set(OAuth2ParameterNames.CLIENT_ID, "my-client");
}
return parameters;
});
val parametersConverter = DefaultOAuth2TokenRequestParametersConverter<TokenExchangeGrantRequest>()
parametersConverter.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
val accessTokenResponseClient = RestClientTokenExchangeTokenResponseClient()
accessTokenResponseClient.setParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "okta") {
parameters[OAuth2ParameterNames.CLIENT_ID] = "my-client"
}
parameters
}
setParametersCustomizer() を使用すると、パラメーターを完全にカスタマイズできます (デフォルトパラメーターの省略を含む)。次の例では、リクエストに client_assertion パラメーターが存在する場合に client_id パラメーターを省略します。
Java
Kotlin
RestClientTokenExchangeTokenResponseClient accessTokenResponseClient =
new RestClientTokenExchangeTokenResponseClient();
accessTokenResponseClient.setParametersCustomizer(parameters -> {
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID);
}
});
val accessTokenResponseClient = RestClientTokenExchangeTokenResponseClient()
accessTokenResponseClient.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
アクセストークンレスポンスのカスタマイズ
RestClientTokenExchangeTokenResponseClient は、OAuth 2.0 アクセストークンレスポンスのレスポンスパラメーターとエラー処理をカスタマイズするためのフックを提供します。
RestClient のカスタマイズ
事前設定された RestClient を setRestClient() に提供することで、トークンレスポンスをカスタマイズできます。デフォルトの RestClient は次のように設定されています。
RestClient 構成 Java
Kotlin
RestClient restClient = RestClient.builder()
.messageConverters(messageConverters -> {
messageConverters.clear();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
})
.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
.build();
RestClientTokenExchangeTokenResponseClient accessTokenResponseClient =
new RestClientTokenExchangeTokenResponseClient();
accessTokenResponseClient.setRestClient(restClient);
val restClient = RestClient.builder()
.messageConverters { messageConverters ->
messageConverters.clear()
messageConverters.add(FormHttpMessageConverter())
messageConverters.add(OAuth2AccessTokenResponseHttpMessageConverter())
}
.defaultStatusHandler(OAuth2ErrorResponseErrorHandler())
.build()
val accessTokenResponseClient = RestClientTokenExchangeTokenResponseClient()
accessTokenResponseClient.setRestClient(restClient)
OAuth2AccessTokenResponseHttpMessageConverter は、OAuth 2.0 アクセストークンレスポンスの HttpMessageConverter です。setAccessTokenResponseConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2AccessTokenResponse への変換をカスタマイズできます。デフォルトの実装は DefaultMapOAuth2AccessTokenResponseConverter です。
OAuth2ErrorResponseErrorHandler は、400 Bad Request などの OAuth 2.0 エラーを処理できる ResponseErrorHandler です。OAuth2ErrorHttpMessageConverter を使用して、OAuth 2.0 エラーパラメーターを OAuth2Error に変換します。setErrorConverter() を呼び出すことで、トークンレスポンスパラメーターの OAuth2Error への変換をカスタマイズできます。
Spring MVC |
レスポンスパラメーターのカスタマイズ
次の例は、トークンレスポンスパラメーターを OAuth2AccessTokenResponse に変換することをカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
accessTokenResponseMessageConverter.setAccessTokenResponseConverter(parameters -> {
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build();
});
val accessTokenResponseMessageConverter = OAuth2AccessTokenResponseHttpMessageConverter()
accessTokenResponseMessageConverter.setAccessTokenResponseConverter { parameters ->
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build()
}
エラー処理のカスタマイズ
次の例は、Error パラメーターから OAuth2Error への変換をカスタマイズするための出発点を示しています。
Java
Kotlin
OAuth2ErrorHttpMessageConverter errorConverter =
new OAuth2ErrorHttpMessageConverter();
errorConverter.setErrorConverter(parameters -> {
// ...
return new OAuth2Error("custom-error", "custom description", "custom-uri");
});
OAuth2ErrorResponseErrorHandler errorHandler =
new OAuth2ErrorResponseErrorHandler();
errorHandler.setErrorConverter(errorConverter);
val errorConverter = OAuth2ErrorHttpMessageConverter()
errorConverter.setErrorConverter { parameters ->
// ...
return OAuth2Error("custom-error", "custom description", "custom-uri")
}
val errorHandler = OAuth2ErrorResponseErrorHandler()
errorHandler.setErrorConverter(errorConverter)
ビルダーを使用してカスタマイズする
RestClientTokenExchangeTokenResponseClient をカスタマイズするか、独自の OAuth2AccessTokenResponseClient 実装を提供するかにかかわらず、次のように OAuth2AuthorizedClientProviderBuilder を使用して構成できます ( Bean を公開する代わりに)。
Java
Kotlin
// Customize
OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeTokenResponseClient = ...
TokenExchangeOAuth2AuthorizedClientProvider tokenExchangeAuthorizedClientProvider = new TokenExchangeOAuth2AuthorizedClientProvider();
tokenExchangeAuthorizedClientProvider.setAccessTokenResponseClient(tokenExchangeTokenResponseClient);
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.provider(tokenExchangeAuthorizedClientProvider)
.build();
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// Customize
val tokenExchangeTokenResponseClient: OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> = ...
val tokenExchangeAuthorizedClientProvider = TokenExchangeOAuth2AuthorizedClientProvider()
tokenExchangeAuthorizedClientProvider.setAccessTokenResponseClient(tokenExchangeTokenResponseClient)
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.provider(tokenExchangeAuthorizedClientProvider)
.build()
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
アクセストークンの使用
OAuth 2.0 クライアント登録用の次の Spring Boot プロパティがあるとします。
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
authorization-grant-type: urn:ietf:params:oauth:grant-type:token-exchange
scope: read
provider:
okta:
token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token …そして OAuth2AuthorizedClientManager @Bean:
Java
Kotlin
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
TokenExchangeOAuth2AuthorizedClientProvider tokenExchangeAuthorizedClientProvider =
new TokenExchangeOAuth2AuthorizedClientProvider();
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.provider(tokenExchangeAuthorizedClientProvider)
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
fun authorizedClientManager(
clientRegistrationRepository: ClientRegistrationRepository,
authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
val tokenExchangeAuthorizedClientProvider = TokenExchangeOAuth2AuthorizedClientProvider()
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.provider(tokenExchangeAuthorizedClientProvider)
.build()
val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository)
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
return authorizedClientManager
}
OAuth2AccessToken は次のようにして入手できます。
Java
Kotlin
@RestController
public class OAuth2ResourceServerController {
@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;
@GetMapping("/resource")
public String resource(JwtAuthenticationToken jwtAuthentication) {
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(jwtAuthentication)
.build();
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
// ...
}
}
class OAuth2ResourceServerController {
@Autowired
private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
@GetMapping("/resource")
fun resource(jwtAuthentication: JwtAuthenticationToken?): String {
val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
.principal(jwtAuthentication)
.build()
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
// ...
}
}
|
別のソースからのサブジェクトトークンを解決する必要がある場合は、 |
アクタートークンを解決する必要がある場合は、 |