Skip to content

Commit 3ee47ef

Browse files
committed
Disable Oidc client registration by default
Closes gh-398
1 parent fe27e39 commit 3ee47ef

File tree

8 files changed

+159
-44
lines changed

8 files changed

+159
-44
lines changed

oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configuration/OAuth2AuthorizationServerConfiguration.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import org.springframework.core.annotation.Order;
3333
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3434
import org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer;
35-
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
3635
import org.springframework.security.oauth2.jwt.JwtDecoder;
3736
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
3837
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
@@ -69,12 +68,10 @@ public static void applyDefaultSecurity(HttpSecurity http) throws Exception {
6968
authorizeRequests.anyRequest().authenticated()
7069
)
7170
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
72-
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
7371
.apply(authorizationServerConfigurer);
7472
}
7573
// @formatter:on
7674

77-
@Bean
7875
public static JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
7976
Set<JWSAlgorithm> jwsAlgs = new HashSet<>();
8077
jwsAlgs.addAll(JWSAlgorithm.Family.RSA);

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,12 @@ abstract class AbstractOAuth2Configurer {
3838

3939
abstract RequestMatcher getRequestMatcher();
4040

41-
protected <T> T postProcess(T object) {
41+
protected final <T> T postProcess(T object) {
4242
return (T) this.objectPostProcessor.postProcess(object);
4343
}
4444

45+
protected final ObjectPostProcessor<Object> getObjectPostProcessor() {
46+
return this.objectPostProcessor;
47+
}
48+
4549
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2020-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization;
17+
18+
import org.springframework.http.HttpMethod;
19+
import org.springframework.security.authentication.AuthenticationManager;
20+
import org.springframework.security.config.annotation.ObjectPostProcessor;
21+
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
22+
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
23+
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcClientRegistrationAuthenticationProvider;
24+
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcClientRegistrationEndpointFilter;
25+
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
26+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
27+
import org.springframework.security.web.util.matcher.RequestMatcher;
28+
29+
/**
30+
* Configurer for OpenID Connect Dynamic Client Registration 1.0 Endpoint.
31+
*
32+
* @author Joe Grandja
33+
* @since 0.2.0
34+
* @see OidcConfigurer#clientRegistrationEndpoint
35+
* @see OidcClientRegistrationEndpointFilter
36+
*/
37+
public final class OidcClientRegistrationEndpointConfigurer extends AbstractOAuth2Configurer {
38+
private RequestMatcher requestMatcher;
39+
40+
/**
41+
* Restrict for internal use only.
42+
*/
43+
OidcClientRegistrationEndpointConfigurer(ObjectPostProcessor<Object> objectPostProcessor) {
44+
super(objectPostProcessor);
45+
}
46+
47+
@Override
48+
<B extends HttpSecurityBuilder<B>> void init(B builder) {
49+
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
50+
this.requestMatcher = new AntPathRequestMatcher(
51+
providerSettings.getOidcClientRegistrationEndpoint(), HttpMethod.POST.name());
52+
53+
OidcClientRegistrationAuthenticationProvider oidcClientRegistrationAuthenticationProvider =
54+
new OidcClientRegistrationAuthenticationProvider(
55+
OAuth2ConfigurerUtils.getRegisteredClientRepository(builder),
56+
OAuth2ConfigurerUtils.getAuthorizationService(builder));
57+
builder.authenticationProvider(postProcess(oidcClientRegistrationAuthenticationProvider));
58+
}
59+
60+
@Override
61+
<B extends HttpSecurityBuilder<B>> void configure(B builder) {
62+
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
63+
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
64+
65+
OidcClientRegistrationEndpointFilter oidcClientRegistrationEndpointFilter =
66+
new OidcClientRegistrationEndpointFilter(
67+
authenticationManager,
68+
providerSettings.getOidcClientRegistrationEndpoint());
69+
builder.addFilterAfter(postProcess(oidcClientRegistrationEndpointFilter), FilterSecurityInterceptor.class);
70+
}
71+
72+
@Override
73+
RequestMatcher getRequestMatcher() {
74+
return this.requestMatcher;
75+
}
76+
77+
}

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

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,11 @@
1919
import java.util.List;
2020

2121
import org.springframework.http.HttpMethod;
22-
import org.springframework.security.authentication.AuthenticationManager;
22+
import org.springframework.security.config.Customizer;
2323
import org.springframework.security.config.annotation.ObjectPostProcessor;
2424
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
2525
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
26-
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcClientRegistrationAuthenticationProvider;
27-
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcClientRegistrationEndpointFilter;
2826
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcProviderConfigurationEndpointFilter;
29-
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
3027
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
3128
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
3229
import org.springframework.security.web.util.matcher.OrRequestMatcher;
@@ -38,10 +35,11 @@
3835
* @author Joe Grandja
3936
* @since 0.2.0
4037
* @see OAuth2AuthorizationServerConfigurer#oidc
38+
* @see OidcClientRegistrationEndpointConfigurer
4139
* @see OidcProviderConfigurationEndpointFilter
42-
* @see OidcClientRegistrationEndpointFilter
4340
*/
4441
public final class OidcConfigurer extends AbstractOAuth2Configurer {
42+
private OidcClientRegistrationEndpointConfigurer clientRegistrationEndpointConfigurer;
4543
private RequestMatcher requestMatcher;
4644

4745
/**
@@ -51,47 +49,50 @@ public final class OidcConfigurer extends AbstractOAuth2Configurer {
5149
super(objectPostProcessor);
5250
}
5351

52+
/**
53+
* Configures the OpenID Connect Dynamic Client Registration 1.0 Endpoint.
54+
*
55+
* @param clientRegistrationEndpointCustomizer the {@link Customizer} providing access to the {@link OidcClientRegistrationEndpointConfigurer}
56+
* @return the {@link OidcConfigurer} for further configuration
57+
*/
58+
public OidcConfigurer clientRegistrationEndpoint(Customizer<OidcClientRegistrationEndpointConfigurer> clientRegistrationEndpointCustomizer) {
59+
if (this.clientRegistrationEndpointConfigurer == null) {
60+
this.clientRegistrationEndpointConfigurer = new OidcClientRegistrationEndpointConfigurer(getObjectPostProcessor());
61+
}
62+
clientRegistrationEndpointCustomizer.customize(this.clientRegistrationEndpointConfigurer);
63+
return this;
64+
}
65+
5466
@Override
5567
<B extends HttpSecurityBuilder<B>> void init(B builder) {
68+
if (this.clientRegistrationEndpointConfigurer != null) {
69+
this.clientRegistrationEndpointConfigurer.init(builder);
70+
}
71+
5672
List<RequestMatcher> requestMatchers = new ArrayList<>();
5773
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
5874
if (providerSettings.getIssuer() != null) {
59-
requestMatchers.add(
60-
new AntPathRequestMatcher(
61-
"/.well-known/openid-configuration",
62-
HttpMethod.GET.name()));
75+
requestMatchers.add(new AntPathRequestMatcher(
76+
"/.well-known/openid-configuration", HttpMethod.GET.name()));
6377
}
64-
requestMatchers.add(
65-
new AntPathRequestMatcher(
66-
providerSettings.getOidcClientRegistrationEndpoint(),
67-
HttpMethod.POST.name()));
68-
this.requestMatcher = new OrRequestMatcher(requestMatchers);
69-
70-
// TODO Make OpenID Client Registration an "opt-in" feature
71-
OidcClientRegistrationAuthenticationProvider oidcClientRegistrationAuthenticationProvider =
72-
new OidcClientRegistrationAuthenticationProvider(
73-
OAuth2ConfigurerUtils.getRegisteredClientRepository(builder),
74-
OAuth2ConfigurerUtils.getAuthorizationService(builder));
75-
builder.authenticationProvider(postProcess(oidcClientRegistrationAuthenticationProvider));
78+
if (this.clientRegistrationEndpointConfigurer != null) {
79+
requestMatchers.add(this.clientRegistrationEndpointConfigurer.getRequestMatcher());
80+
}
81+
this.requestMatcher = !requestMatchers.isEmpty() ? new OrRequestMatcher(requestMatchers) : request -> false;
7682
}
7783

7884
@Override
7985
<B extends HttpSecurityBuilder<B>> void configure(B builder) {
86+
if (this.clientRegistrationEndpointConfigurer != null) {
87+
this.clientRegistrationEndpointConfigurer.configure(builder);
88+
}
89+
8090
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
8191
if (providerSettings.getIssuer() != null) {
8292
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
8393
new OidcProviderConfigurationEndpointFilter(providerSettings);
8494
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
8595
}
86-
87-
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
88-
89-
// TODO Make OpenID Client Registration an "opt-in" feature
90-
OidcClientRegistrationEndpointFilter oidcClientRegistrationEndpointFilter =
91-
new OidcClientRegistrationEndpointFilter(
92-
authenticationManager,
93-
providerSettings.getOidcClientRegistrationEndpoint());
94-
builder.addFilterAfter(postProcess(oidcClientRegistrationEndpointFilter), FilterSecurityInterceptor.class);
9596
}
9697

9798
@Override

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
6262
import org.springframework.security.crypto.password.PasswordEncoder;
6363
import org.springframework.security.oauth2.core.AuthorizationGrantType;
64+
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
6465
import org.springframework.security.oauth2.core.OAuth2TokenType;
6566
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
6667
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType;
@@ -76,7 +77,6 @@
7677
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
7778
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
7879
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
79-
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
8080
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
8181
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
8282
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
@@ -601,6 +601,11 @@ JWKSource<SecurityContext> jwkSource() {
601601
return jwkSource;
602602
}
603603

604+
@Bean
605+
JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
606+
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
607+
}
608+
604609
@Bean
605610
OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
606611
return context -> {

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131
import org.springframework.beans.factory.annotation.Autowired;
3232
import org.springframework.context.annotation.Bean;
33-
import org.springframework.context.annotation.Import;
3433
import org.springframework.http.HttpHeaders;
3534
import org.springframework.http.HttpStatus;
3635
import org.springframework.http.MediaType;
@@ -43,8 +42,11 @@
4342
import org.springframework.mock.http.MockHttpOutputMessage;
4443
import org.springframework.mock.http.client.MockClientHttpResponse;
4544
import org.springframework.mock.web.MockHttpServletResponse;
45+
import org.springframework.security.config.Customizer;
46+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
4647
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
4748
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
49+
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
4850
import org.springframework.security.config.test.SpringTestRule;
4951
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
5052
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -59,11 +61,14 @@
5961
import org.springframework.security.oauth2.core.oidc.http.converter.OidcClientRegistrationHttpMessageConverter;
6062
import org.springframework.security.oauth2.jose.TestJwks;
6163
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
64+
import org.springframework.security.oauth2.jwt.JwtDecoder;
6265
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
6366
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository.RegisteredClientParametersMapper;
6467
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
6568
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
6669
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
70+
import org.springframework.security.web.SecurityFilterChain;
71+
import org.springframework.security.web.util.matcher.RequestMatcher;
6772
import org.springframework.test.web.servlet.MockMvc;
6873
import org.springframework.test.web.servlet.MvcResult;
6974

@@ -223,9 +228,30 @@ private static OidcClientRegistration readClientRegistrationResponse(MockHttpSer
223228
}
224229

225230
@EnableWebSecurity
226-
@Import(OAuth2AuthorizationServerConfiguration.class)
227231
static class AuthorizationServerConfiguration {
228232

233+
// @formatter:off
234+
@Bean
235+
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
236+
OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =
237+
new OAuth2AuthorizationServerConfigurer<>();
238+
authorizationServerConfigurer
239+
.oidc(oidc ->
240+
oidc.clientRegistrationEndpoint(Customizer.withDefaults()));
241+
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
242+
243+
http
244+
.requestMatcher(endpointsMatcher)
245+
.authorizeRequests(authorizeRequests ->
246+
authorizeRequests.anyRequest().authenticated()
247+
)
248+
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
249+
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
250+
.apply(authorizationServerConfigurer);
251+
return http.build();
252+
}
253+
// @formatter:on
254+
229255
@Bean
230256
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations, PasswordEncoder passwordEncoder) {
231257
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
@@ -247,10 +273,16 @@ JWKSource<SecurityContext> jwkSource() {
247273
return jwkSource;
248274
}
249275

276+
@Bean
277+
JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
278+
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
279+
}
280+
250281
@Bean
251282
PasswordEncoder passwordEncoder() {
252283
return NoOpPasswordEncoder.getInstance();
253284
}
254285

255286
}
287+
256288
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
5757
import org.springframework.security.crypto.password.PasswordEncoder;
5858
import org.springframework.security.oauth2.core.AuthorizationGrantType;
59+
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
5960
import org.springframework.security.oauth2.core.OAuth2TokenType;
6061
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
6162
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType;
@@ -69,7 +70,6 @@
6970
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
7071
import org.springframework.security.oauth2.server.authorization.JwtEncodingContext;
7172
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
72-
import org.springframework.security.oauth2.core.OAuth2AuthorizationCode;
7373
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
7474
import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer;
7575
import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository;
@@ -294,6 +294,11 @@ JWKSource<SecurityContext> jwkSource() {
294294
return jwkSource;
295295
}
296296

297+
@Bean
298+
JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
299+
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
300+
}
301+
297302
@Bean
298303
OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
299304
return context -> {

samples/boot/oauth2-integration/authorizationserver/src/main/java/sample/config/AuthorizationServerConfig.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import org.springframework.security.oauth2.core.AuthorizationGrantType;
3838
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
3939
import org.springframework.security.oauth2.core.oidc.OidcScopes;
40-
import org.springframework.security.oauth2.jwt.JwtDecoder;
4140
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationConsentService;
4241
import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
4342
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationConsentService;
@@ -106,11 +105,6 @@ public JWKSource<SecurityContext> jwkSource() {
106105
return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet);
107106
}
108107

109-
@Bean
110-
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
111-
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
112-
}
113-
114108
@Bean
115109
public ProviderSettings providerSettings() {
116110
return ProviderSettings.builder().issuer("http://auth-server:9000").build();

0 commit comments

Comments
 (0)