Browse Source

Add BadOpaqueTokenException

Updated NimbusOpaqueTokenIntrospector and
NimbusReactiveOpaqueTokenIntrospector to throw.
Updated OpaqueTokenAuthenticationProvider and
OpaqueTokenReactiveAuthenticationManager to catch.

Fixes gh-7902
Josh Cummings 5 years ago
parent
commit
209c81d65d
10 changed files with 63 additions and 25 deletions
  1. 1 1
      config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurerTests.java
  2. 5 1
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java
  3. 9 3
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java
  4. 34 0
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/BadOpaqueTokenException.java
  5. 2 3
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java
  6. 3 4
      oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java
  7. 2 4
      oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProviderTests.java
  8. 2 4
      oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManagerTests.java
  9. 2 2
      oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospectorTests.java
  10. 3 3
      oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospectorTests.java

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

@@ -1158,7 +1158,7 @@ public class OAuth2ResourceServerConfigurerTests {
 				.with(bearerToken("token")))
 				.andExpect(status().isUnauthorized())
 				.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE,
-						containsString("Provided token [token] isn't active")));
+						containsString("Provided token isn't active")));
 	}
 
 	@Test

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

@@ -20,6 +20,7 @@ import java.util.Collection;
 
 import org.springframework.security.authentication.AbstractAuthenticationToken;
 import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.GrantedAuthority;
@@ -27,6 +28,7 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken;
 import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
 import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
 import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
+import org.springframework.security.oauth2.server.resource.introspection.BadOpaqueTokenException;
 import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
 import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
 import org.springframework.util.Assert;
@@ -88,8 +90,10 @@ public final class OpaqueTokenAuthenticationProvider implements AuthenticationPr
 		OAuth2AuthenticatedPrincipal principal;
 		try {
 			principal = this.introspector.introspect(bearer.getToken());
-		} catch (OAuth2IntrospectionException failed) {
+		} catch (BadOpaqueTokenException failed) {
 			throw new InvalidBearerTokenException(failed.getMessage());
+		} catch (OAuth2IntrospectionException failed) {
+			throw new AuthenticationServiceException(failed.getMessage());
 		}
 
 		AbstractAuthenticationToken result = convert(principal, bearer.getToken());

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

@@ -21,13 +21,15 @@ import java.util.Collection;
 
 import reactor.core.publisher.Mono;
 
+import org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.security.authentication.ReactiveAuthenticationManager;
 import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.oauth2.core.OAuth2AccessToken;
-import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
 import org.springframework.security.oauth2.server.resource.InvalidBearerTokenException;
+import org.springframework.security.oauth2.server.resource.introspection.BadOpaqueTokenException;
 import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
 import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector;
 import org.springframework.util.Assert;
@@ -94,7 +96,11 @@ public class OpaqueTokenReactiveAuthenticationManager implements ReactiveAuthent
 				.onErrorMap(OAuth2IntrospectionException.class, this::onError);
 	}
 
-	private OAuth2AuthenticationException onError(OAuth2IntrospectionException e) {
-		return new InvalidBearerTokenException(e.getMessage(), e);
+	private AuthenticationException onError(OAuth2IntrospectionException e) {
+		if (e instanceof BadOpaqueTokenException) {
+			return new InvalidBearerTokenException(e.getMessage(), e);
+		} else {
+			return new AuthenticationServiceException(e.getMessage(), e);
+		}
 	}
 }

+ 34 - 0
oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/BadOpaqueTokenException.java

@@ -0,0 +1,34 @@
+/*
+ * Copyright 2002-2020 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.oauth2.server.resource.introspection;
+
+/**
+ * An exception similar to {@link org.springframework.security.authentication.BadCredentialsException}
+ * that indicates an opaque token that is invalid in some way.
+ *
+ * @author Josh Cummings
+ * @since 5.3
+ */
+public class BadOpaqueTokenException extends OAuth2IntrospectionException {
+	public BadOpaqueTokenException(String message) {
+		super(message);
+	}
+
+	public BadOpaqueTokenException(String message, Throwable cause) {
+		super(message, cause);
+	}
+}

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

@@ -24,7 +24,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.ArrayList;
 
 import com.nimbusds.oauth2.sdk.TokenIntrospectionResponse;
 import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
@@ -133,7 +132,7 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
 	public OAuth2AuthenticatedPrincipal introspect(String token) {
 		RequestEntity<?> requestEntity = this.requestEntityConverter.convert(token);
 		if (requestEntity == null) {
-			throw new OAuth2IntrospectionException("Provided token [" + token + "] isn't active");
+			throw new OAuth2IntrospectionException("requestEntityConverter returned a null entity");
 		}
 
 		ResponseEntity<String> responseEntity = makeRequest(requestEntity);
@@ -143,7 +142,7 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
 
 		// relying solely on the authorization server to validate this token (not checking 'exp', for example)
 		if (!introspectionSuccessResponse.isActive()) {
-			throw new OAuth2IntrospectionException("Provided token [" + token + "] isn't active");
+			throw new BadOpaqueTokenException("Provided token isn't active");
 		}
 
 		return convertClaimsSet(introspectionSuccessResponse);

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

@@ -24,16 +24,15 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.ArrayList;
 
 import com.nimbusds.oauth2.sdk.TokenIntrospectionResponse;
 import com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse;
 import com.nimbusds.oauth2.sdk.http.HTTPResponse;
 import com.nimbusds.oauth2.sdk.id.Audience;
-import org.springframework.core.io.buffer.DataBuffer;
-import org.springframework.core.io.buffer.DataBufferUtils;
 import reactor.core.publisher.Mono;
 
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.security.core.GrantedAuthority;
@@ -154,7 +153,7 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
 	private void validate(String token, TokenIntrospectionSuccessResponse response) {
 		// relying solely on the authorization server to validate this token (not checking 'exp', for example)
 		if (!response.isActive()) {
-			throw new OAuth2IntrospectionException("Provided token [" + token + "] isn't active");
+			throw new BadOpaqueTokenException("Provided token isn't active");
 		}
 	}
 

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

@@ -23,10 +23,10 @@ import java.util.Map;
 
 import org.junit.Test;
 
+import org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal;
 import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
-import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
 import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
 import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
@@ -109,9 +109,7 @@ public class OpaqueTokenAuthenticationProviderTests {
 		OpaqueTokenAuthenticationProvider provider = new OpaqueTokenAuthenticationProvider(introspector);
 
 		assertThatCode(() -> provider.authenticate(new BearerTokenAuthenticationToken("token")))
-				.isInstanceOf(OAuth2AuthenticationException.class)
-				.extracting("error.description")
-				.isEqualTo("Invalid token");
+				.isInstanceOf(AuthenticationServiceException.class);
 	}
 
 	@Test

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

@@ -25,10 +25,10 @@ import java.util.Map;
 import org.junit.Test;
 import reactor.core.publisher.Mono;
 
+import org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal;
 import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
-import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
 import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
 import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
 import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
@@ -115,9 +115,7 @@ public class OpaqueTokenReactiveAuthenticationManagerTests {
 				new OpaqueTokenReactiveAuthenticationManager(introspector);
 
 		assertThatCode(() -> provider.authenticate(new BearerTokenAuthenticationToken("token")).block())
-				.isInstanceOf(OAuth2AuthenticationException.class)
-				.extracting("error.description")
-				.isEqualTo("Invalid token");
+				.isInstanceOf(AuthenticationServiceException.class);
 	}
 
 	@Test

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

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -168,7 +168,7 @@ public class NimbusOpaqueTokenIntrospectorTests {
 		assertThatCode(() -> introspectionClient.introspect("token"))
 				.isInstanceOf(OAuth2IntrospectionException.class)
 				.extracting("message")
-				.isEqualTo("Provided token [token] isn't active");
+				.isEqualTo("Provided token isn't active");
 	}
 
 	@Test

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

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -140,9 +140,9 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests {
 				new NimbusReactiveOpaqueTokenIntrospector(INTROSPECTION_URL, webClient);
 
 		assertThatCode(() -> introspectionClient.introspect("token").block())
-				.isInstanceOf(OAuth2IntrospectionException.class)
+				.isInstanceOf(BadOpaqueTokenException.class)
 				.extracting("message")
-				.isEqualTo("Provided token [token] isn't active");
+				.isEqualTo("Provided token isn't active");
 	}
 
 	@Test