用戶端驗證支援

用戶端憑證

使用 client_secret_basic 進行身份驗證

HTTP Basic 用戶端驗證已開箱即用,無需任何自訂設定即可啟用。預設實作由 DefaultOAuth2TokenRequestHeadersConverter 提供。

假設 OAuth 2.0 用戶端註冊的 Spring Boot 屬性如下

spring:
  security:
    oauth2:
      client:
        registration:
          okta:
            client-id: client-id
            client-secret: client-secret
            client-authentication-method: client_secret_basic
            authorization-grant-type: authorization_code
            ...

以下範例示範如何組態 WebClientReactiveAuthorizationCodeTokenResponseClient 以停用用戶端憑證的 URL 編碼

  • Java

  • Kotlin

DefaultOAuth2TokenRequestHeadersConverter<OAuth2AuthorizationCodeGrantRequest> headersConverter =
		new DefaultOAuth2TokenRequestHeadersConverter<>();
headersConverter.setEncodeClientCredentials(false);

WebClientReactiveAuthorizationCodeTokenResponseClient tokenResponseClient =
		new WebClientReactiveAuthorizationCodeTokenResponseClient();
tokenResponseClient.setHeadersConverter(headersConverter);
val headersConverter = DefaultOAuth2TokenRequestHeadersConverter<OAuth2AuthorizationCodeGrantRequest>()
headersConverter.setEncodeClientCredentials(false)

val tokenResponseClient = WebClientReactiveAuthorizationCodeTokenResponseClient()
tokenResponseClient.setHeadersConverter(headersConverter)

使用 client_secret_post 進行身份驗證

支援在請求內文中包含用戶端憑證的用戶端驗證,且無需任何自訂設定即可啟用。

以下 OAuth 2.0 用戶端註冊的 Spring Boot 屬性示範了組態

spring:
  security:
    oauth2:
      client:
        registration:
          okta:
            client-id: client-id
            client-secret: client-secret
            client-authentication-method: client_secret_post
            authorization-grant-type: authorization_code
            ...

JWT Bearer

關於 JWT Bearer 用戶端驗證的更多詳細資訊,請參閱 OAuth 2.0 用戶端驗證和授權許可的 JSON Web Token (JWT) Profile。

JWT Bearer 用戶端驗證的預設實作是 NimbusJwtClientAuthenticationParametersConverter,它是一個 Converter,透過在 client_assertion 參數中新增簽署的 JSON Web Token (JWS) 來客製化權杖請求參數。

用於簽署 JWS 的 java.security.PrivateKeyjavax.crypto.SecretKey 由與 NimbusJwtClientAuthenticationParametersConverter 關聯的 com.nimbusds.jose.jwk.JWK 解析器提供。

使用 private_key_jwt 進行身份驗證

假設 OAuth 2.0 用戶端註冊的 Spring Boot 屬性如下

spring:
  security:
    oauth2:
      client:
        registration:
          okta:
            client-id: okta-client-id
            client-authentication-method: private_key_jwt
            authorization-grant-type: authorization_code
            ...

以下範例示範如何組態 WebClientReactiveAuthorizationCodeTokenResponseClient

  • Java

  • Kotlin

Function<ClientRegistration, JWK> jwkResolver = (clientRegistration) -> {
	if (clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.PRIVATE_KEY_JWT)) {
		// Assuming RSA key type
		RSAPublicKey publicKey = ...
		RSAPrivateKey privateKey = ...
		return new RSAKey.Builder(publicKey)
				.privateKey(privateKey)
				.keyID(UUID.randomUUID().toString())
				.build();
	}
	return null;
};

WebClientReactiveAuthorizationCodeTokenResponseClient tokenResponseClient =
		new WebClientReactiveAuthorizationCodeTokenResponseClient();
tokenResponseClient.addParametersConverter(
		new NimbusJwtClientAuthenticationParametersConverter<>(jwkResolver));
val jwkResolver: Function<ClientRegistration, JWK> =
    Function<ClientRegistration, JWK> { clientRegistration ->
        if (clientRegistration.clientAuthenticationMethod.equals(ClientAuthenticationMethod.PRIVATE_KEY_JWT)) {
            // Assuming RSA key type
            var publicKey: RSAPublicKey = ...
            var privateKey: RSAPrivateKey = ...
            RSAKey.Builder(publicKey)
                    .privateKey(privateKey)
                    .keyID(UUID.randomUUID().toString())
                .build()
        }
        null
    }

val tokenResponseClient = WebClientReactiveAuthorizationCodeTokenResponseClient()
tokenResponseClient.addParametersConverter(
    NimbusJwtClientAuthenticationParametersConverter(jwkResolver)
)

使用 client_secret_jwt 進行身份驗證

假設 OAuth 2.0 用戶端註冊的 Spring Boot 屬性如下

spring:
  security:
    oauth2:
      client:
        registration:
          okta:
            client-id: okta-client-id
            client-secret: okta-client-secret
            client-authentication-method: client_secret_jwt
            authorization-grant-type: client_credentials
            ...

以下範例示範如何組態 WebClientReactiveClientCredentialsTokenResponseClient

  • Java

  • Kotlin

Function<ClientRegistration, JWK> jwkResolver = (clientRegistration) -> {
	if (clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.CLIENT_SECRET_JWT)) {
		SecretKeySpec secretKey = new SecretKeySpec(
				clientRegistration.getClientSecret().getBytes(StandardCharsets.UTF_8),
				"HmacSHA256");
		return new OctetSequenceKey.Builder(secretKey)
				.keyID(UUID.randomUUID().toString())
				.build();
	}
	return null;
};

WebClientReactiveClientCredentialsTokenResponseClient tokenResponseClient =
		new WebClientReactiveClientCredentialsTokenResponseClient();
tokenResponseClient.addParametersConverter(
		new NimbusJwtClientAuthenticationParametersConverter<>(jwkResolver));
val jwkResolver = Function<ClientRegistration, JWK?> { clientRegistration: ClientRegistration ->
    if (clientRegistration.clientAuthenticationMethod == ClientAuthenticationMethod.CLIENT_SECRET_JWT) {
        val secretKey = SecretKeySpec(
            clientRegistration.clientSecret.toByteArray(StandardCharsets.UTF_8),
            "HmacSHA256"
        )
        OctetSequenceKey.Builder(secretKey)
            .keyID(UUID.randomUUID().toString())
            .build()
    }
    null
}

val tokenResponseClient = WebClientReactiveClientCredentialsTokenResponseClient()
tokenResponseClient.addParametersConverter(
    NimbusJwtClientAuthenticationParametersConverter(jwkResolver)
)

自訂 JWT 斷言

NimbusJwtClientAuthenticationParametersConverter 產生的 JWT 預設包含 isssubaudjtiiatexp 宣告。您可以透過提供 Consumer<NimbusJwtClientAuthenticationParametersConverter.JwtClientAuthenticationContext<T>>setJwtClientAssertionCustomizer() 來客製化標頭和/或宣告。以下範例示範如何客製化 JWT 的宣告

  • Java

  • Kotlin

Function<ClientRegistration, JWK> jwkResolver = ...

NimbusJwtClientAuthenticationParametersConverter<OAuth2ClientCredentialsGrantRequest> converter =
		new NimbusJwtClientAuthenticationParametersConverter<>(jwkResolver);
converter.setJwtClientAssertionCustomizer((context) -> {
	context.getHeaders().header("custom-header", "header-value");
	context.getClaims().claim("custom-claim", "claim-value");
});
val jwkResolver = ...

val converter: NimbusJwtClientAuthenticationParametersConverter<OAuth2ClientCredentialsGrantRequest> =
    NimbusJwtClientAuthenticationParametersConverter(jwkResolver)
converter.setJwtClientAssertionCustomizer { context ->
    context.headers.header("custom-header", "header-value")
    context.claims.claim("custom-claim", "claim-value")
}

公開驗證

公開用戶端驗證已開箱即用,無需任何自訂設定即可啟用。

以下 OAuth 2.0 用戶端註冊的 Spring Boot 屬性示範了組態

spring:
  security:
    oauth2:
      client:
        registration:
          okta:
            client-id: client-id
            client-authentication-method: none
            authorization-grant-type: authorization_code
            ...
使用程式碼交換證明金鑰 (PKCE) 支援公開用戶端。當 client-authentication-method 設定為 "none" (ClientAuthenticationMethod.NONE) 時,將自動使用 PKCE。