From 65e3a5ec9b84fdda89ce0fb226b2418572cdd81c Mon Sep 17 00:00:00 2001 From: Joe Grandja <10884212+jgrandja@users.noreply.github.com> Date: Wed, 26 Mar 2025 05:22:44 -0400 Subject: [PATCH] Add authorization server metadata for DPoP support Issue gh-1813 Closes gh-1951 --- ...ractOAuth2AuthorizationServerMetadata.java | 47 ++++++++++++++++++- ...horizationServerMetadataClaimAccessor.java | 17 ++++++- ...AuthorizationServerMetadataClaimNames.java | 14 +++++- ...ionServerMetadataHttpMessageConverter.java | 4 +- ...dcProviderConfigurationEndpointFilter.java | 18 ++++++- ...orizationServerMetadataEndpointFilter.java | 20 +++++++- ...Auth2AuthorizationServerMetadataTests.java | 42 ++++++++++++++++- ...viderConfigurationEndpointFilterTests.java | 4 +- ...tionServerMetadataEndpointFilterTests.java | 4 +- 9 files changed, 160 insertions(+), 10 deletions(-) diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/AbstractOAuth2AuthorizationServerMetadata.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/AbstractOAuth2AuthorizationServerMetadata.java index 4b6bec59..e1254f0c 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/AbstractOAuth2AuthorizationServerMetadata.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/AbstractOAuth2AuthorizationServerMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; +import org.springframework.security.oauth2.jose.jws.JwsAlgorithms; import org.springframework.security.oauth2.server.authorization.util.SpringAuthorizationServerVersion; import org.springframework.util.Assert; @@ -48,6 +49,9 @@ import org.springframework.util.Assert; * @see 3.3 Mutual-TLS Client * Certificate-Bound Access Tokens Metadata + * @see 5.1 OAuth 2.0 Demonstrating + * Proof of Possession (DPoP) Metadata */ public abstract class AbstractOAuth2AuthorizationServerMetadata implements OAuth2AuthorizationServerMetadataClaimAccessor, Serializable { @@ -379,6 +383,37 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata tlsClientCertificateBoundAccessTokens); } + /** + * Add a {@link JwsAlgorithms JSON Web Signature (JWS) algorithm} to the + * collection of {@code dpop_signing_alg_values_supported} in the resulting + * {@link AbstractOAuth2AuthorizationServerMetadata}, OPTIONAL. + * @param dPoPSigningAlgorithm the {@link JwsAlgorithms JSON Web Signature (JWS) + * algorithm} supported for DPoP Proof JWTs + * @return the {@link AbstractBuilder} for further configuration + * @since 1.5 + */ + public B dPoPSigningAlgorithm(String dPoPSigningAlgorithm) { + addClaimToClaimList(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED, + dPoPSigningAlgorithm); + return getThis(); + } + + /** + * A {@code Consumer} of the {@link JwsAlgorithms JSON Web Signature (JWS) + * algorithms} supported for DPoP Proof JWTs allowing the ability to add, replace, + * or remove. + * @param dPoPSigningAlgorithmsConsumer a {@code Consumer} of the + * {@link JwsAlgorithms JSON Web Signature (JWS) algorithms} supported for DPoP + * Proof JWTs + * @return the {@link AbstractBuilder} for further configuration + * @since 1.5 + */ + public B dPoPSigningAlgorithms(Consumer> dPoPSigningAlgorithmsConsumer) { + acceptClaimValues(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED, + dPoPSigningAlgorithmsConsumer); + return getThis(); + } + /** * Use this claim in the resulting * {@link AbstractOAuth2AuthorizationServerMetadata}. @@ -506,6 +541,16 @@ public abstract class AbstractOAuth2AuthorizationServerMetadata .get(OAuth2AuthorizationServerMetadataClaimNames.CODE_CHALLENGE_METHODS_SUPPORTED), "codeChallengeMethods cannot be empty"); } + if (getClaims() + .get(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED) != null) { + Assert.isInstanceOf(List.class, + getClaims().get(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED), + "dPoPSigningAlgorithms must be of type List"); + Assert.notEmpty( + (List) getClaims() + .get(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED), + "dPoPSigningAlgorithms cannot be empty"); + } } @SuppressWarnings("unchecked") diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimAccessor.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimAccessor.java index 54c6057c..a7ceb35e 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimAccessor.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import java.net.URL; import java.util.List; import org.springframework.security.oauth2.core.ClaimAccessor; +import org.springframework.security.oauth2.jose.jws.JwsAlgorithms; /** * A {@link ClaimAccessor} for the "claims" an Authorization Server describes about its @@ -40,6 +41,9 @@ import org.springframework.security.oauth2.core.ClaimAccessor; * @see 3.3 Mutual-TLS Client * Certificate-Bound Access Tokens Metadata + * @see 5.1 OAuth 2.0 Demonstrating + * Proof of Possession (DPoP) Metadata */ public interface OAuth2AuthorizationServerMetadataClaimAccessor extends ClaimAccessor { @@ -193,4 +197,15 @@ public interface OAuth2AuthorizationServerMetadataClaimAccessor extends ClaimAcc OAuth2AuthorizationServerMetadataClaimNames.TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKENS)); } + /** + * Returns the {@link JwsAlgorithms JSON Web Signature (JWS) algorithms} supported for + * DPoP Proof JWTs {@code (dpop_signing_alg_values_supported)}. + * @return the {@link JwsAlgorithms JSON Web Signature (JWS) algorithms} supported for + * DPoP Proof JWTs + * @since 1.5 + */ + default List getDPoPSigningAlgorithms() { + return getClaimAsStringList(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED); + } + } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimNames.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimNames.java index 0a410bf3..7a47498b 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimNames.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataClaimNames.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,8 @@ */ package org.springframework.security.oauth2.server.authorization; +import org.springframework.security.oauth2.jose.jws.JwsAlgorithms; + /** * The names of the "claims" an Authorization Server describes about its configuration, * used in OAuth 2.0 Authorization Server Metadata and OpenID Connect Discovery 1.0. @@ -32,6 +34,9 @@ package org.springframework.security.oauth2.server.authorization; * @see 3.3 Mutual-TLS Client * Certificate-Bound Access Tokens Metadata + * @see 5.1 OAuth 2.0 Demonstrating + * Proof of Possession (DPoP) Metadata */ public class OAuth2AuthorizationServerMetadataClaimNames { @@ -130,6 +135,13 @@ public class OAuth2AuthorizationServerMetadataClaimNames { */ public static final String TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKENS = "tls_client_certificate_bound_access_tokens"; + /** + * {@code dpop_signing_alg_values_supported} - the {@link JwsAlgorithms JSON Web + * Signature (JWS) algorithms} supported for DPoP Proof JWTs + * @since 1.5 + */ + public static final String DPOP_SIGNING_ALG_VALUES_SUPPORTED = "dpop_signing_alg_values_supported"; + protected OAuth2AuthorizationServerMetadataClaimNames() { } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/http/converter/OAuth2AuthorizationServerMetadataHttpMessageConverter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/http/converter/OAuth2AuthorizationServerMetadataHttpMessageConverter.java index a2db1d72..3339ebea 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/http/converter/OAuth2AuthorizationServerMetadataHttpMessageConverter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/http/converter/OAuth2AuthorizationServerMetadataHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -169,6 +169,8 @@ public class OAuth2AuthorizationServerMetadataHttpMessageConverter collectionStringConverter); claimConverters.put(OAuth2AuthorizationServerMetadataClaimNames.CODE_CHALLENGE_METHODS_SUPPORTED, collectionStringConverter); + claimConverters.put(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED, + collectionStringConverter); this.claimTypeConverter = new ClaimTypeConverter(claimConverters); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java index 556964cf..b527396f 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.ClientAuthenticationMethod; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType; import org.springframework.security.oauth2.core.oidc.OidcScopes; +import org.springframework.security.oauth2.jose.jws.JwsAlgorithms; import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm; import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContext; import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContextHolder; @@ -118,6 +119,7 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques .tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods()) .codeChallengeMethod("S256") .tlsClientCertificateBoundAccessTokens(true) + .dPoPSigningAlgorithms(dPoPSigningAlgorithms()) .subjectType("public") .idTokenSigningAlgorithm(SignatureAlgorithm.RS256.getName()) .scope(OidcScopes.OPENID); @@ -151,6 +153,20 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques }; } + private static Consumer> dPoPSigningAlgorithms() { + return (algs) -> { + algs.add(JwsAlgorithms.RS256); + algs.add(JwsAlgorithms.RS384); + algs.add(JwsAlgorithms.RS512); + algs.add(JwsAlgorithms.PS256); + algs.add(JwsAlgorithms.PS384); + algs.add(JwsAlgorithms.PS512); + algs.add(JwsAlgorithms.ES256); + algs.add(JwsAlgorithms.ES384); + algs.add(JwsAlgorithms.ES512); + }; + } + private static String asUrl(String issuer, String endpoint) { return UriComponentsBuilder.fromUriString(issuer).path(endpoint).build().toUriString(); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java index 043b9b63..608766ae 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.ClientAuthenticationMethod; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType; +import org.springframework.security.oauth2.jose.jws.JwsAlgorithms; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationServerMetadata; import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContext; import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContextHolder; @@ -115,7 +116,8 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP .tokenIntrospectionEndpoint(asUrl(issuer, authorizationServerSettings.getTokenIntrospectionEndpoint())) .tokenIntrospectionEndpointAuthenticationMethods(clientAuthenticationMethods()) .codeChallengeMethod("S256") - .tlsClientCertificateBoundAccessTokens(true); + .tlsClientCertificateBoundAccessTokens(true) + .dPoPSigningAlgorithms(dPoPSigningAlgorithms()); this.authorizationServerMetadataCustomizer.accept(authorizationServerMetadata); @@ -146,6 +148,20 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP }; } + private static Consumer> dPoPSigningAlgorithms() { + return (algs) -> { + algs.add(JwsAlgorithms.RS256); + algs.add(JwsAlgorithms.RS384); + algs.add(JwsAlgorithms.RS512); + algs.add(JwsAlgorithms.PS256); + algs.add(JwsAlgorithms.PS384); + algs.add(JwsAlgorithms.PS512); + algs.add(JwsAlgorithms.ES256); + algs.add(JwsAlgorithms.ES384); + algs.add(JwsAlgorithms.ES512); + }; + } + private static String asUrl(String issuer, String endpoint) { return UriComponentsBuilder.fromUriString(issuer).path(endpoint).toUriString(); } diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataTests.java index 0a031afb..86fa599a 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationServerMetadataTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.security.oauth2.jose.jws.JwsAlgorithms; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationServerMetadata.Builder; import static org.assertj.core.api.Assertions.assertThat; @@ -63,6 +64,8 @@ public class OAuth2AuthorizationServerMetadataTests { .tokenIntrospectionEndpointAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()) .codeChallengeMethod("S256") .tlsClientCertificateBoundAccessTokens(true) + .dPoPSigningAlgorithm(JwsAlgorithms.RS256) + .dPoPSigningAlgorithm(JwsAlgorithms.ES256) .claim("a-claim", "a-value") .build(); @@ -87,6 +90,8 @@ public class OAuth2AuthorizationServerMetadataTests { .containsExactly(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()); assertThat(authorizationServerMetadata.getCodeChallengeMethods()).containsExactly("S256"); assertThat(authorizationServerMetadata.isTlsClientCertificateBoundAccessTokens()).isTrue(); + assertThat(authorizationServerMetadata.getDPoPSigningAlgorithms()).containsExactly(JwsAlgorithms.RS256, + JwsAlgorithms.ES256); assertThat(authorizationServerMetadata.getClaimAsString("a-claim")).isEqualTo("a-value"); } @@ -113,6 +118,7 @@ public class OAuth2AuthorizationServerMetadataTests { assertThat(authorizationServerMetadata.getTokenIntrospectionEndpoint()).isNull(); assertThat(authorizationServerMetadata.getTokenIntrospectionEndpointAuthenticationMethods()).isNull(); assertThat(authorizationServerMetadata.getCodeChallengeMethods()).isNull(); + assertThat(authorizationServerMetadata.getDPoPSigningAlgorithms()).isNull(); } @Test @@ -152,6 +158,7 @@ public class OAuth2AuthorizationServerMetadataTests { .isEqualTo(url("https://example.com/oauth2/introspect")); assertThat(authorizationServerMetadata.getTokenIntrospectionEndpointAuthenticationMethods()).isNull(); assertThat(authorizationServerMetadata.getCodeChallengeMethods()).isNull(); + assertThat(authorizationServerMetadata.getDPoPSigningAlgorithms()).isNull(); assertThat(authorizationServerMetadata.getClaimAsString("some-claim")).isEqualTo("some-value"); } @@ -191,6 +198,7 @@ public class OAuth2AuthorizationServerMetadataTests { .isEqualTo(url("https://example.com/oauth2/introspect")); assertThat(authorizationServerMetadata.getTokenIntrospectionEndpointAuthenticationMethods()).isNull(); assertThat(authorizationServerMetadata.getCodeChallengeMethods()).isNull(); + assertThat(authorizationServerMetadata.getDPoPSigningAlgorithms()).isNull(); assertThat(authorizationServerMetadata.getClaimAsString("some-claim")).isEqualTo("some-value"); } @@ -536,6 +544,38 @@ public class OAuth2AuthorizationServerMetadataTests { assertThat(authorizationServerMetadata.getCodeChallengeMethods()).containsExactly("some-authentication-method"); } + @Test + public void buildWhenDPoPSigningAlgorithmsNotListThenThrowIllegalArgumentException() { + Builder builder = this.minimalBuilder.claims((claims) -> claims + .put(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED, "not-a-list")); + + assertThatIllegalArgumentException().isThrownBy(builder::build) + .withMessageStartingWith("dPoPSigningAlgorithms must be of type List"); + } + + @Test + public void buildWhenDPoPSigningAlgorithmsEmptyListThenThrowIllegalArgumentException() { + Builder builder = this.minimalBuilder.claims( + (claims) -> claims.put(OAuth2AuthorizationServerMetadataClaimNames.DPOP_SIGNING_ALG_VALUES_SUPPORTED, + Collections.emptyList())); + + assertThatIllegalArgumentException().isThrownBy(builder::build) + .withMessage("dPoPSigningAlgorithms cannot be empty"); + } + + @Test + public void buildWhenDPoPSigningAlgorithmsAddingOrRemovingThenCorrectValues() { + OAuth2AuthorizationServerMetadata authorizationServerMetadata = this.minimalBuilder + .dPoPSigningAlgorithm(JwsAlgorithms.RS256) + .dPoPSigningAlgorithms((algs) -> { + algs.clear(); + algs.add(JwsAlgorithms.ES256); + }) + .build(); + + assertThat(authorizationServerMetadata.getDPoPSigningAlgorithms()).containsExactly(JwsAlgorithms.ES256); + } + @Test public void claimWhenNameNullThenThrowIllegalArgumentException() { assertThatIllegalArgumentException() diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java index 5532813c..80b70e30 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -148,6 +148,8 @@ public class OidcProviderConfigurationEndpointFilterTests { "\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); assertThat(providerConfigurationResponse).contains("\"code_challenge_methods_supported\":[\"S256\"]"); assertThat(providerConfigurationResponse).contains("\"tls_client_certificate_bound_access_tokens\":true"); + assertThat(providerConfigurationResponse).contains( + "\"dpop_signing_alg_values_supported\":[\"RS256\",\"RS384\",\"RS512\",\"PS256\",\"PS384\",\"PS512\",\"ES256\",\"ES384\",\"ES512\"]"); assertThat(providerConfigurationResponse).contains("\"subject_types_supported\":[\"public\"]"); assertThat(providerConfigurationResponse).contains("\"id_token_signing_alg_values_supported\":[\"RS256\"]"); assertThat(providerConfigurationResponse).contains("\"userinfo_endpoint\":\"https://example.com/userinfo\""); diff --git a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java index 005f5859..4f9de8e1 100644 --- a/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java +++ b/oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the original author or authors. + * Copyright 2020-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -145,6 +145,8 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests { "\"introspection_endpoint_auth_methods_supported\":[\"client_secret_basic\",\"client_secret_post\",\"client_secret_jwt\",\"private_key_jwt\",\"tls_client_auth\",\"self_signed_tls_client_auth\"]"); assertThat(authorizationServerMetadataResponse).contains("\"code_challenge_methods_supported\":[\"S256\"]"); assertThat(authorizationServerMetadataResponse).contains("\"tls_client_certificate_bound_access_tokens\":true"); + assertThat(authorizationServerMetadataResponse).contains( + "\"dpop_signing_alg_values_supported\":[\"RS256\",\"RS384\",\"RS512\",\"PS256\",\"PS384\",\"PS512\",\"ES256\",\"ES384\",\"ES512\"]"); } @Test