Explorar o código

Add OidcConfigurationProvider ClientAuthenticationMethod.POST support

Issue: gh-5355
Rob Winch %!s(int64=7) %!d(string=hai) anos
pai
achega
18c8af8f0d

+ 15 - 7
config/src/main/java/org/springframework/security/config/oauth2/client/oidc/OidcConfigurationProvider.java

@@ -72,13 +72,9 @@ public final class OidcConfigurationProvider {
 		String openidConfiguration = rest.getForObject(issuer + "/.well-known/openid-configuration", String.class);
 		OIDCProviderMetadata metadata = parse(openidConfiguration);
 		String name = URI.create(issuer).getHost();
-		List<com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod> metadataAuthMethods = metadata.getTokenEndpointAuthMethods();
-			// if null, the default includes client_secret_basic
-		if (metadataAuthMethods != null && !metadataAuthMethods.contains(com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) {
-			throw new IllegalArgumentException("Only ClientAuthenticationMethod.BASIC is supported. The issuer \"" + issuer + "\" returned a configuration of " + metadataAuthMethods);
-		}
+		ClientAuthenticationMethod method = getClientAuthenticationMethod(issuer, metadata.getTokenEndpointAuthMethods());
 		List<GrantType> grantTypes = metadata.getGrantTypes();
-			// If null, the default includes authorization_code
+		// If null, the default includes authorization_code
 		if (grantTypes != null && !grantTypes.contains(GrantType.AUTHORIZATION_CODE)) {
 			throw new IllegalArgumentException("Only AuthorizationGrantType.AUTHORIZATION_CODE is supported. The issuer \"" + issuer + "\" returned a configuration of " + grantTypes);
 		}
@@ -87,7 +83,7 @@ public final class OidcConfigurationProvider {
 				.userNameAttributeName(IdTokenClaimNames.SUB)
 				.scope(scopes)
 				.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
-				.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC)
+				.clientAuthenticationMethod(method)
 				.redirectUriTemplate("{baseUrl}/{action}/oauth2/code/{registrationId}")
 				.authorizationUri(metadata.getAuthorizationEndpointURI().toASCIIString())
 				.jwkSetUri(metadata.getJWKSetURI().toASCIIString())
@@ -96,6 +92,18 @@ public final class OidcConfigurationProvider {
 				.clientName(issuer);
 	}
 
+
+	private static ClientAuthenticationMethod getClientAuthenticationMethod(String issuer, List<com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod> metadataAuthMethods) {
+		if (metadataAuthMethods == null || metadataAuthMethods.contains(com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) {
+			// If null, the default includes client_secret_basic
+			return ClientAuthenticationMethod.BASIC;
+		}
+		if (metadataAuthMethods.contains(com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod.CLIENT_SECRET_POST)) {
+			return ClientAuthenticationMethod.POST;
+		}
+		throw new IllegalArgumentException("Only ClientAuthenticationMethod.BASIC and ClientAuthenticationMethod.POST are supported. The issuer \"" + issuer + "\" returned a configuration of " + metadataAuthMethods);
+	}
+
 	private static List<String> getScopes(OIDCProviderMetadata metadata) {
 		Scope scope = metadata.getScopes();
 		if (scope == null) {

+ 11 - 3
config/src/test/java/org/springframework/security/config/oauth2/client/oidc/OidcConfigurationProviderTests.java

@@ -25,7 +25,6 @@ import org.junit.Before;
 import org.junit.Test;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
-import org.springframework.security.config.oauth2.client.oidc.OidcConfigurationProvider;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.core.AuthorizationGrantType;
 import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
@@ -181,17 +180,26 @@ public class OidcConfigurationProviderTests {
 		assertThat(registration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.BASIC);
 	}
 
+	@Test
+	public void issuerWhenTokenEndpointAuthMethodsPostThenMethodIsPost() throws Exception {
+		this.response.put("token_endpoint_auth_methods_supported", Arrays.asList("client_secret_post"));
+
+		ClientRegistration registration = registration("");
+
+		assertThat(registration.getClientAuthenticationMethod()).isEqualTo(ClientAuthenticationMethod.POST);
+	}
+
 	/**
 	 * We currently only support client_secret_basic, so verify we have a meaningful error until we add support.
 	 * @throws Exception
 	 */
 	@Test
 	public void issuerWhenTokenEndpointAuthMethodsInvalidThenException() throws Exception {
-		this.response.put("token_endpoint_auth_methods_supported", Arrays.asList("client_secret_post"));
+		this.response.put("token_endpoint_auth_methods_supported", Arrays.asList("tls_client_auth"));
 
 		assertThatThrownBy(() -> registration(""))
 				.isInstanceOf(IllegalArgumentException.class)
-				.hasMessageContaining("Only ClientAuthenticationMethod.BASIC is supported. The issuer \"" + this.issuer + "\" returned a configuration of [client_secret_post]");
+				.hasMessageContaining("Only ClientAuthenticationMethod.BASIC and ClientAuthenticationMethod.POST are supported. The issuer \"" + this.issuer + "\" returned a configuration of [tls_client_auth]");
 	}
 
 	private ClientRegistration registration(String path) throws Exception {