Skip to content

Commit 666d569

Browse files
committed
Support resolving issuer from current request
Closes gh-479
1 parent 646ea00 commit 666d569

File tree

34 files changed

+468
-150
lines changed

34 files changed

+468
-150
lines changed

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

+9-7
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,17 @@ public void init(B builder) {
216216

217217
@Override
218218
public void configure(B builder) {
219+
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
220+
221+
// IMPORTANT:
222+
// This filter must be registered first as it resolves the current issuer identifier and
223+
// sets it as a request attribute under WebAttributes.ISSUER, which may be used by upstream components.
224+
OAuth2AuthorizationServerMetadataEndpointFilter authorizationServerMetadataEndpointFilter =
225+
new OAuth2AuthorizationServerMetadataEndpointFilter(providerSettings);
226+
builder.addFilterBefore(postProcess(authorizationServerMetadataEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
227+
219228
this.configurers.values().forEach(configurer -> configurer.configure(builder));
220229

221-
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
222230
AuthenticationManager authenticationManager = builder.getSharedObject(AuthenticationManager.class);
223231

224232
OAuth2TokenIntrospectionEndpointFilter tokenIntrospectionEndpointFilter =
@@ -238,12 +246,6 @@ public void configure(B builder) {
238246
OAuth2ConfigurerUtils.getJwkSource(builder),
239247
providerSettings.getJwkSetEndpoint());
240248
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-
}
247249
}
248250

249251
private Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer> createConfigurers() {

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

+6-11
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,13 @@ <B extends HttpSecurityBuilder<B>> void init(B builder) {
8585
}
8686

8787
List<RequestMatcher> requestMatchers = new ArrayList<>();
88-
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
89-
if (providerSettings.getIssuer() != null) {
90-
requestMatchers.add(new AntPathRequestMatcher(
91-
"/.well-known/openid-configuration", HttpMethod.GET.name()));
92-
}
88+
requestMatchers.add(new AntPathRequestMatcher(
89+
"/.well-known/openid-configuration", HttpMethod.GET.name()));
9390
requestMatchers.add(this.userInfoEndpointConfigurer.getRequestMatcher());
9491
if (this.clientRegistrationEndpointConfigurer != null) {
9592
requestMatchers.add(this.clientRegistrationEndpointConfigurer.getRequestMatcher());
9693
}
97-
this.requestMatcher = requestMatchers.size() > 1 ? new OrRequestMatcher(requestMatchers) : requestMatchers.get(0);
94+
this.requestMatcher = new OrRequestMatcher(requestMatchers);
9895
}
9996

10097
@Override
@@ -105,11 +102,9 @@ <B extends HttpSecurityBuilder<B>> void configure(B builder) {
105102
}
106103

107104
ProviderSettings providerSettings = OAuth2ConfigurerUtils.getProviderSettings(builder);
108-
if (providerSettings.getIssuer() != null) {
109-
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
110-
new OidcProviderConfigurationEndpointFilter(providerSettings);
111-
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
112-
}
105+
OidcProviderConfigurationEndpointFilter oidcProviderConfigurationEndpointFilter =
106+
new OidcProviderConfigurationEndpointFilter(providerSettings);
107+
builder.addFilterBefore(postProcess(oidcProviderConfigurationEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
113108
}
114109

115110
@Override

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import java.util.function.Consumer;
2727
import java.util.function.Supplier;
2828

29-
import org.springframework.beans.factory.annotation.Autowired;
3029
import org.springframework.security.authentication.AuthenticationProvider;
3130
import org.springframework.security.core.Authentication;
3231
import org.springframework.security.core.AuthenticationException;
@@ -87,7 +86,6 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth
8786
private final JwtEncoder jwtEncoder;
8887
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer = (context) -> {};
8988
private Supplier<String> refreshTokenGenerator = DEFAULT_REFRESH_TOKEN_GENERATOR::generateKey;
90-
private ProviderSettings providerSettings;
9189

9290
/**
9391
* Constructs an {@code OAuth2AuthorizationCodeAuthenticationProvider} using the provided parameters.
@@ -124,9 +122,8 @@ public void setRefreshTokenGenerator(Supplier<String> refreshTokenGenerator) {
124122
this.refreshTokenGenerator = refreshTokenGenerator;
125123
}
126124

127-
@Autowired(required = false)
125+
@Deprecated
128126
protected void setProviderSettings(ProviderSettings providerSettings) {
129-
this.providerSettings = providerSettings;
130127
}
131128

132129
@Override
@@ -167,7 +164,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
167164
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_GRANT);
168165
}
169166

170-
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
167+
String issuer = authorizationCodeAuthentication.getIssuer();
171168
Set<String> authorizedScopes = authorization.getAttribute(
172169
OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME);
173170

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationToken.java

+20
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends OAuth2Authorizat
4343
* @param clientPrincipal the authenticated client principal
4444
* @param redirectUri the redirect uri
4545
* @param additionalParameters the additional parameters
46+
* @deprecated Use {@link #OAuth2AuthorizationCodeAuthenticationToken(String, String, Authentication, String, Map)} instead
4647
*/
48+
@Deprecated
4749
public OAuth2AuthorizationCodeAuthenticationToken(String code, Authentication clientPrincipal,
4850
@Nullable String redirectUri, @Nullable Map<String, Object> additionalParameters) {
4951
super(AuthorizationGrantType.AUTHORIZATION_CODE, clientPrincipal, additionalParameters);
@@ -52,6 +54,24 @@ public OAuth2AuthorizationCodeAuthenticationToken(String code, Authentication cl
5254
this.redirectUri = redirectUri;
5355
}
5456

57+
/**
58+
* Constructs an {@code OAuth2AuthorizationCodeAuthenticationToken} using the provided parameters.
59+
*
60+
* @param issuer the issuer identifier
61+
* @param code the authorization code
62+
* @param clientPrincipal the authenticated client principal
63+
* @param redirectUri the redirect uri
64+
* @param additionalParameters the additional parameters
65+
* @since 0.2.1
66+
*/
67+
public OAuth2AuthorizationCodeAuthenticationToken(String issuer, String code, Authentication clientPrincipal,
68+
@Nullable String redirectUri, @Nullable Map<String, Object> additionalParameters) {
69+
super(AuthorizationGrantType.AUTHORIZATION_CODE, issuer, clientPrincipal, additionalParameters);
70+
Assert.hasText(code, "code cannot be empty");
71+
this.code = code;
72+
this.redirectUri = redirectUri;
73+
}
74+
5575
/**
5676
* Returns the authorization code.
5777
*

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationGrantAuthenticationToken.java

+38
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
public class OAuth2AuthorizationGrantAuthenticationToken extends AbstractAuthenticationToken {
4040
private static final long serialVersionUID = Version.SERIAL_VERSION_UID;
4141
private final AuthorizationGrantType authorizationGrantType;
42+
private final String issuer;
4243
private final Authentication clientPrincipal;
4344
private final Map<String, Object> additionalParameters;
4445

@@ -48,13 +49,40 @@ public class OAuth2AuthorizationGrantAuthenticationToken extends AbstractAuthent
4849
* @param authorizationGrantType the authorization grant type
4950
* @param clientPrincipal the authenticated client principal
5051
* @param additionalParameters the additional parameters
52+
* @deprecated Use {@link #OAuth2AuthorizationGrantAuthenticationToken(AuthorizationGrantType, String, Authentication, Map)} instead
5153
*/
54+
@Deprecated
5255
protected OAuth2AuthorizationGrantAuthenticationToken(AuthorizationGrantType authorizationGrantType,
5356
Authentication clientPrincipal, @Nullable Map<String, Object> additionalParameters) {
5457
super(Collections.emptyList());
5558
Assert.notNull(authorizationGrantType, "authorizationGrantType cannot be null");
5659
Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
5760
this.authorizationGrantType = authorizationGrantType;
61+
this.issuer = null;
62+
this.clientPrincipal = clientPrincipal;
63+
this.additionalParameters = Collections.unmodifiableMap(
64+
additionalParameters != null ?
65+
new HashMap<>(additionalParameters) :
66+
Collections.emptyMap());
67+
}
68+
69+
/**
70+
* Sub-class constructor.
71+
*
72+
* @param authorizationGrantType the authorization grant type
73+
* @param issuer the issuer identifier
74+
* @param clientPrincipal the authenticated client principal
75+
* @param additionalParameters the additional parameters
76+
* @since 0.2.1
77+
*/
78+
protected OAuth2AuthorizationGrantAuthenticationToken(AuthorizationGrantType authorizationGrantType,
79+
String issuer, Authentication clientPrincipal, @Nullable Map<String, Object> additionalParameters) {
80+
super(Collections.emptyList());
81+
Assert.notNull(authorizationGrantType, "authorizationGrantType cannot be null");
82+
Assert.hasText(issuer, "issuer cannot be empty");
83+
Assert.notNull(clientPrincipal, "clientPrincipal cannot be null");
84+
this.authorizationGrantType = authorizationGrantType;
85+
this.issuer = issuer;
5886
this.clientPrincipal = clientPrincipal;
5987
this.additionalParameters = Collections.unmodifiableMap(
6088
additionalParameters != null ?
@@ -71,6 +99,16 @@ public AuthorizationGrantType getGrantType() {
7199
return this.authorizationGrantType;
72100
}
73101

102+
/**
103+
* Returns the issuer identifier.
104+
*
105+
* @return the issuer identifier
106+
* @since 0.2.1
107+
*/
108+
public String getIssuer() {
109+
return this.issuer;
110+
}
111+
74112
@Override
75113
public Object getPrincipal() {
76114
return this.clientPrincipal;

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.Set;
2020
import java.util.function.Consumer;
2121

22-
import org.springframework.beans.factory.annotation.Autowired;
2322
import org.springframework.security.authentication.AuthenticationProvider;
2423
import org.springframework.security.core.Authentication;
2524
import org.springframework.security.core.AuthenticationException;
@@ -62,7 +61,6 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth
6261
private final OAuth2AuthorizationService authorizationService;
6362
private final JwtEncoder jwtEncoder;
6463
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer = (context) -> {};
65-
private ProviderSettings providerSettings;
6664

6765
/**
6866
* Constructs an {@code OAuth2ClientCredentialsAuthenticationProvider} using the provided parameters.
@@ -90,9 +88,8 @@ public void setJwtCustomizer(OAuth2TokenCustomizer<JwtEncodingContext> jwtCustom
9088
this.jwtCustomizer = jwtCustomizer;
9189
}
9290

93-
@Autowired(required = false)
91+
@Deprecated
9492
protected void setProviderSettings(ProviderSettings providerSettings) {
95-
this.providerSettings = providerSettings;
9693
}
9794

9895
@Override
@@ -118,7 +115,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
118115
authorizedScopes = new LinkedHashSet<>(clientCredentialsAuthentication.getScopes());
119116
}
120117

121-
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
118+
String issuer = clientCredentialsAuthentication.getIssuer();
122119

123120
JoseHeader.Builder headersBuilder = JwtUtils.headers();
124121
JwtClaimsSet.Builder claimsBuilder = JwtUtils.accessTokenClaims(

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationToken.java

+18
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,32 @@ public class OAuth2ClientCredentialsAuthenticationToken extends OAuth2Authorizat
4141
* @param clientPrincipal the authenticated client principal
4242
* @param scopes the requested scope(s)
4343
* @param additionalParameters the additional parameters
44+
* @deprecated Use {@link #OAuth2ClientCredentialsAuthenticationToken(String, Authentication, Set, Map)} instead
4445
*/
46+
@Deprecated
4547
public OAuth2ClientCredentialsAuthenticationToken(Authentication clientPrincipal,
4648
@Nullable Set<String> scopes, @Nullable Map<String, Object> additionalParameters) {
4749
super(AuthorizationGrantType.CLIENT_CREDENTIALS, clientPrincipal, additionalParameters);
4850
this.scopes = Collections.unmodifiableSet(
4951
scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
5052
}
5153

54+
/**
55+
* Constructs an {@code OAuth2ClientCredentialsAuthenticationToken} using the provided parameters.
56+
*
57+
* @param issuer the issuer identifier
58+
* @param clientPrincipal the authenticated client principal
59+
* @param scopes the requested scope(s)
60+
* @param additionalParameters the additional parameters
61+
* @since 0.2.1
62+
*/
63+
public OAuth2ClientCredentialsAuthenticationToken(String issuer, Authentication clientPrincipal,
64+
@Nullable Set<String> scopes, @Nullable Map<String, Object> additionalParameters) {
65+
super(AuthorizationGrantType.CLIENT_CREDENTIALS, issuer, clientPrincipal, additionalParameters);
66+
this.scopes = Collections.unmodifiableSet(
67+
scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
68+
}
69+
5270
/**
5371
* Returns the requested scope(s).
5472
*

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import java.util.function.Consumer;
2727
import java.util.function.Supplier;
2828

29-
import org.springframework.beans.factory.annotation.Autowired;
3029
import org.springframework.security.authentication.AuthenticationProvider;
3130
import org.springframework.security.core.Authentication;
3231
import org.springframework.security.core.AuthenticationException;
@@ -80,7 +79,6 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic
8079
private final JwtEncoder jwtEncoder;
8180
private OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer = (context) -> {};
8281
private Supplier<String> refreshTokenGenerator = DEFAULT_REFRESH_TOKEN_GENERATOR::generateKey;
83-
private ProviderSettings providerSettings;
8482

8583
/**
8684
* Constructs an {@code OAuth2RefreshTokenAuthenticationProvider} using the provided parameters.
@@ -118,9 +116,8 @@ public void setRefreshTokenGenerator(Supplier<String> refreshTokenGenerator) {
118116
this.refreshTokenGenerator = refreshTokenGenerator;
119117
}
120118

121-
@Autowired(required = false)
119+
@Deprecated
122120
protected void setProviderSettings(ProviderSettings providerSettings) {
123-
this.providerSettings = providerSettings;
124121
}
125122

126123
@Override
@@ -166,7 +163,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
166163
scopes = authorizedScopes;
167164
}
168165

169-
String issuer = this.providerSettings != null ? this.providerSettings.getIssuer() : null;
166+
String issuer = refreshTokenAuthentication.getIssuer();
170167

171168
JoseHeader.Builder headersBuilder = JwtUtils.headers();
172169
JwtClaimsSet.Builder claimsBuilder = JwtUtils.accessTokenClaims(

oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationToken.java

+21
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ public class OAuth2RefreshTokenAuthenticationToken extends OAuth2AuthorizationGr
4444
* @param clientPrincipal the authenticated client principal
4545
* @param scopes the requested scope(s)
4646
* @param additionalParameters the additional parameters
47+
* @deprecated Use {@link #OAuth2RefreshTokenAuthenticationToken(String, String, Authentication, Set, Map)} instead
4748
*/
49+
@Deprecated
4850
public OAuth2RefreshTokenAuthenticationToken(String refreshToken, Authentication clientPrincipal,
4951
@Nullable Set<String> scopes, @Nullable Map<String, Object> additionalParameters) {
5052
super(AuthorizationGrantType.REFRESH_TOKEN, clientPrincipal, additionalParameters);
@@ -54,6 +56,25 @@ public OAuth2RefreshTokenAuthenticationToken(String refreshToken, Authentication
5456
scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
5557
}
5658

59+
/**
60+
* Constructs an {@code OAuth2RefreshTokenAuthenticationToken} using the provided parameters.
61+
*
62+
* @param issuer the issuer identifier
63+
* @param refreshToken the refresh token
64+
* @param clientPrincipal the authenticated client principal
65+
* @param scopes the requested scope(s)
66+
* @param additionalParameters the additional parameters
67+
* @since 0.2.1
68+
*/
69+
public OAuth2RefreshTokenAuthenticationToken(String issuer, String refreshToken, Authentication clientPrincipal,
70+
@Nullable Set<String> scopes, @Nullable Map<String, Object> additionalParameters) {
71+
super(AuthorizationGrantType.REFRESH_TOKEN, issuer, clientPrincipal, additionalParameters);
72+
Assert.hasText(refreshToken, "refreshToken cannot be empty");
73+
this.refreshToken = refreshToken;
74+
this.scopes = Collections.unmodifiableSet(
75+
scopes != null ? new HashSet<>(scopes) : Collections.emptySet());
76+
}
77+
5778
/**
5879
* Returns the refresh token.
5980
*

0 commit comments

Comments
 (0)