Skip to content

Commit ab37e37

Browse files
committed
Token Exchange review updates
Issue spring-projectsgh-60
1 parent e7a0c06 commit ab37e37

21 files changed

+287
-379
lines changed

Diff for: oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/aot/hint/OAuth2AuthorizationServerBeanRegistrationAotProcessor.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
4444
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
4545
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
46-
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ActorAuthenticationToken;
47-
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2CompositeAuthenticationToken;
46+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeActor;
47+
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2TokenExchangeCompositeAuthenticationToken;
4848
import org.springframework.security.oauth2.server.authorization.jackson2.OAuth2AuthorizationServerJackson2Module;
4949
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
5050
import org.springframework.security.web.authentication.WebAuthenticationDetails;
@@ -111,9 +111,9 @@ private void registerHints(RuntimeHints hints) {
111111
TypeReference.of(OidcIdToken.class),
112112
TypeReference.of(AbstractOAuth2Token.class),
113113
TypeReference.of(OidcUserInfo.class),
114-
TypeReference.of(OAuth2ActorAuthenticationToken.class),
114+
TypeReference.of(OAuth2TokenExchangeActor.class),
115115
TypeReference.of(OAuth2AuthorizationRequest.class),
116-
TypeReference.of(OAuth2CompositeAuthenticationToken.class),
116+
TypeReference.of(OAuth2TokenExchangeCompositeAuthenticationToken.class),
117117
TypeReference.of(AuthorizationGrantType.class),
118118
TypeReference.of(OAuth2AuthorizationResponseType.class),
119119
TypeReference.of(OAuth2TokenFormat.class)

Diff for: oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ActorAuthenticationToken.java

-53
This file was deleted.

Diff for: oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthenticationProviderUtils.java

+24
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717

1818
import org.springframework.security.authentication.AuthenticationProvider;
1919
import org.springframework.security.core.Authentication;
20+
import org.springframework.security.oauth2.core.ClaimAccessor;
21+
import org.springframework.security.oauth2.core.OAuth2AccessToken;
2022
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
2123
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
2224
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
2325
import org.springframework.security.oauth2.core.OAuth2Token;
2426
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
2527
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
28+
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
29+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext;
2630

2731
/**
2832
* Utility methods for the OAuth 2.0 {@link AuthenticationProvider}'s.
@@ -74,4 +78,24 @@ static <T extends OAuth2Token> OAuth2Authorization invalidate(
7478

7579
return authorizationBuilder.build();
7680
}
81+
82+
static <T extends OAuth2Token> OAuth2AccessToken accessToken(OAuth2Authorization.Builder builder, T token,
83+
OAuth2TokenContext accessTokenContext) {
84+
85+
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
86+
token.getTokenValue(), token.getIssuedAt(), token.getExpiresAt(),
87+
accessTokenContext.getAuthorizedScopes());
88+
OAuth2TokenFormat accessTokenFormat = accessTokenContext.getRegisteredClient().getTokenSettings()
89+
.getAccessTokenFormat();
90+
builder.token(accessToken, (metadata) -> {
91+
if (token instanceof ClaimAccessor claimAccessor) {
92+
metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, claimAccessor.getClaims());
93+
}
94+
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, false);
95+
metadata.put(OAuth2TokenFormat.class.getName(), accessTokenFormat.getValue());
96+
});
97+
98+
return accessToken;
99+
}
100+
77101
}

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

+2-10
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import org.springframework.security.core.session.SessionInformation;
3838
import org.springframework.security.core.session.SessionRegistry;
3939
import org.springframework.security.oauth2.core.AuthorizationGrantType;
40-
import org.springframework.security.oauth2.core.ClaimAccessor;
4140
import org.springframework.security.oauth2.core.OAuth2AccessToken;
4241
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
4342
import org.springframework.security.oauth2.core.OAuth2Error;
@@ -204,15 +203,8 @@ public Authentication authenticate(Authentication authentication) throws Authent
204203
this.logger.trace("Generated access token");
205204
}
206205

207-
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
208-
generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
209-
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
210-
if (generatedAccessToken instanceof ClaimAccessor) {
211-
authorizationBuilder.token(accessToken, (metadata) ->
212-
metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims()));
213-
} else {
214-
authorizationBuilder.accessToken(accessToken);
215-
}
206+
OAuth2AccessToken accessToken = OAuth2AuthenticationProviderUtils.accessToken(authorizationBuilder,
207+
generatedAccessToken, tokenContext);
216208

217209
// ----- Refresh token -----
218210
OAuth2RefreshToken refreshToken = null;

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

+3-11
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.springframework.security.core.Authentication;
2828
import org.springframework.security.core.AuthenticationException;
2929
import org.springframework.security.oauth2.core.AuthorizationGrantType;
30-
import org.springframework.security.oauth2.core.ClaimAccessor;
3130
import org.springframework.security.oauth2.core.OAuth2AccessToken;
3231
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
3332
import org.springframework.security.oauth2.core.OAuth2Error;
@@ -137,22 +136,15 @@ public Authentication authenticate(Authentication authentication) throws Authent
137136
this.logger.trace("Generated access token");
138137
}
139138

140-
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
141-
generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
142-
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
143-
144139
// @formatter:off
145140
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient)
146141
.principalName(clientPrincipal.getName())
147142
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
148143
.authorizedScopes(authorizedScopes);
149144
// @formatter:on
150-
if (generatedAccessToken instanceof ClaimAccessor) {
151-
authorizationBuilder.token(accessToken, (metadata) ->
152-
metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims()));
153-
} else {
154-
authorizationBuilder.accessToken(accessToken);
155-
}
145+
146+
OAuth2AccessToken accessToken = OAuth2AuthenticationProviderUtils.accessToken(authorizationBuilder,
147+
generatedAccessToken, tokenContext);
156148

157149
OAuth2Authorization authorization = authorizationBuilder.build();
158150

Diff for: oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2DeviceCodeAuthenticationProvider.java

+2-10
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.springframework.security.core.Authentication;
2626
import org.springframework.security.core.AuthenticationException;
2727
import org.springframework.security.oauth2.core.AuthorizationGrantType;
28-
import org.springframework.security.oauth2.core.ClaimAccessor;
2928
import org.springframework.security.oauth2.core.OAuth2AccessToken;
3029
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
3130
import org.springframework.security.oauth2.core.OAuth2DeviceCode;
@@ -213,15 +212,8 @@ public Authentication authenticate(Authentication authentication) throws Authent
213212
this.logger.trace("Generated access token");
214213
}
215214

216-
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
217-
generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
218-
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
219-
if (generatedAccessToken instanceof ClaimAccessor) {
220-
authorizationBuilder.token(accessToken, (metadata) ->
221-
metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims()));
222-
} else {
223-
authorizationBuilder.accessToken(accessToken);
224-
}
215+
OAuth2AccessToken accessToken = OAuth2AuthenticationProviderUtils.accessToken(authorizationBuilder,
216+
generatedAccessToken, tokenContext);
225217

226218
// ----- Refresh token -----
227219
OAuth2RefreshToken refreshToken = null;

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

+2-12
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.springframework.security.core.Authentication;
3030
import org.springframework.security.core.AuthenticationException;
3131
import org.springframework.security.oauth2.core.AuthorizationGrantType;
32-
import org.springframework.security.oauth2.core.ClaimAccessor;
3332
import org.springframework.security.oauth2.core.OAuth2AccessToken;
3433
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
3534
import org.springframework.security.oauth2.core.OAuth2Error;
@@ -181,17 +180,8 @@ public Authentication authenticate(Authentication authentication) throws Authent
181180
this.logger.trace("Generated access token");
182181
}
183182

184-
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
185-
generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
186-
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
187-
if (generatedAccessToken instanceof ClaimAccessor) {
188-
authorizationBuilder.token(accessToken, (metadata) -> {
189-
metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims());
190-
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, false);
191-
});
192-
} else {
193-
authorizationBuilder.accessToken(accessToken);
194-
}
183+
OAuth2AccessToken accessToken = OAuth2AuthenticationProviderUtils.accessToken(authorizationBuilder,
184+
generatedAccessToken, tokenContext);
195185

196186
// ----- Refresh token -----
197187
OAuth2RefreshToken currentRefreshToken = refreshToken.getToken();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2020-2024 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+
17+
package org.springframework.security.oauth2.server.authorization.authentication;
18+
19+
import java.util.Collections;
20+
import java.util.Map;
21+
import java.util.Objects;
22+
23+
import org.springframework.security.oauth2.core.ClaimAccessor;
24+
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenClaimNames;
25+
import org.springframework.util.Assert;
26+
27+
/**
28+
* A {@link ClaimAccessor} used for the OAuth 2.0 Token Exchange Grant to represent an actor in a
29+
* {@link OAuth2TokenExchangeCompositeAuthenticationToken} (e.g. the "delegation" use case).
30+
*
31+
* @author Steve Riesenberg
32+
* @since 1.3
33+
* @see OAuth2TokenExchangeCompositeAuthenticationToken
34+
*/
35+
public final class OAuth2TokenExchangeActor implements ClaimAccessor {
36+
37+
private final Map<String, Object> claims;
38+
39+
public OAuth2TokenExchangeActor(Map<String, Object> claims) {
40+
Assert.notNull(claims, "claims cannot be null");
41+
this.claims = Collections.unmodifiableMap(claims);
42+
}
43+
44+
@Override
45+
public Map<String, Object> getClaims() {
46+
return this.claims;
47+
}
48+
49+
public String getIssuer() {
50+
return getClaimAsString(OAuth2TokenClaimNames.ISS);
51+
}
52+
53+
public String getSubject() {
54+
return getClaimAsString(OAuth2TokenClaimNames.SUB);
55+
}
56+
57+
@Override
58+
public boolean equals(Object obj) {
59+
if (!(obj instanceof OAuth2TokenExchangeActor other)) {
60+
return false;
61+
}
62+
return Objects.equals(this.claims, other.claims);
63+
}
64+
65+
@Override
66+
public int hashCode() {
67+
return Objects.hash(this.claims);
68+
}
69+
70+
}

0 commit comments

Comments
 (0)