Browse Source

Return PAR endpoint metadata only when enabled

Closes gh-2219
pull/2222/head
Joe Grandja 5 months ago
parent
commit
ac2eaf4826
  1. 26
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java
  2. 24
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcConfigurer.java
  3. 2
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java
  4. 2
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java
  5. 42
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataTests.java
  6. 40
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationTests.java
  7. 3
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java
  8. 3
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java

26
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerConfigurer.java

@ -47,6 +47,8 @@ import org.springframework.security.oauth2.server.authorization.authentication.O @@ -47,6 +47,8 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationException;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContext;
import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContextHolder;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
import org.springframework.security.oauth2.server.authorization.web.NimbusJwkSetEndpointFilter;
@ -57,6 +59,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @@ -57,6 +59,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.web.util.UriComponentsBuilder;
/**
* An {@link AbstractHttpConfigurer} for OAuth 2.0 Authorization Server support.
@ -407,6 +410,27 @@ public final class OAuth2AuthorizationServerConfigurer @@ -407,6 +410,27 @@ public final class OAuth2AuthorizationServerConfigurer
@Override
public void configure(HttpSecurity httpSecurity) {
OAuth2PushedAuthorizationRequestEndpointConfigurer pushedAuthorizationRequestEndpointConfigurer = getConfigurer(
OAuth2PushedAuthorizationRequestEndpointConfigurer.class);
if (pushedAuthorizationRequestEndpointConfigurer != null) {
OAuth2AuthorizationServerMetadataEndpointConfigurer authorizationServerMetadataEndpointConfigurer = getConfigurer(
OAuth2AuthorizationServerMetadataEndpointConfigurer.class);
authorizationServerMetadataEndpointConfigurer.addDefaultAuthorizationServerMetadataCustomizer((builder) -> {
AuthorizationServerContext authorizationServerContext = AuthorizationServerContextHolder.getContext();
String issuer = authorizationServerContext.getIssuer();
AuthorizationServerSettings authorizationServerSettings = authorizationServerContext
.getAuthorizationServerSettings();
String pushedAuthorizationRequestEndpoint = UriComponentsBuilder.fromUriString(issuer)
.path(authorizationServerSettings.getPushedAuthorizationRequestEndpoint())
.build()
.toUriString();
builder.pushedAuthorizationRequestEndpoint(pushedAuthorizationRequestEndpoint);
});
}
this.configurers.values().forEach((configurer) -> configurer.configure(httpSecurity));
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils
@ -453,7 +477,7 @@ public final class OAuth2AuthorizationServerConfigurer @@ -453,7 +477,7 @@ public final class OAuth2AuthorizationServerConfigurer
}
@SuppressWarnings("unchecked")
private <T> T getConfigurer(Class<T> type) {
<T> T getConfigurer(Class<T> type) {
return (T) this.configurers.get(type);
}

24
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcConfigurer.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2023 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,28 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer { @@ -148,6 +148,28 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
});
}
OAuth2PushedAuthorizationRequestEndpointConfigurer pushedAuthorizationRequestEndpointConfigurer = httpSecurity
.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.getConfigurer(OAuth2PushedAuthorizationRequestEndpointConfigurer.class);
if (pushedAuthorizationRequestEndpointConfigurer != null) {
OidcProviderConfigurationEndpointConfigurer providerConfigurationEndpointConfigurer = getConfigurer(
OidcProviderConfigurationEndpointConfigurer.class);
providerConfigurationEndpointConfigurer.addDefaultProviderConfigurationCustomizer((builder) -> {
AuthorizationServerContext authorizationServerContext = AuthorizationServerContextHolder.getContext();
String issuer = authorizationServerContext.getIssuer();
AuthorizationServerSettings authorizationServerSettings = authorizationServerContext
.getAuthorizationServerSettings();
String pushedAuthorizationRequestEndpoint = UriComponentsBuilder.fromUriString(issuer)
.path(authorizationServerSettings.getPushedAuthorizationRequestEndpoint())
.build()
.toUriString();
builder.pushedAuthorizationRequestEndpoint(pushedAuthorizationRequestEndpoint);
});
}
this.configurers.values().forEach((configurer) -> configurer.configure(httpSecurity));
}

2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilter.java

@ -101,8 +101,6 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques @@ -101,8 +101,6 @@ public final class OidcProviderConfigurationEndpointFilter extends OncePerReques
OidcProviderConfiguration.Builder providerConfiguration = OidcProviderConfiguration.builder()
.issuer(issuer)
.authorizationEndpoint(asUrl(issuer, authorizationServerSettings.getAuthorizationEndpoint()))
.pushedAuthorizationRequestEndpoint(
asUrl(issuer, authorizationServerSettings.getPushedAuthorizationRequestEndpoint()))
.deviceAuthorizationEndpoint(asUrl(issuer, authorizationServerSettings.getDeviceAuthorizationEndpoint()))
.tokenEndpoint(asUrl(issuer, authorizationServerSettings.getTokenEndpoint()))
.tokenEndpointAuthenticationMethods(clientAuthenticationMethods())

2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilter.java

@ -101,8 +101,6 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP @@ -101,8 +101,6 @@ public final class OAuth2AuthorizationServerMetadataEndpointFilter extends OnceP
.builder()
.issuer(issuer)
.authorizationEndpoint(asUrl(issuer, authorizationServerSettings.getAuthorizationEndpoint()))
.pushedAuthorizationRequestEndpoint(
asUrl(issuer, authorizationServerSettings.getPushedAuthorizationRequestEndpoint()))
.deviceAuthorizationEndpoint(asUrl(issuer, authorizationServerSettings.getDeviceAuthorizationEndpoint()))
.tokenEndpoint(asUrl(issuer, authorizationServerSettings.getTokenEndpoint()))
.tokenEndpointAuthenticationMethods(clientAuthenticationMethods())

42
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OAuth2AuthorizationServerMetadataTests.java

@ -1,5 +1,5 @@ @@ -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.
@ -35,6 +35,7 @@ import org.springframework.jdbc.core.JdbcTemplate; @@ -35,6 +35,7 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.oauth2.jose.TestJwks;
@ -80,6 +81,9 @@ public class OAuth2AuthorizationServerMetadataTests { @@ -80,6 +81,9 @@ public class OAuth2AuthorizationServerMetadataTests {
@Autowired
private JdbcOperations jdbcOperations;
@Autowired
private AuthorizationServerSettings authorizationServerSettings;
@BeforeAll
public static void setupClass() {
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
@ -155,6 +159,17 @@ public class OAuth2AuthorizationServerMetadataTests { @@ -155,6 +159,17 @@ public class OAuth2AuthorizationServerMetadataTests {
hasItems("scope1", "scope2")));
}
@Test
public void requestWhenAuthorizationServerMetadataRequestAndPushedAuthorizationRequestEnabledThenMetadataResponseIncludesPushedAuthorizationRequestEndpoint()
throws Exception {
this.spring.register(AuthorizationServerConfigurationWithPushedAuthorizationRequestEnabled.class).autowire();
this.mvc.perform(get(ISSUER.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpect(jsonPath("$.pushed_authorization_request_endpoint")
.value(ISSUER.concat(this.authorizationServerSettings.getPushedAuthorizationRequestEndpoint())));
}
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
static class AuthorizationServerConfiguration {
@ -226,4 +241,29 @@ public class OAuth2AuthorizationServerMetadataTests { @@ -226,4 +241,29 @@ public class OAuth2AuthorizationServerMetadataTests {
}
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithPushedAuthorizationRequestEnabled
extends AuthorizationServerConfiguration {
// @formatter:off
@Bean
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.pushedAuthorizationRequestEndpoint(Customizer.withDefaults())
)
.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
);
return http.build();
}
// @formatter:on
}
}

40
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/annotation/web/configurers/OidcProviderConfigurationTests.java

@ -1,5 +1,5 @@ @@ -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.
@ -144,6 +144,18 @@ public class OidcProviderConfigurationTests { @@ -144,6 +144,18 @@ public class OidcProviderConfigurationTests {
.value(ISSUER.concat(this.authorizationServerSettings.getOidcClientRegistrationEndpoint())));
}
@Test
public void requestWhenConfigurationRequestAndPushedAuthorizationRequestEnabledThenConfigurationResponseIncludesPushedAuthorizationRequestEndpoint()
throws Exception {
this.spring.register(AuthorizationServerConfigurationWithPushedAuthorizationRequestEnabled.class).autowire();
this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
.andExpect(status().is2xxSuccessful())
.andExpectAll(defaultConfigurationMatchers(ISSUER))
.andExpect(jsonPath("$.pushed_authorization_request_endpoint")
.value(ISSUER.concat(this.authorizationServerSettings.getPushedAuthorizationRequestEndpoint())));
}
private ResultMatcher[] defaultConfigurationMatchers(String issuer) {
// @formatter:off
return new ResultMatcher[] {
@ -407,4 +419,30 @@ public class OidcProviderConfigurationTests { @@ -407,4 +419,30 @@ public class OidcProviderConfigurationTests {
}
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithPushedAuthorizationRequestEnabled
extends AuthorizationServerConfiguration {
// @formatter:off
@Bean
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.pushedAuthorizationRequestEndpoint(Customizer.withDefaults())
.oidc(Customizer.withDefaults())
)
.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
);
return http.build();
}
// @formatter:on
}
}

3
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/web/OidcProviderConfigurationEndpointFilterTests.java

@ -133,8 +133,7 @@ public class OidcProviderConfigurationEndpointFilterTests { @@ -133,8 +133,7 @@ public class OidcProviderConfigurationEndpointFilterTests {
assertThat(providerConfigurationResponse).contains("\"issuer\":\"https://example.com\"");
assertThat(providerConfigurationResponse)
.contains("\"authorization_endpoint\":\"https://example.com/oauth2/v1/authorize\"");
assertThat(providerConfigurationResponse)
.contains("\"pushed_authorization_request_endpoint\":\"https://example.com/oauth2/v1/par\"");
assertThat(providerConfigurationResponse).doesNotContain("\"pushed_authorization_request_endpoint\"");
assertThat(providerConfigurationResponse)
.contains("\"token_endpoint\":\"https://example.com/oauth2/v1/token\"");
assertThat(providerConfigurationResponse).contains("\"jwks_uri\":\"https://example.com/oauth2/v1/jwks\"");

3
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationServerMetadataEndpointFilterTests.java

@ -129,8 +129,7 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests { @@ -129,8 +129,7 @@ public class OAuth2AuthorizationServerMetadataEndpointFilterTests {
assertThat(authorizationServerMetadataResponse).contains("\"issuer\":\"https://example.com\"");
assertThat(authorizationServerMetadataResponse)
.contains("\"authorization_endpoint\":\"https://example.com/oauth2/v1/authorize\"");
assertThat(authorizationServerMetadataResponse)
.contains("\"pushed_authorization_request_endpoint\":\"https://example.com/oauth2/v1/par\"");
assertThat(authorizationServerMetadataResponse).doesNotContain("\"pushed_authorization_request_endpoint\"");
assertThat(authorizationServerMetadataResponse)
.contains("\"token_endpoint\":\"https://example.com/oauth2/v1/token\"");
assertThat(authorizationServerMetadataResponse).contains(

Loading…
Cancel
Save