Skip to content

Commit 209c81d

Browse files
committed
Add BadOpaqueTokenException
Updated NimbusOpaqueTokenIntrospector and NimbusReactiveOpaqueTokenIntrospector to throw. Updated OpaqueTokenAuthenticationProvider and OpaqueTokenReactiveAuthenticationManager to catch. Fixes gh-7902
1 parent 0c3754c commit 209c81d

File tree

10 files changed

+63
-25
lines changed

10 files changed

+63
-25
lines changed

config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,7 @@ public void getWhenIntrospectionFailsThenUnauthorized() throws Exception {
11581158
.with(bearerToken("token")))
11591159
.andExpect(status().isUnauthorized())
11601160
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE,
1161-
containsString("Provided token [token] isn't active")));
1161+
containsString("Provided token isn't active")));
11621162
}
11631163

11641164
@Test

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020

2121
import org.springframework.security.authentication.AbstractAuthenticationToken;
2222
import org.springframework.security.authentication.AuthenticationProvider;
23+
import org.springframework.security.authentication.AuthenticationServiceException;
2324
import org.springframework.security.core.Authentication;
2425
import org.springframework.security.core.AuthenticationException;
2526
import org.springframework.security.core.GrantedAuthority;
2627
import org.springframework.security.oauth2.core.OAuth2AccessToken;
2728
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
2829
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
2930
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
31+
import org.springframework.security.oauth2.server.resource.introspection.BadOpaqueTokenException;
3032
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
3133
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
3234
import org.springframework.util.Assert;
@@ -88,8 +90,10 @@ public Authentication authenticate(Authentication authentication) throws Authent
8890
OAuth2AuthenticatedPrincipal principal;
8991
try {
9092
principal = this.introspector.introspect(bearer.getToken());
91-
} catch (OAuth2IntrospectionException failed) {
93+
} catch (BadOpaqueTokenException failed) {
9294
throw new InvalidBearerTokenException(failed.getMessage());
95+
} catch (OAuth2IntrospectionException failed) {
96+
throw new AuthenticationServiceException(failed.getMessage());
9397
}
9498

9599
AbstractAuthenticationToken result = convert(principal, bearer.getToken());

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121

2222
import reactor.core.publisher.Mono;
2323

24+
import org.springframework.security.authentication.AuthenticationServiceException;
2425
import org.springframework.security.authentication.ReactiveAuthenticationManager;
2526
import org.springframework.security.core.Authentication;
27+
import org.springframework.security.core.AuthenticationException;
2628
import org.springframework.security.core.GrantedAuthority;
2729
import org.springframework.security.oauth2.core.OAuth2AccessToken;
28-
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
2930
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
3031
import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
32+
import org.springframework.security.oauth2.server.resource.introspection.BadOpaqueTokenException;
3133
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
3234
import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector;
3335
import org.springframework.util.Assert;
@@ -94,7 +96,11 @@ private Mono<BearerTokenAuthentication> authenticate(String token) {
9496
.onErrorMap(OAuth2IntrospectionException.class, this::onError);
9597
}
9698

97-
private OAuth2AuthenticationException onError(OAuth2IntrospectionException e) {
98-
return new InvalidBearerTokenException(e.getMessage(), e);
99+
private AuthenticationException onError(OAuth2IntrospectionException e) {
100+
if (e instanceof BadOpaqueTokenException) {
101+
return new InvalidBearerTokenException(e.getMessage(), e);
102+
} else {
103+
return new AuthenticationServiceException(e.getMessage(), e);
104+
}
99105
}
100106
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2002-2020 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.resource.introspection;
18+
19+
/**
20+
* An exception similar to {@link org.springframework.security.authentication.BadCredentialsException}
21+
* that indicates an opaque token that is invalid in some way.
22+
*
23+
* @author Josh Cummings
24+
* @since 5.3
25+
*/
26+
public class BadOpaqueTokenException extends OAuth2IntrospectionException {
27+
public BadOpaqueTokenException(String message) {
28+
super(message);
29+
}
30+
31+
public BadOpaqueTokenException(String message, Throwable cause) {
32+
super(message, cause);
33+
}
34+
}

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import java.util.Collections;
2525
import java.util.List;
2626
import java.util.Map;
27-
import java.util.ArrayList;
2827

2928
import com.nimbusds.oauth2.sdk.TokenIntrospectionResponse;
3029
import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
@@ -133,7 +132,7 @@ private MultiValueMap<String, String> requestBody(String token) {
133132
public OAuth2AuthenticatedPrincipal introspect(String token) {
134133
RequestEntity<?> requestEntity = this.requestEntityConverter.convert(token);
135134
if (requestEntity == null) {
136-
throw new OAuth2IntrospectionException("Provided token [" + token + "] isn't active");
135+
throw new OAuth2IntrospectionException("requestEntityConverter returned a null entity");
137136
}
138137

139138
ResponseEntity<String> responseEntity = makeRequest(requestEntity);
@@ -143,7 +142,7 @@ public OAuth2AuthenticatedPrincipal introspect(String token) {
143142

144143
// relying solely on the authorization server to validate this token (not checking 'exp', for example)
145144
if (!introspectionSuccessResponse.isActive()) {
146-
throw new OAuth2IntrospectionException("Provided token [" + token + "] isn't active");
145+
throw new BadOpaqueTokenException("Provided token isn't active");
147146
}
148147

149148
return convertClaimsSet(introspectionSuccessResponse);

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,15 @@
2424
import java.util.Collections;
2525
import java.util.List;
2626
import java.util.Map;
27-
import java.util.ArrayList;
2827

2928
import com.nimbusds.oauth2.sdk.TokenIntrospectionResponse;
3029
import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
3130
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
3231
import com.nimbusds.oauth2.sdk.id.Audience;
33-
import org.springframework.core.io.buffer.DataBuffer;
34-
import org.springframework.core.io.buffer.DataBufferUtils;
3532
import reactor.core.publisher.Mono;
3633

34+
import org.springframework.core.io.buffer.DataBuffer;
35+
import org.springframework.core.io.buffer.DataBufferUtils;
3736
import org.springframework.http.HttpHeaders;
3837
import org.springframework.http.MediaType;
3938
import org.springframework.security.core.GrantedAuthority;
@@ -154,7 +153,7 @@ private TokenIntrospectionSuccessResponse castToNimbusSuccess(TokenIntrospection
154153
private void validate(String token, TokenIntrospectionSuccessResponse response) {
155154
// relying solely on the authorization server to validate this token (not checking 'exp', for example)
156155
if (!response.isActive()) {
157-
throw new OAuth2IntrospectionException("Provided token [" + token + "] isn't active");
156+
throw new BadOpaqueTokenException("Provided token isn't active");
158157
}
159158
}
160159

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProviderTests.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323

2424
import org.junit.Test;
2525

26+
import org.springframework.security.authentication.AuthenticationServiceException;
2627
import org.springframework.security.core.Authentication;
2728
import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal;
2829
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
29-
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
3030
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
3131
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
3232
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
@@ -109,9 +109,7 @@ public void authenticateWhenIntrospectionEndpointThrowsExceptionThenInvalidToken
109109
OpaqueTokenAuthenticationProvider provider = new OpaqueTokenAuthenticationProvider(introspector);
110110

111111
assertThatCode(() -> provider.authenticate(new BearerTokenAuthenticationToken("token")))
112-
.isInstanceOf(OAuth2AuthenticationException.class)
113-
.extracting("error.description")
114-
.isEqualTo("Invalid token");
112+
.isInstanceOf(AuthenticationServiceException.class);
115113
}
116114

117115
@Test

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManagerTests.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
import org.junit.Test;
2626
import reactor.core.publisher.Mono;
2727

28+
import org.springframework.security.authentication.AuthenticationServiceException;
2829
import org.springframework.security.core.Authentication;
2930
import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal;
3031
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
31-
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
3232
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
3333
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
3434
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
@@ -115,9 +115,7 @@ public void authenticateWhenIntrospectionEndpointThrowsExceptionThenInvalidToken
115115
new OpaqueTokenReactiveAuthenticationManager(introspector);
116116

117117
assertThatCode(() -> provider.authenticate(new BearerTokenAuthenticationToken("token")).block())
118-
.isInstanceOf(OAuth2AuthenticationException.class)
119-
.extracting("error.description")
120-
.isEqualTo("Invalid token");
118+
.isInstanceOf(AuthenticationServiceException.class);
121119
}
122120

123121
@Test

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospectorTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 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.
@@ -168,7 +168,7 @@ public void introspectWhenInactiveTokenThenInvalidToken() {
168168
assertThatCode(() -> introspectionClient.introspect("token"))
169169
.isInstanceOf(OAuth2IntrospectionException.class)
170170
.extracting("message")
171-
.isEqualTo("Provided token [token] isn't active");
171+
.isEqualTo("Provided token isn't active");
172172
}
173173

174174
@Test

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospectorTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 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.
@@ -140,9 +140,9 @@ public void authenticateWhenInactiveTokenThenInvalidToken() {
140140
new NimbusReactiveOpaqueTokenIntrospector(INTROSPECTION_URL, webClient);
141141

142142
assertThatCode(() -> introspectionClient.introspect("token").block())
143-
.isInstanceOf(OAuth2IntrospectionException.class)
143+
.isInstanceOf(BadOpaqueTokenException.class)
144144
.extracting("message")
145-
.isEqualTo("Provided token [token] isn't active");
145+
.isEqualTo("Provided token isn't active");
146146
}
147147

148148
@Test

0 commit comments

Comments
 (0)