Skip to content

Commit 8edbc26

Browse files
committed
Add convenience method for invalidating an OAuth2Token
Closes gh-1717
1 parent 5b7e815 commit 8edbc26

13 files changed

+64
-101
lines changed

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

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2024 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.
@@ -479,7 +479,6 @@ public <T extends OAuth2Token> Builder token(T token) {
479479
* @return the {@link Builder}
480480
*/
481481
public <T extends OAuth2Token> Builder token(T token, Consumer<Map<String, Object>> metadataConsumer) {
482-
483482
Assert.notNull(token, "token cannot be null");
484483
Map<String, Object> metadata = Token.defaultMetadata();
485484
Token<?> existingToken = this.tokens.get(token.getClass());
@@ -492,6 +491,33 @@ public <T extends OAuth2Token> Builder token(T token, Consumer<Map<String, Objec
492491
return this;
493492
}
494493

494+
/**
495+
* Invalidates the {@link OAuth2Token token}.
496+
* @param token the token
497+
* @param <T> the type of the token
498+
* @return the {@link Builder}
499+
* @since 1.4
500+
*/
501+
public <T extends OAuth2Token> Builder invalidate(T token) {
502+
Assert.notNull(token, "token cannot be null");
503+
if (this.tokens.get(token.getClass()) == null) {
504+
return this;
505+
}
506+
token(token, (metadata) -> metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
507+
if (OAuth2RefreshToken.class.isAssignableFrom(token.getClass())) {
508+
Token<?> accessToken = this.tokens.get(OAuth2AccessToken.class);
509+
token(accessToken.getToken(),
510+
(metadata) -> metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
511+
512+
Token<?> authorizationCode = this.tokens.get(OAuth2AuthorizationCode.class);
513+
if (authorizationCode != null && !authorizationCode.isInvalidated()) {
514+
token(authorizationCode.getToken(),
515+
(metadata) -> metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
516+
}
517+
}
518+
return this;
519+
}
520+
495521
protected final Builder tokens(Map<Class<? extends OAuth2Token>, Token<?>> tokens) {
496522
this.tokens = new HashMap<>(tokens);
497523
return this;

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

+1-31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2024 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.
@@ -21,10 +21,8 @@
2121
import org.springframework.security.oauth2.core.OAuth2AccessToken;
2222
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
2323
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
24-
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
2524
import org.springframework.security.oauth2.core.OAuth2Token;
2625
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
27-
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
2826
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
2927
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext;
3028

@@ -50,34 +48,6 @@ static OAuth2ClientAuthenticationToken getAuthenticatedClientElseThrowInvalidCli
5048
throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_CLIENT);
5149
}
5250

53-
static <T extends OAuth2Token> OAuth2Authorization invalidate(OAuth2Authorization authorization, T token) {
54-
55-
// @formatter:off
56-
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.from(authorization)
57-
.token(token,
58-
(metadata) ->
59-
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
60-
61-
if (OAuth2RefreshToken.class.isAssignableFrom(token.getClass())) {
62-
authorizationBuilder.token(
63-
authorization.getAccessToken().getToken(),
64-
(metadata) ->
65-
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
66-
67-
OAuth2Authorization.Token<OAuth2AuthorizationCode> authorizationCode =
68-
authorization.getToken(OAuth2AuthorizationCode.class);
69-
if (authorizationCode != null && !authorizationCode.isInvalidated()) {
70-
authorizationBuilder.token(
71-
authorizationCode.getToken(),
72-
(metadata) ->
73-
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
74-
}
75-
}
76-
// @formatter:on
77-
78-
return authorizationBuilder.build();
79-
}
80-
8151
static <T extends OAuth2Token> OAuth2AccessToken accessToken(OAuth2Authorization.Builder builder, T token,
8252
OAuth2TokenContext accessTokenContext) {
8353

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

+7-6
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ public Authentication authenticate(Authentication authentication) throws Authent
144144
if (!authorizationCode.isInvalidated()) {
145145
// Invalidate the authorization code given that a different client is
146146
// attempting to use it
147-
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization,
148-
authorizationCode.getToken());
147+
authorization = OAuth2Authorization.from(authorization)
148+
.invalidate(authorizationCode.getToken())
149+
.build();
149150
this.authorizationService.save(authorization);
150151
if (this.logger.isWarnEnabled()) {
151152
this.logger.warn(LogMessage.format("Invalidated authorization code used by registered client '%s'",
@@ -172,7 +173,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
172173
if (token != null) {
173174
// Invalidate the access (and refresh) token as the client is
174175
// attempting to use the authorization code more than once
175-
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, token.getToken());
176+
authorization = OAuth2Authorization.from(authorization).invalidate(token.getToken()).build();
176177
this.authorizationService.save(authorization);
177178
if (this.logger.isWarnEnabled()) {
178179
this.logger.warn(LogMessage.format(
@@ -284,10 +285,10 @@ public Authentication authenticate(Authentication authentication) throws Authent
284285
idToken = null;
285286
}
286287

287-
authorization = authorizationBuilder.build();
288-
289288
// Invalidate the authorization code as it can only be used once
290-
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, authorizationCode.getToken());
289+
authorizationBuilder.invalidate(authorizationCode.getToken());
290+
291+
authorization = authorizationBuilder.build();
291292

292293
this.authorizationService.save(authorization);
293294

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

+4-7
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-2024 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.
@@ -187,10 +187,8 @@ public Authentication authenticate(Authentication authentication) throws Authent
187187
}
188188
}
189189
authorization = OAuth2Authorization.from(authorization)
190-
.token((deviceCodeToken.getToken()),
191-
(metadata) -> metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true))
192-
.token((userCodeToken.getToken()),
193-
(metadata) -> metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true))
190+
.invalidate(deviceCodeToken.getToken())
191+
.invalidate(userCodeToken.getToken())
194192
.attributes((attrs) -> attrs.remove(OAuth2ParameterNames.STATE))
195193
.build();
196194
this.authorizationService.save(authorization);
@@ -210,8 +208,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
210208

211209
authorization = OAuth2Authorization.from(authorization)
212210
.authorizedScopes(authorizedScopes)
213-
.token((userCodeToken.getToken()),
214-
(metadata) -> metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true))
211+
.invalidate(userCodeToken.getToken())
215212
.attributes((attrs) -> attrs.remove(OAuth2ParameterNames.STATE))
216213
.attributes((attrs) -> attrs.remove(OAuth2ParameterNames.SCOPE))
217214
.build();

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

+4-5
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-2024 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.
@@ -124,7 +124,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
124124
if (!deviceCode.isInvalidated()) {
125125
// Invalidate the device code given that a different client is attempting
126126
// to use it
127-
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, deviceCode.getToken());
127+
authorization = OAuth2Authorization.from(authorization).invalidate(deviceCode.getToken()).build();
128128
this.authorizationService.save(authorization);
129129
if (this.logger.isWarnEnabled()) {
130130
this.logger.warn(LogMessage.format("Invalidated device code used by registered client '%s'",
@@ -172,7 +172,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
172172
// restarting to avoid unnecessary polling.
173173
if (deviceCode.isExpired()) {
174174
// Invalidate the device code
175-
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, deviceCode.getToken());
175+
authorization = OAuth2Authorization.from(authorization).invalidate(deviceCode.getToken()).build();
176176
this.authorizationService.save(authorization);
177177
if (this.logger.isWarnEnabled()) {
178178
this.logger.warn(LogMessage.format("Invalidated device code used by registered client '%s'",
@@ -200,8 +200,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
200200
// @formatter:off
201201
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.from(authorization)
202202
// Invalidate the device code as it can only be used (successfully) once
203-
.token(deviceCode.getToken(), (metadata) ->
204-
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
203+
.invalidate(deviceCode.getToken());
205204
// @formatter:on
206205

207206
// ----- Access token -----

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

+2-3
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-2024 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.
@@ -166,8 +166,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
166166
authorization = OAuth2Authorization.from(authorization)
167167
.principalName(principal.getName())
168168
.authorizedScopes(requestedScopes)
169-
.token(userCode.getToken(), (metadata) -> metadata
170-
.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true))
169+
.invalidate(userCode.getToken())
171170
.attribute(Principal.class.getName(), principal)
172171
.attributes((attributes) -> attributes.remove(OAuth2ParameterNames.SCOPE))
173172
.build();

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2024 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.
@@ -79,7 +79,7 @@ public Authentication authenticate(Authentication authentication) throws Authent
7979
}
8080

8181
OAuth2Authorization.Token<OAuth2Token> token = authorization.getToken(tokenRevocationAuthentication.getToken());
82-
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, token.getToken());
82+
authorization = OAuth2Authorization.from(authorization).invalidate(token.getToken()).build();
8383
this.authorizationService.save(authorization);
8484

8585
if (this.logger.isTraceEnabled()) {

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

+1-31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2024 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.
@@ -18,10 +18,8 @@
1818
import org.springframework.security.authentication.AuthenticationProvider;
1919
import org.springframework.security.oauth2.core.ClaimAccessor;
2020
import org.springframework.security.oauth2.core.OAuth2AccessToken;
21-
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
2221
import org.springframework.security.oauth2.core.OAuth2Token;
2322
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
24-
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationCode;
2523
import org.springframework.security.oauth2.server.authorization.settings.OAuth2TokenFormat;
2624
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext;
2725

@@ -36,34 +34,6 @@ final class OidcAuthenticationProviderUtils {
3634
private OidcAuthenticationProviderUtils() {
3735
}
3836

39-
static <T extends OAuth2Token> OAuth2Authorization invalidate(OAuth2Authorization authorization, T token) {
40-
41-
// @formatter:off
42-
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.from(authorization)
43-
.token(token,
44-
(metadata) ->
45-
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
46-
47-
if (OAuth2RefreshToken.class.isAssignableFrom(token.getClass())) {
48-
authorizationBuilder.token(
49-
authorization.getAccessToken().getToken(),
50-
(metadata) ->
51-
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
52-
53-
OAuth2Authorization.Token<OAuth2AuthorizationCode> authorizationCode =
54-
authorization.getToken(OAuth2AuthorizationCode.class);
55-
if (authorizationCode != null && !authorizationCode.isInvalidated()) {
56-
authorizationBuilder.token(
57-
authorizationCode.getToken(),
58-
(metadata) ->
59-
metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true));
60-
}
61-
}
62-
// @formatter:on
63-
64-
return authorizationBuilder.build();
65-
}
66-
6737
static <T extends OAuth2Token> OAuth2AccessToken accessToken(OAuth2Authorization.Builder builder, T token,
6838
OAuth2TokenContext accessTokenContext) {
6939

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

+5-5
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-2024 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.
@@ -260,12 +260,12 @@ private OidcClientRegistrationAuthenticationToken registerClient(
260260
OAuth2Authorization registeredClientAuthorization = registerAccessToken(registeredClient);
261261

262262
// Invalidate the "initial" access token as it can only be used once
263-
authorization = OidcAuthenticationProviderUtils.invalidate(authorization,
264-
authorization.getAccessToken().getToken());
263+
OAuth2Authorization.Builder builder = OAuth2Authorization.from(authorization)
264+
.invalidate(authorization.getAccessToken().getToken());
265265
if (authorization.getRefreshToken() != null) {
266-
authorization = OidcAuthenticationProviderUtils.invalidate(authorization,
267-
authorization.getRefreshToken().getToken());
266+
builder.invalidate(authorization.getRefreshToken().getToken());
268267
}
268+
authorization = builder.build();
269269
this.authorizationService.save(authorization);
270270

271271
if (this.logger.isTraceEnabled()) {

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenIntrospectionAuthenticationProviderTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2024 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.
@@ -147,7 +147,7 @@ public void authenticateWhenTokenInvalidatedThenNotActive() {
147147
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
148148
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization(registeredClient).build();
149149
OAuth2AccessToken accessToken = authorization.getAccessToken().getToken();
150-
authorization = OAuth2AuthenticationProviderUtils.invalidate(authorization, accessToken);
150+
authorization = OAuth2Authorization.from(authorization).invalidate(accessToken).build();
151151
given(this.authorizationService.findByToken(eq(accessToken.getTokenValue()), isNull()))
152152
.willReturn(authorization);
153153
OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken(registeredClient,

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientConfigurationAuthenticationProviderTests.java

+2-2
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-2024 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.
@@ -176,8 +176,8 @@ public void authenticateWhenAccessTokenNotActiveThenThrowOAuth2AuthenticationExc
176176
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
177177
OAuth2Authorization authorization = TestOAuth2Authorizations
178178
.authorization(registeredClient, jwtAccessToken, jwt.getClaims())
179+
.invalidate(jwtAccessToken)
179180
.build();
180-
authorization = OidcAuthenticationProviderUtils.invalidate(authorization, jwtAccessToken);
181181
given(this.authorizationService.findByToken(eq(jwtAccessToken.getTokenValue()),
182182
eq(OAuth2TokenType.ACCESS_TOKEN)))
183183
.willReturn(authorization);

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcClientRegistrationAuthenticationProviderTests.java

+2-2
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-2024 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.
@@ -250,8 +250,8 @@ public void authenticateWhenAccessTokenNotActiveThenThrowOAuth2AuthenticationExc
250250
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build();
251251
OAuth2Authorization authorization = TestOAuth2Authorizations
252252
.authorization(registeredClient, jwtAccessToken, jwt.getClaims())
253+
.invalidate(jwtAccessToken)
253254
.build();
254-
authorization = OidcAuthenticationProviderUtils.invalidate(authorization, jwtAccessToken);
255255
given(this.authorizationService.findByToken(eq(jwtAccessToken.getTokenValue()),
256256
eq(OAuth2TokenType.ACCESS_TOKEN)))
257257
.willReturn(authorization);

oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcUserInfoAuthenticationProviderTests.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 the original author or authors.
2+
* Copyright 2020-2024 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.
@@ -133,8 +133,9 @@ public void authenticateWhenAccessTokenNotFoundThenThrowOAuth2AuthenticationExce
133133
public void authenticateWhenAccessTokenNotActiveThenThrowOAuth2AuthenticationException() {
134134
String tokenValue = "token";
135135
OAuth2Authorization authorization = TestOAuth2Authorizations.authorization().build();
136-
authorization = OidcAuthenticationProviderUtils.invalidate(authorization,
137-
authorization.getAccessToken().getToken());
136+
authorization = OAuth2Authorization.from(authorization)
137+
.invalidate(authorization.getAccessToken().getToken())
138+
.build();
138139
given(this.authorizationService.findByToken(eq(tokenValue), eq(OAuth2TokenType.ACCESS_TOKEN)))
139140
.willReturn(authorization);
140141

0 commit comments

Comments
 (0)