Skip to content

Commit fe27e39

Browse files
committed
Extract configurer for OpenID Connect 1.0 support
Issue gh-398
1 parent 57aadce commit fe27e39

File tree

2 files changed

+129
-47
lines changed

2 files changed

+129
-47
lines changed

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

Lines changed: 27 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
import java.util.LinkedHashMap;
2020
import java.util.Map;
2121

22-
import com.nimbusds.jose.jwk.source.JWKSource;
23-
import com.nimbusds.jose.proc.SecurityContext;
24-
2522
import org.springframework.http.HttpMethod;
2623
import org.springframework.http.HttpStatus;
2724
import org.springframework.security.authentication.AuthenticationManager;
@@ -35,9 +32,6 @@
3532
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenRevocationAuthenticationProvider;
3633
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
3734
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
38-
import org.springframework.security.oauth2.server.authorization.oidc.authentication.OidcClientRegistrationAuthenticationProvider;
39-
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcClientRegistrationEndpointFilter;
40-
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcProviderConfigurationEndpointFilter;
4135
import org.springframework.security.oauth2.server.authorization.web.NimbusJwkSetEndpointFilter;
4236
import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationServerMetadataEndpointFilter;
4337
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenIntrospectionEndpointFilter;
@@ -62,15 +56,14 @@
6256
* @see OAuth2ClientAuthenticationConfigurer
6357
* @see OAuth2AuthorizationEndpointConfigurer
6458
* @see OAuth2TokenEndpointConfigurer
59+
* @see OidcConfigurer
6560
* @see RegisteredClientRepository
6661
* @see OAuth2AuthorizationService
6762
* @see OAuth2AuthorizationConsentService
6863
* @see OAuth2TokenIntrospectionEndpointFilter
6964
* @see OAuth2TokenRevocationEndpointFilter
7065
* @see NimbusJwkSetEndpointFilter
71-
* @see OidcProviderConfigurationEndpointFilter
7266
* @see OAuth2AuthorizationServerMetadataEndpointFilter
73-
* @see OidcClientRegistrationEndpointFilter
7467
*/
7568
public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBuilder<B>>
7669
extends AbstractHttpConfigurer<OAuth2AuthorizationServerConfigurer<B>, B> {
@@ -79,18 +72,15 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
7972
private RequestMatcher tokenIntrospectionEndpointMatcher;
8073
private RequestMatcher tokenRevocationEndpointMatcher;
8174
private RequestMatcher jwkSetEndpointMatcher;
82-
private RequestMatcher oidcProviderConfigurationEndpointMatcher;
8375
private RequestMatcher authorizationServerMetadataEndpointMatcher;
84-
private RequestMatcher oidcClientRegistrationEndpointMatcher;
8576
private final RequestMatcher endpointsMatcher = (request) ->
8677
getRequestMatcher(OAuth2AuthorizationEndpointConfigurer.class).matches(request) ||
8778
getRequestMatcher(OAuth2TokenEndpointConfigurer.class).matches(request) ||
79+
getRequestMatcher(OidcConfigurer.class).matches(request) ||
8880
this.tokenIntrospectionEndpointMatcher.matches(request) ||
8981
this.tokenRevocationEndpointMatcher.matches(request) ||
9082
this.jwkSetEndpointMatcher.matches(request) ||
91-
this.oidcProviderConfigurationEndpointMatcher.matches(request) ||
92-
this.authorizationServerMetadataEndpointMatcher.matches(request) ||
93-
this.oidcClientRegistrationEndpointMatcher.matches(request);
83+
this.authorizationServerMetadataEndpointMatcher.matches(request);
9484

9585
/**
9686
* Sets the repository of registered clients.
@@ -173,6 +163,17 @@ public OAuth2AuthorizationServerConfigurer<B> tokenEndpoint(Customizer<OAuth2Tok
173163
return this;
174164
}
175165

166+
/**
167+
* Configures OpenID Connect 1.0 support.
168+
*
169+
* @param oidcCustomizer the {@link Customizer} providing access to the {@link OidcConfigurer}
170+
* @return the {@link OAuth2AuthorizationServerConfigurer} for further configuration
171+
*/
172+
public OAuth2AuthorizationServerConfigurer<B> oidc(Customizer<OidcConfigurer> oidcCustomizer) {
173+
oidcCustomizer.customize(getConfigurer(OidcConfigurer.class));
174+
return this;
175+
}
176+
176177
/**
177178
* Returns a {@link RequestMatcher} for the authorization server endpoints.
178179
*
@@ -201,13 +202,6 @@ public void init(B builder) {
201202
OAuth2ConfigurerUtils.getAuthorizationService(builder));
202203
builder.authenticationProvider(postProcess(tokenRevocationAuthenticationProvider));
203204

204-
// TODO Make OpenID Client Registration an "opt-in" feature
205-
OidcClientRegistrationAuthenticationProvider oidcClientRegistrationAuthenticationProvider =
206-
new OidcClientRegistrationAuthenticationProvider(
207-
OAuth2ConfigurerUtils.getRegisteredClientRepository(builder),
208-
OAuth2ConfigurerUtils.getAuthorizationService(builder));
209-
builder.authenticationProvider(postProcess(oidcClientRegistrationAuthenticationProvider));
210-
211205
ExceptionHandlingConfigurer<B> exceptionHandling = builder.getConfigurer(ExceptionHandlingConfigurer.class);
212206
if (exceptionHandling != null) {
213207
exceptionHandling.defaultAuthenticationEntryPointFor(
@@ -225,22 +219,6 @@ public void configure(B builder) {
225219
this.configurers.values().forEach(configurer -> configurer.configure(builder));
226220

227221
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
228-
if (providerSettings.getIssuer() != null) {
229-
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
230-
new OidcProviderConfigurationEndpointFilter(providerSettings);
231-
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
232-
233-
OAuth2AuthorizationServerMetadataEndpointFilter authorizationServerMetadataEndpointFilter =
234-
new OAuth2AuthorizationServerMetadataEndpointFilter(providerSettings);
235-
builder.addFilterBefore(postProcess(authorizationServerMetadataEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
236-
}
237-
238-
JWKSource<SecurityContext> jwkSource = OAuth2ConfigurerUtils.getJwkSource(builder);
239-
NimbusJwkSetEndpointFilter jwkSetEndpointFilter = new NimbusJwkSetEndpointFilter(
240-
jwkSource,
241-
providerSettings.getJwkSetEndpoint());
242-
builder.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
243-
244222
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
245223

246224
OAuth2TokenIntrospectionEndpointFilter tokenIntrospectionEndpointFilter =
@@ -253,21 +231,27 @@ public void configure(B builder) {
253231
new OAuth2TokenRevocationEndpointFilter(
254232
authenticationManager,
255233
providerSettings.getTokenRevocationEndpoint());
256-
builder.addFilterAfter(postProcess(tokenRevocationEndpointFilter), OAuth2TokenIntrospectionEndpointFilter.class);
234+
builder.addFilterAfter(postProcess(tokenRevocationEndpointFilter), FilterSecurityInterceptor.class);
257235

258-
// TODO Make OpenID Client Registration an "opt-in" feature
259-
OidcClientRegistrationEndpointFilter oidcClientRegistrationEndpointFilter =
260-
new OidcClientRegistrationEndpointFilter(
261-
authenticationManager,
262-
providerSettings.getOidcClientRegistrationEndpoint());
263-
builder.addFilterAfter(postProcess(oidcClientRegistrationEndpointFilter), OAuth2TokenRevocationEndpointFilter.class);
236+
NimbusJwkSetEndpointFilter jwkSetEndpointFilter =
237+
new NimbusJwkSetEndpointFilter(
238+
OAuth2ConfigurerUtils.getJwkSource(builder),
239+
providerSettings.getJwkSetEndpoint());
240+
builder.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
241+
242+
if (providerSettings.getIssuer() != null) {
243+
OAuth2AuthorizationServerMetadataEndpointFilter authorizationServerMetadataEndpointFilter =
244+
new OAuth2AuthorizationServerMetadataEndpointFilter(providerSettings);
245+
builder.addFilterBefore(postProcess(authorizationServerMetadataEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
246+
}
264247
}
265248

266249
private Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer> createConfigurers() {
267250
Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer> configurers = new LinkedHashMap<>();
268251
configurers.put(OAuth2ClientAuthenticationConfigurer.class, new OAuth2ClientAuthenticationConfigurer(this::postProcess));
269252
configurers.put(OAuth2AuthorizationEndpointConfigurer.class, new OAuth2AuthorizationEndpointConfigurer(this::postProcess));
270253
configurers.put(OAuth2TokenEndpointConfigurer.class, new OAuth2TokenEndpointConfigurer(this::postProcess));
254+
configurers.put(OidcConfigurer.class, new OidcConfigurer(this::postProcess));
271255
return configurers;
272256
}
273257

@@ -287,12 +271,8 @@ private void initEndpointMatchers(ProviderSettings providerSettings) {
287271
providerSettings.getTokenRevocationEndpoint(), HttpMethod.POST.name());
288272
this.jwkSetEndpointMatcher = new AntPathRequestMatcher(
289273
providerSettings.getJwkSetEndpoint(), HttpMethod.GET.name());
290-
this.oidcProviderConfigurationEndpointMatcher = new AntPathRequestMatcher(
291-
"/.well-known/openid-configuration", HttpMethod.GET.name());
292274
this.authorizationServerMetadataEndpointMatcher = new AntPathRequestMatcher(
293275
"/.well-known/oauth-authorization-server", HttpMethod.GET.name());
294-
this.oidcClientRegistrationEndpointMatcher = new AntPathRequestMatcher(
295-
providerSettings.getOidcClientRegistrationEndpoint(), HttpMethod.POST.name());
296276
}
297277

298278
private static void validateProviderSettings(ProviderSettings providerSettings) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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 java.util.ArrayList;
19+
import java.util.List;
20+
21+
import org.springframework.http.HttpMethod;
22+
import org.springframework.security.authentication.AuthenticationManager;
23+
import org.springframework.security.config.annotation.ObjectPostProcessor;
24+
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
25+
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;
28+
import org.springframework.security.oauth2.server.authorization.oidc.web.OidcProviderConfigurationEndpointFilter;
29+
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
30+
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
31+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
32+
import org.springframework.security.web.util.matcher.OrRequestMatcher;
33+
import org.springframework.security.web.util.matcher.RequestMatcher;
34+
35+
/**
36+
* Configurer for OpenID Connect 1.0 support.
37+
*
38+
* @author Joe Grandja
39+
* @since 0.2.0
40+
* @see OAuth2AuthorizationServerConfigurer#oidc
41+
* @see OidcProviderConfigurationEndpointFilter
42+
* @see OidcClientRegistrationEndpointFilter
43+
*/
44+
public final class OidcConfigurer extends AbstractOAuth2Configurer {
45+
private RequestMatcher requestMatcher;
46+
47+
/**
48+
* Restrict for internal use only.
49+
*/
50+
OidcConfigurer(ObjectPostProcessor<Object> objectPostProcessor) {
51+
super(objectPostProcessor);
52+
}
53+
54+
@Override
55+
<B extends HttpSecurityBuilder<B>> void init(B builder) {
56+
List<RequestMatcher> requestMatchers = new ArrayList<>();
57+
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
58+
if (providerSettings.getIssuer() != null) {
59+
requestMatchers.add(
60+
new AntPathRequestMatcher(
61+
"/.well-known/openid-configuration",
62+
HttpMethod.GET.name()));
63+
}
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));
76+
}
77+
78+
@Override
79+
<B extends HttpSecurityBuilder<B>> void configure(B builder) {
80+
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
81+
if (providerSettings.getIssuer() != null) {
82+
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
83+
new OidcProviderConfigurationEndpointFilter(providerSettings);
84+
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
85+
}
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);
95+
}
96+
97+
@Override
98+
RequestMatcher getRequestMatcher() {
99+
return this.requestMatcher;
100+
}
101+
102+
}

0 commit comments

Comments
 (0)