Skip to content

Commit ac2eaf4

Browse files
committed
Return PAR endpoint metadata only when enabled
Closes gh-2219
1 parent d85f96a commit ac2eaf4

File tree

8 files changed

+130
-12
lines changed

8 files changed

+130
-12
lines changed

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationException;
4848
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
4949
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
50+
import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContext;
51+
import org.springframework.security.oauth2.server.authorization.context.AuthorizationServerContextHolder;
5052
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
5153
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
5254
import org.springframework.security.oauth2.server.authorization.web.NimbusJwkSetEndpointFilter;
@@ -57,6 +59,7 @@
5759
import org.springframework.security.web.util.matcher.OrRequestMatcher;
5860
import org.springframework.security.web.util.matcher.RequestMatcher;
5961
import org.springframework.util.Assert;
62+
import org.springframework.web.util.UriComponentsBuilder;
6063

6164
/**
6265
* An {@link AbstractHttpConfigurer} for OAuth 2.0 Authorization Server support.
@@ -407,6 +410,27 @@ public void init(HttpSecurity httpSecurity) throws Exception {
407410

408411
@Override
409412
public void configure(HttpSecurity httpSecurity) {
413+
OAuth2PushedAuthorizationRequestEndpointConfigurer pushedAuthorizationRequestEndpointConfigurer = getConfigurer(
414+
OAuth2PushedAuthorizationRequestEndpointConfigurer.class);
415+
if (pushedAuthorizationRequestEndpointConfigurer != null) {
416+
OAuth2AuthorizationServerMetadataEndpointConfigurer authorizationServerMetadataEndpointConfigurer = getConfigurer(
417+
OAuth2AuthorizationServerMetadataEndpointConfigurer.class);
418+
419+
authorizationServerMetadataEndpointConfigurer.addDefaultAuthorizationServerMetadataCustomizer((builder) -> {
420+
AuthorizationServerContext authorizationServerContext = AuthorizationServerContextHolder.getContext();
421+
String issuer = authorizationServerContext.getIssuer();
422+
AuthorizationServerSettings authorizationServerSettings = authorizationServerContext
423+
.getAuthorizationServerSettings();
424+
425+
String pushedAuthorizationRequestEndpoint = UriComponentsBuilder.fromUriString(issuer)
426+
.path(authorizationServerSettings.getPushedAuthorizationRequestEndpoint())
427+
.build()
428+
.toUriString();
429+
430+
builder.pushedAuthorizationRequestEndpoint(pushedAuthorizationRequestEndpoint);
431+
});
432+
}
433+
410434
this.configurers.values().forEach((configurer) -> configurer.configure(httpSecurity));
411435

412436
AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils
@@ -453,7 +477,7 @@ private Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer>
453477
}
454478

455479
@SuppressWarnings("unchecked")
456-
private <T> T getConfigurer(Class<T> type) {
480+
<T> T getConfigurer(Class<T> type) {
457481
return (T) this.configurers.get(type);
458482
}
459483

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 the original author or authors.
2+
* Copyright 2020-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -148,6 +148,28 @@ void configure(HttpSecurity httpSecurity) {
148148
});
149149
}
150150

151+
OAuth2PushedAuthorizationRequestEndpointConfigurer pushedAuthorizationRequestEndpointConfigurer = httpSecurity
152+
.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
153+
.getConfigurer(OAuth2PushedAuthorizationRequestEndpointConfigurer.class);
154+
if (pushedAuthorizationRequestEndpointConfigurer != null) {
155+
OidcProviderConfigurationEndpointConfigurer providerConfigurationEndpointConfigurer = getConfigurer(
156+
OidcProviderConfigurationEndpointConfigurer.class);
157+
158+
providerConfigurationEndpointConfigurer.addDefaultProviderConfigurationCustomizer((builder) -> {
159+
AuthorizationServerContext authorizationServerContext = AuthorizationServerContextHolder.getContext();
160+
String issuer = authorizationServerContext.getIssuer();
161+
AuthorizationServerSettings authorizationServerSettings = authorizationServerContext
162+
.getAuthorizationServerSettings();
163+
164+
String pushedAuthorizationRequestEndpoint = UriComponentsBuilder.fromUriString(issuer)
165+
.path(authorizationServerSettings.getPushedAuthorizationRequestEndpoint())
166+
.build()
167+
.toUriString();
168+
169+
builder.pushedAuthorizationRequestEndpoint(pushedAuthorizationRequestEndpoint);
170+
});
171+
}
172+
151173
this.configurers.values().forEach((configurer) -> configurer.configure(httpSecurity));
152174
}
153175

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
101101
OidcProviderConfiguration.Builder providerConfiguration = OidcProviderConfiguration.builder()
102102
.issuer(issuer)
103103
.authorizationEndpoint(asUrl(issuer, authorizationServerSettings.getAuthorizationEndpoint()))
104-
.pushedAuthorizationRequestEndpoint(
105-
asUrl(issuer, authorizationServerSettings.getPushedAuthorizationRequestEndpoint()))
106104
.deviceAuthorizationEndpoint(asUrl(issuer, authorizationServerSettings.getDeviceAuthorizationEndpoint()))
107105
.tokenEndpoint(asUrl(issuer, authorizationServerSettings.getTokenEndpoint()))
108106
.tokenEndpointAuthenticationMethods(clientAuthenticationMethods())

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
101101
.builder()
102102
.issuer(issuer)
103103
.authorizationEndpoint(asUrl(issuer, authorizationServerSettings.getAuthorizationEndpoint()))
104-
.pushedAuthorizationRequestEndpoint(
105-
asUrl(issuer, authorizationServerSettings.getPushedAuthorizationRequestEndpoint()))
106104
.deviceAuthorizationEndpoint(asUrl(issuer, authorizationServerSettings.getDeviceAuthorizationEndpoint()))
107105
.tokenEndpoint(asUrl(issuer, authorizationServerSettings.getTokenEndpoint()))
108106
.tokenEndpointAuthenticationMethods(clientAuthenticationMethods())

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

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2024 the original author or authors.
2+
* Copyright 2020-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
3535
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
3636
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
3737
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
38+
import org.springframework.security.config.Customizer;
3839
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3940
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
4041
import org.springframework.security.oauth2.jose.TestJwks;
@@ -80,6 +81,9 @@ public class OAuth2AuthorizationServerMetadataTests {
8081
@Autowired
8182
private JdbcOperations jdbcOperations;
8283

84+
@Autowired
85+
private AuthorizationServerSettings authorizationServerSettings;
86+
8387
@BeforeAll
8488
public static void setupClass() {
8589
JWKSet jwkSet = new JWKSet(TestJwks.DEFAULT_RSA_JWK);
@@ -155,6 +159,17 @@ public void requestWhenAuthorizationServerMetadataRequestAndMetadataCustomizerSe
155159
hasItems("scope1", "scope2")));
156160
}
157161

162+
@Test
163+
public void requestWhenAuthorizationServerMetadataRequestAndPushedAuthorizationRequestEnabledThenMetadataResponseIncludesPushedAuthorizationRequestEndpoint()
164+
throws Exception {
165+
this.spring.register(AuthorizationServerConfigurationWithPushedAuthorizationRequestEnabled.class).autowire();
166+
167+
this.mvc.perform(get(ISSUER.concat(DEFAULT_OAUTH2_AUTHORIZATION_SERVER_METADATA_ENDPOINT_URI)))
168+
.andExpect(status().is2xxSuccessful())
169+
.andExpect(jsonPath("$.pushed_authorization_request_endpoint")
170+
.value(ISSUER.concat(this.authorizationServerSettings.getPushedAuthorizationRequestEndpoint())));
171+
}
172+
158173
@EnableWebSecurity
159174
@Import(OAuth2AuthorizationServerConfiguration.class)
160175
static class AuthorizationServerConfiguration {
@@ -226,4 +241,29 @@ AuthorizationServerSettings authorizationServerSettings() {
226241

227242
}
228243

244+
@EnableWebSecurity
245+
@Configuration(proxyBeanMethods = false)
246+
static class AuthorizationServerConfigurationWithPushedAuthorizationRequestEnabled
247+
extends AuthorizationServerConfiguration {
248+
249+
// @formatter:off
250+
@Bean
251+
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
252+
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
253+
OAuth2AuthorizationServerConfigurer.authorizationServer();
254+
http
255+
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
256+
.with(authorizationServerConfigurer, (authorizationServer) ->
257+
authorizationServer
258+
.pushedAuthorizationRequestEndpoint(Customizer.withDefaults())
259+
)
260+
.authorizeHttpRequests((authorize) ->
261+
authorize.anyRequest().authenticated()
262+
);
263+
return http.build();
264+
}
265+
// @formatter:on
266+
267+
}
268+
229269
}

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

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2024 the original author or authors.
2+
* Copyright 2020-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -144,6 +144,18 @@ public void requestWhenConfigurationRequestAndClientRegistrationEnabledThenConfi
144144
.value(ISSUER.concat(this.authorizationServerSettings.getOidcClientRegistrationEndpoint())));
145145
}
146146

147+
@Test
148+
public void requestWhenConfigurationRequestAndPushedAuthorizationRequestEnabledThenConfigurationResponseIncludesPushedAuthorizationRequestEndpoint()
149+
throws Exception {
150+
this.spring.register(AuthorizationServerConfigurationWithPushedAuthorizationRequestEnabled.class).autowire();
151+
152+
this.mvc.perform(get(ISSUER.concat(DEFAULT_OIDC_PROVIDER_CONFIGURATION_ENDPOINT_URI)))
153+
.andExpect(status().is2xxSuccessful())
154+
.andExpectAll(defaultConfigurationMatchers(ISSUER))
155+
.andExpect(jsonPath("$.pushed_authorization_request_endpoint")
156+
.value(ISSUER.concat(this.authorizationServerSettings.getPushedAuthorizationRequestEndpoint())));
157+
}
158+
147159
private ResultMatcher[] defaultConfigurationMatchers(String issuer) {
148160
// @formatter:off
149161
return new ResultMatcher[] {
@@ -407,4 +419,30 @@ AuthorizationServerSettings authorizationServerSettings() {
407419

408420
}
409421

422+
@EnableWebSecurity
423+
@Configuration(proxyBeanMethods = false)
424+
static class AuthorizationServerConfigurationWithPushedAuthorizationRequestEnabled
425+
extends AuthorizationServerConfiguration {
426+
427+
// @formatter:off
428+
@Bean
429+
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
430+
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
431+
OAuth2AuthorizationServerConfigurer.authorizationServer();
432+
http
433+
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
434+
.with(authorizationServerConfigurer, (authorizationServer) ->
435+
authorizationServer
436+
.pushedAuthorizationRequestEndpoint(Customizer.withDefaults())
437+
.oidc(Customizer.withDefaults())
438+
)
439+
.authorizeHttpRequests((authorize) ->
440+
authorize.anyRequest().authenticated()
441+
);
442+
return http.build();
443+
}
444+
// @formatter:on
445+
446+
}
447+
410448
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,7 @@ public void doFilterWhenConfigurationRequestThenConfigurationResponse() throws E
133133
assertThat(providerConfigurationResponse).contains("\"issuer\":\"https://example.com\"");
134134
assertThat(providerConfigurationResponse)
135135
.contains("\"authorization_endpoint\":\"https://example.com/oauth2/v1/authorize\"");
136-
assertThat(providerConfigurationResponse)
137-
.contains("\"pushed_authorization_request_endpoint\":\"https://example.com/oauth2/v1/par\"");
136+
assertThat(providerConfigurationResponse).doesNotContain("\"pushed_authorization_request_endpoint\"");
138137
assertThat(providerConfigurationResponse)
139138
.contains("\"token_endpoint\":\"https://example.com/oauth2/v1/token\"");
140139
assertThat(providerConfigurationResponse).contains("\"jwks_uri\":\"https://example.com/oauth2/v1/jwks\"");

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,7 @@ public void doFilterWhenAuthorizationServerMetadataRequestThenMetadataResponse()
129129
assertThat(authorizationServerMetadataResponse).contains("\"issuer\":\"https://example.com\"");
130130
assertThat(authorizationServerMetadataResponse)
131131
.contains("\"authorization_endpoint\":\"https://example.com/oauth2/v1/authorize\"");
132-
assertThat(authorizationServerMetadataResponse)
133-
.contains("\"pushed_authorization_request_endpoint\":\"https://example.com/oauth2/v1/par\"");
132+
assertThat(authorizationServerMetadataResponse).doesNotContain("\"pushed_authorization_request_endpoint\"");
134133
assertThat(authorizationServerMetadataResponse)
135134
.contains("\"token_endpoint\":\"https://example.com/oauth2/v1/token\"");
136135
assertThat(authorizationServerMetadataResponse).contains(

0 commit comments

Comments
 (0)