diff --git a/etc/checkstyle/checkstyle-suppressions.xml b/etc/checkstyle/checkstyle-suppressions.xml
index 6f58307877..cd90b3cd04 100644
--- a/etc/checkstyle/checkstyle-suppressions.xml
+++ b/etc/checkstyle/checkstyle-suppressions.xml
@@ -27,6 +27,7 @@
+
diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimAccessor.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimAccessor.java
new file mode 100644
index 0000000000..e253b8b58f
--- /dev/null
+++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimAccessor.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2002-2021 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.core;
+
+import java.net.URL;
+import java.time.Instant;
+import java.util.List;
+
+import org.springframework.lang.Nullable;
+
+/**
+ * A {@link ClaimAccessor} for the "claims" that may be contained in the
+ * Introspection Response.
+ *
+ * @author David Kovac
+ * @since 5.6
+ * @see ClaimAccessor
+ * @see OAuth2TokenIntrospectionClaimNames
+ * @see Introspection Response
+ */
+public interface OAuth2TokenIntrospectionClaimAccessor extends ClaimAccessor {
+
+ /**
+ * Returns the indicator {@code (active)} whether or not the token is currently active
+ * @return the indicator whether or not the token is currently active
+ */
+ default boolean isActive() {
+ return Boolean.TRUE.equals(getClaimAsBoolean(OAuth2TokenIntrospectionClaimNames.ACTIVE));
+ }
+
+ /**
+ * Returns a human-readable identifier {@code (username)} for the resource owner that
+ * authorized the token
+ * @return a human-readable identifier for the resource owner that authorized the
+ * token
+ */
+ @Nullable
+ default String getUsername() {
+ return getClaimAsString(OAuth2TokenIntrospectionClaimNames.USERNAME);
+ }
+
+ /**
+ * Returns the client identifier {@code (client_id)} for the token
+ * @return the client identifier for the token
+ */
+ @Nullable
+ default String getClientId() {
+ return getClaimAsString(OAuth2TokenIntrospectionClaimNames.CLIENT_ID);
+ }
+
+ /**
+ * Returns the scopes {@code (scope)} associated with the token
+ * @return the scopes associated with the token
+ */
+ @Nullable
+ default List getScopes() {
+ return getClaimAsStringList(OAuth2TokenIntrospectionClaimNames.SCOPE);
+ }
+
+ /**
+ * Returns the type of the token {@code (token_type)}, for example {@code bearer}.
+ * @return the type of the token, for example {@code bearer}.
+ */
+ @Nullable
+ default String getTokenType() {
+ return getClaimAsString(OAuth2TokenIntrospectionClaimNames.TOKEN_TYPE);
+ }
+
+ /**
+ * Returns a timestamp {@code (exp)} indicating when the token expires
+ * @return a timestamp indicating when the token expires
+ */
+ @Nullable
+ default Instant getExpiresAt() {
+ return getClaimAsInstant(OAuth2TokenIntrospectionClaimNames.EXP);
+ }
+
+ /**
+ * Returns a timestamp {@code (iat)} indicating when the token was issued
+ * @return a timestamp indicating when the token was issued
+ */
+ @Nullable
+ default Instant getIssuedAt() {
+ return getClaimAsInstant(OAuth2TokenIntrospectionClaimNames.IAT);
+ }
+
+ /**
+ * Returns a timestamp {@code (nbf)} indicating when the token is not to be used
+ * before
+ * @return a timestamp indicating when the token is not to be used before
+ */
+ @Nullable
+ default Instant getNotBefore() {
+ return getClaimAsInstant(OAuth2TokenIntrospectionClaimNames.NBF);
+ }
+
+ /**
+ * Returns usually a machine-readable identifier {@code (sub)} of the resource owner
+ * who authorized the token
+ * @return usually a machine-readable identifier of the resource owner who authorized
+ * the token
+ */
+ @Nullable
+ default String getSubject() {
+ return getClaimAsString(OAuth2TokenIntrospectionClaimNames.SUB);
+ }
+
+ /**
+ * Returns the intended audience {@code (aud)} for the token
+ * @return the intended audience for the token
+ */
+ @Nullable
+ default List getAudience() {
+ return getClaimAsStringList(OAuth2TokenIntrospectionClaimNames.AUD);
+ }
+
+ /**
+ * Returns the issuer {@code (iss)} of the token
+ * @return the issuer of the token
+ */
+ @Nullable
+ default URL getIssuer() {
+ return getClaimAsURL(OAuth2TokenIntrospectionClaimNames.ISS);
+ }
+
+ /**
+ * Returns the identifier {@code (jti)} for the token
+ * @return the identifier for the token
+ */
+ @Nullable
+ default String getId() {
+ return getClaimAsString(OAuth2TokenIntrospectionClaimNames.JTI);
+ }
+
+}
diff --git a/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimNames.java b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimNames.java
new file mode 100644
index 0000000000..ceedbd6420
--- /dev/null
+++ b/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimNames.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2002-2021 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.core;
+
+/**
+ * The names of the "Introspection Claims" defined by an
+ * Introspection
+ * Response.
+ *
+ * @author Josh Cummings
+ * @since 5.6
+ * @see OAuth
+ * 2.0 Token Introspection (RFC7662)
+ * @see OAuth
+ * Parameters (IANA)
+ */
+public interface OAuth2TokenIntrospectionClaimNames {
+
+ /**
+ * {@code active} - Indicator whether or not the token is currently active
+ */
+ String ACTIVE = "active";
+
+ /**
+ * {@code username} - A human-readable identifier for the resource owner that
+ * authorized the token
+ */
+ String USERNAME = "username";
+
+ /**
+ * {@code client_id} - The Client identifier for the token
+ */
+ String CLIENT_ID = "client_id";
+
+ /**
+ * {@code scope} - The scopes for the token
+ */
+ String SCOPE = "scope";
+
+ /**
+ * {@code token_type} - The type of the token, for example {@code bearer}.
+ */
+ String TOKEN_TYPE = "token_type";
+
+ /**
+ * {@code exp} - A timestamp indicating when the token expires
+ */
+ String EXP = "exp";
+
+ /**
+ * {@code iat} - A timestamp indicating when the token was issued
+ */
+ String IAT = "iat";
+
+ /**
+ * {@code nbf} - A timestamp indicating when the token is not to be used before
+ */
+ String NBF = "nbf";
+
+ /**
+ * {@code sub} - Usually a machine-readable identifier of the resource owner who
+ * authorized the token
+ */
+ String SUB = "sub";
+
+ /**
+ * {@code aud} - The intended audience for the token
+ */
+ String AUD = "aud";
+
+ /**
+ * {@code iss} - The issuer of the token
+ */
+ String ISS = "iss";
+
+ /**
+ * {@code jti} - The identifier for the token
+ */
+ String JTI = "jti";
+
+}
diff --git a/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimAccessorTests.java b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimAccessorTests.java
new file mode 100644
index 0000000000..bd0ea50923
--- /dev/null
+++ b/oauth2/oauth2-core/src/test/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimAccessorTests.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2002-2021 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.core;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link OAuth2TokenIntrospectionClaimAccessor}.
+ *
+ * @author David Kovac
+ */
+public class OAuth2TokenIntrospectionClaimAccessorTests {
+
+ private final Map claims = new HashMap<>();
+
+ private final OAuth2TokenIntrospectionClaimAccessor claimAccessor = (() -> this.claims);
+
+ @BeforeEach
+ public void setup() {
+ this.claims.clear();
+ }
+
+ @Test
+ public void isActiveWhenActiveClaimNotExistingThenReturnFalse() {
+ assertThat(this.claimAccessor.isActive()).isFalse();
+ }
+
+ @Test
+ public void isActiveWhenActiveClaimValueIsNullThenReturnFalse() {
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.ACTIVE, null);
+ assertThat(this.claimAccessor.isActive()).isFalse();
+ }
+
+ @Test
+ public void isActiveWhenActiveClaimValueIsTrueThenReturnTrue() {
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.ACTIVE, "true");
+ assertThat(this.claimAccessor.isActive()).isTrue();
+ }
+
+ @Test
+ public void getUsernameWhenUsernameClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getUsername()).isNull();
+ }
+
+ @Test
+ public void getUsernameWhenUsernameClaimExistingThenReturnUsername() {
+ String expectedUsernameValue = "username";
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.USERNAME, expectedUsernameValue);
+ assertThat(this.claimAccessor.getUsername()).isEqualTo(expectedUsernameValue);
+ }
+
+ @Test
+ public void getClientIdWhenClientIdClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getUsername()).isNull();
+ }
+
+ @Test
+ public void getClientIdWhenClientIdClaimExistingThenReturnClientId() {
+ String expectedClientIdValue = "clientId";
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, expectedClientIdValue);
+ assertThat(this.claimAccessor.getClientId()).isEqualTo(expectedClientIdValue);
+ }
+
+ @Test
+ public void getScopesWhenScopeClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getScopes()).isNull();
+ }
+
+ @Test
+ public void getScopesWhenScopeClaimExistingThenReturnScope() {
+ List expectedScopeValue = Arrays.asList("scope1", "scope2");
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.SCOPE, expectedScopeValue);
+ assertThat(this.claimAccessor.getScopes()).hasSameElementsAs(expectedScopeValue);
+ }
+
+ @Test
+ public void getTokenTypeWhenTokenTypeClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getTokenType()).isNull();
+ }
+
+ @Test
+ public void getTokenTypeWhenTokenTypeClaimExistingThenReturnTokenType() {
+ String expectedTokenTypeValue = "tokenType";
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.TOKEN_TYPE, expectedTokenTypeValue);
+ assertThat(this.claimAccessor.getTokenType()).isEqualTo(expectedTokenTypeValue);
+ }
+
+ @Test
+ public void getExpiresAtWhenExpiresAtClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getExpiresAt()).isNull();
+ }
+
+ @Test
+ public void getExpiresAtWhenExpiresAtClaimExistingThenReturnExpiresAt() {
+ Instant expectedExpiresAtValue = Instant.now();
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.EXP, expectedExpiresAtValue);
+ assertThat(this.claimAccessor.getExpiresAt()).isEqualTo(expectedExpiresAtValue);
+ }
+
+ @Test
+ public void getIssuedAtWhenIssuedAtClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getExpiresAt()).isNull();
+ }
+
+ @Test
+ public void getIssuedAtWhenIssuedAtClaimExistingThenReturnIssuedAt() {
+ Instant expectedIssuedAtValue = Instant.now();
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.IAT, expectedIssuedAtValue);
+ assertThat(this.claimAccessor.getIssuedAt()).isEqualTo(expectedIssuedAtValue);
+ }
+
+ @Test
+ public void getNotBeforeWhenNotBeforeClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getNotBefore()).isNull();
+ }
+
+ @Test
+ public void getNotBeforeWhenNotBeforeClaimExistingThenReturnNotBefore() {
+ Instant expectedNotBeforeValue = Instant.now();
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.NBF, expectedNotBeforeValue);
+ assertThat(this.claimAccessor.getNotBefore()).isEqualTo(expectedNotBeforeValue);
+ }
+
+ @Test
+ public void getSubjectWhenSubjectClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getSubject()).isNull();
+ }
+
+ @Test
+ public void getSubjectWhenSubjectClaimExistingThenReturnSubject() {
+ String expectedSubjectValue = "subject";
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.SUB, expectedSubjectValue);
+ assertThat(this.claimAccessor.getSubject()).isEqualTo(expectedSubjectValue);
+ }
+
+ @Test
+ public void getAudienceWhenAudienceClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getAudience()).isNull();
+ }
+
+ @Test
+ public void getAudienceWhenAudienceClaimExistingThenReturnAudience() {
+ List expectedAudienceValue = Arrays.asList("audience1", "audience2");
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.AUD, expectedAudienceValue);
+ assertThat(this.claimAccessor.getAudience()).hasSameElementsAs(expectedAudienceValue);
+ }
+
+ @Test
+ public void getIssuerWhenIssuerClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getIssuer()).isNull();
+ }
+
+ @Test
+ public void getIssuerWhenIssuerClaimExistingThenReturnIssuer() throws MalformedURLException {
+ URL expectedIssuerValue = new URL("https://issuer.com");
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.ISS, expectedIssuerValue);
+ assertThat(this.claimAccessor.getIssuer()).isEqualTo(expectedIssuerValue);
+ }
+
+ @Test
+ public void getIdWhenJtiClaimNotExistingThenReturnNull() {
+ assertThat(this.claimAccessor.getId()).isNull();
+ }
+
+ @Test
+ public void getIdWhenJtiClaimExistingThenReturnId() {
+ String expectedIdValue = "id";
+ this.claims.put(OAuth2TokenIntrospectionClaimNames.JTI, expectedIdValue);
+ assertThat(this.claimAccessor.getId()).isEqualTo(expectedIdValue);
+ }
+
+}
diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java
index d754424531..fec9821e9f 100644
--- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java
+++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenAuthenticationProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -30,10 +30,10 @@ 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.OAuth2AuthenticatedPrincipal;
+import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
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.OAuth2IntrospectionClaimNames;
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
import org.springframework.util.Assert;
@@ -117,8 +117,8 @@ public final class OpaqueTokenAuthenticationProvider implements AuthenticationPr
}
private AbstractAuthenticationToken convert(OAuth2AuthenticatedPrincipal principal, String token) {
- Instant iat = principal.getAttribute(OAuth2IntrospectionClaimNames.ISSUED_AT);
- Instant exp = principal.getAttribute(OAuth2IntrospectionClaimNames.EXPIRES_AT);
+ Instant iat = principal.getAttribute(OAuth2TokenIntrospectionClaimNames.IAT);
+ Instant exp = principal.getAttribute(OAuth2TokenIntrospectionClaimNames.EXP);
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token, iat, exp);
return new BearerTokenAuthentication(principal, accessToken, principal.getAuthorities());
}
diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java
index ad2d848241..d3c62c0dd9 100644
--- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java
+++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/OpaqueTokenReactiveAuthenticationManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -27,10 +27,10 @@ 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.OAuth2TokenIntrospectionClaimNames;
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.OAuth2IntrospectionClaimNames;
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
import org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector;
import org.springframework.util.Assert;
@@ -89,8 +89,8 @@ public class OpaqueTokenReactiveAuthenticationManager implements ReactiveAuthent
// @formatter:off
return this.introspector.introspect(token)
.map((principal) -> {
- Instant iat = principal.getAttribute(OAuth2IntrospectionClaimNames.ISSUED_AT);
- Instant exp = principal.getAttribute(OAuth2IntrospectionClaimNames.EXPIRES_AT);
+ Instant iat = principal.getAttribute(OAuth2TokenIntrospectionClaimNames.IAT);
+ Instant exp = principal.getAttribute(OAuth2TokenIntrospectionClaimNames.EXP);
// construct token
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, token, iat, exp);
return new BearerTokenAuthentication(principal, accessToken, principal.getAuthorities());
diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java
index 51fe7d0df6..830ec77ee5 100644
--- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java
+++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java
@@ -42,6 +42,7 @@ import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
+import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -192,28 +193,28 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
for (Audience audience : response.getAudience()) {
audiences.add(audience.getValue());
}
- claims.put(OAuth2IntrospectionClaimNames.AUDIENCE, Collections.unmodifiableList(audiences));
+ claims.put(OAuth2TokenIntrospectionClaimNames.AUD, Collections.unmodifiableList(audiences));
}
if (response.getClientID() != null) {
- claims.put(OAuth2IntrospectionClaimNames.CLIENT_ID, response.getClientID().getValue());
+ claims.put(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, response.getClientID().getValue());
}
if (response.getExpirationTime() != null) {
Instant exp = response.getExpirationTime().toInstant();
- claims.put(OAuth2IntrospectionClaimNames.EXPIRES_AT, exp);
+ claims.put(OAuth2TokenIntrospectionClaimNames.EXP, exp);
}
if (response.getIssueTime() != null) {
Instant iat = response.getIssueTime().toInstant();
- claims.put(OAuth2IntrospectionClaimNames.ISSUED_AT, iat);
+ claims.put(OAuth2TokenIntrospectionClaimNames.IAT, iat);
}
if (response.getIssuer() != null) {
- claims.put(OAuth2IntrospectionClaimNames.ISSUER, issuer(response.getIssuer().getValue()));
+ claims.put(OAuth2TokenIntrospectionClaimNames.ISS, issuer(response.getIssuer().getValue()));
}
if (response.getNotBeforeTime() != null) {
- claims.put(OAuth2IntrospectionClaimNames.NOT_BEFORE, response.getNotBeforeTime().toInstant());
+ claims.put(OAuth2TokenIntrospectionClaimNames.NBF, response.getNotBeforeTime().toInstant());
}
if (response.getScope() != null) {
List scopes = Collections.unmodifiableList(response.getScope().toStringList());
- claims.put(OAuth2IntrospectionClaimNames.SCOPE, scopes);
+ claims.put(OAuth2TokenIntrospectionClaimNames.SCOPE, scopes);
for (String scope : scopes) {
authorities.add(new SimpleGrantedAuthority(this.authorityPrefix + scope));
}
@@ -227,7 +228,7 @@ public class NimbusOpaqueTokenIntrospector implements OpaqueTokenIntrospector {
}
catch (Exception ex) {
throw new OAuth2IntrospectionException(
- "Invalid " + OAuth2IntrospectionClaimNames.ISSUER + " value: " + uri);
+ "Invalid " + OAuth2TokenIntrospectionClaimNames.ISS + " value: " + uri);
}
}
diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java
index 670f6a3ac5..b562c86308 100644
--- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java
+++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusReactiveOpaqueTokenIntrospector.java
@@ -38,6 +38,7 @@ import org.springframework.http.MediaType;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
+import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
import org.springframework.util.Assert;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientResponse;
@@ -159,28 +160,28 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
for (Audience audience : response.getAudience()) {
audiences.add(audience.getValue());
}
- claims.put(OAuth2IntrospectionClaimNames.AUDIENCE, Collections.unmodifiableList(audiences));
+ claims.put(OAuth2TokenIntrospectionClaimNames.AUD, Collections.unmodifiableList(audiences));
}
if (response.getClientID() != null) {
- claims.put(OAuth2IntrospectionClaimNames.CLIENT_ID, response.getClientID().getValue());
+ claims.put(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, response.getClientID().getValue());
}
if (response.getExpirationTime() != null) {
Instant exp = response.getExpirationTime().toInstant();
- claims.put(OAuth2IntrospectionClaimNames.EXPIRES_AT, exp);
+ claims.put(OAuth2TokenIntrospectionClaimNames.EXP, exp);
}
if (response.getIssueTime() != null) {
Instant iat = response.getIssueTime().toInstant();
- claims.put(OAuth2IntrospectionClaimNames.ISSUED_AT, iat);
+ claims.put(OAuth2TokenIntrospectionClaimNames.IAT, iat);
}
if (response.getIssuer() != null) {
- claims.put(OAuth2IntrospectionClaimNames.ISSUER, issuer(response.getIssuer().getValue()));
+ claims.put(OAuth2TokenIntrospectionClaimNames.ISS, issuer(response.getIssuer().getValue()));
}
if (response.getNotBeforeTime() != null) {
- claims.put(OAuth2IntrospectionClaimNames.NOT_BEFORE, response.getNotBeforeTime().toInstant());
+ claims.put(OAuth2TokenIntrospectionClaimNames.NBF, response.getNotBeforeTime().toInstant());
}
if (response.getScope() != null) {
List scopes = Collections.unmodifiableList(response.getScope().toStringList());
- claims.put(OAuth2IntrospectionClaimNames.SCOPE, scopes);
+ claims.put(OAuth2TokenIntrospectionClaimNames.SCOPE, scopes);
for (String scope : scopes) {
authorities.add(new SimpleGrantedAuthority(this.authorityPrefix + scope));
@@ -195,7 +196,7 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
}
catch (Exception ex) {
throw new OAuth2IntrospectionException(
- "Invalid " + OAuth2IntrospectionClaimNames.ISSUER + " value: " + uri);
+ "Invalid " + OAuth2TokenIntrospectionClaimNames.ISS + " value: " + uri);
}
}
diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimAccessor.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimAccessor.java
index b95109d670..ca04d23849 100644
--- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimAccessor.java
+++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimAccessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -16,16 +16,16 @@
package org.springframework.security.oauth2.server.resource.introspection;
-import java.net.URL;
-import java.time.Instant;
-import java.util.List;
-
+import org.springframework.lang.Nullable;
import org.springframework.security.oauth2.core.ClaimAccessor;
+import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimAccessor;
+import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
/**
* A {@link ClaimAccessor} for the "claims" that may be contained in the
* Introspection Response.
*
+ * @deprecated Use {@link OAuth2TokenIntrospectionClaimAccessor} instead
* @author David Kovac
* @since 5.4
* @see ClaimAccessor
@@ -34,107 +34,17 @@ import org.springframework.security.oauth2.core.ClaimAccessor;
* @see Introspection Response
*/
-public interface OAuth2IntrospectionClaimAccessor extends ClaimAccessor {
-
- /**
- * Returns the indicator {@code (active)} whether or not the token is currently active
- * @return the indicator whether or not the token is currently active
- */
- default boolean isActive() {
- return Boolean.TRUE.equals(this.getClaimAsBoolean(OAuth2IntrospectionClaimNames.ACTIVE));
- }
+@Deprecated
+public interface OAuth2IntrospectionClaimAccessor extends OAuth2TokenIntrospectionClaimAccessor {
/**
* Returns the scopes {@code (scope)} associated with the token
* @return the scopes associated with the token
+ * @deprecated Since 5.6. Use {@link #getScopes()} instead
*/
+ @Nullable
default String getScope() {
- return this.getClaimAsString(OAuth2IntrospectionClaimNames.SCOPE);
- }
-
- /**
- * Returns the client identifier {@code (client_id)} for the token
- * @return the client identifier for the token
- */
- default String getClientId() {
- return this.getClaimAsString(OAuth2IntrospectionClaimNames.CLIENT_ID);
- }
-
- /**
- * Returns a human-readable identifier {@code (username)} for the resource owner that
- * authorized the token
- * @return a human-readable identifier for the resource owner that authorized the
- * token
- */
- default String getUsername() {
- return this.getClaimAsString(OAuth2IntrospectionClaimNames.USERNAME);
- }
-
- /**
- * Returns the type of the token {@code (token_type)}, for example {@code bearer}.
- * @return the type of the token, for example {@code bearer}.
- */
- default String getTokenType() {
- return this.getClaimAsString(OAuth2IntrospectionClaimNames.TOKEN_TYPE);
- }
-
- /**
- * Returns a timestamp {@code (exp)} indicating when the token expires
- * @return a timestamp indicating when the token expires
- */
- default Instant getExpiresAt() {
- return this.getClaimAsInstant(OAuth2IntrospectionClaimNames.EXPIRES_AT);
- }
-
- /**
- * Returns a timestamp {@code (iat)} indicating when the token was issued
- * @return a timestamp indicating when the token was issued
- */
- default Instant getIssuedAt() {
- return this.getClaimAsInstant(OAuth2IntrospectionClaimNames.ISSUED_AT);
- }
-
- /**
- * Returns a timestamp {@code (nbf)} indicating when the token is not to be used
- * before
- * @return a timestamp indicating when the token is not to be used before
- */
- default Instant getNotBefore() {
- return this.getClaimAsInstant(OAuth2IntrospectionClaimNames.NOT_BEFORE);
- }
-
- /**
- * Returns usually a machine-readable identifier {@code (sub)} of the resource owner
- * who authorized the token
- * @return usually a machine-readable identifier of the resource owner who authorized
- * the token
- */
- default String getSubject() {
- return this.getClaimAsString(OAuth2IntrospectionClaimNames.SUBJECT);
- }
-
- /**
- * Returns the intended audience {@code (aud)} for the token
- * @return the intended audience for the token
- */
- default List getAudience() {
- return this.getClaimAsStringList(OAuth2IntrospectionClaimNames.AUDIENCE);
- }
-
- /**
- * Returns the issuer {@code (iss)} of the token
- * @return the issuer of the token
- */
- default URL getIssuer() {
- return this.getClaimAsURL(OAuth2IntrospectionClaimNames.ISSUER);
- }
-
- /**
- * Returns the identifier {@code (jti)} for the token
- * @return the identifier for the token
- */
- default String getId() {
- return this.getClaimAsString(OAuth2IntrospectionClaimNames.JTI);
+ return getClaimAsString(OAuth2TokenIntrospectionClaimNames.SCOPE);
}
}
diff --git a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimNames.java b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimNames.java
index c21e4bb91a..9e5c8227cd 100644
--- a/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimNames.java
+++ b/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/OAuth2IntrospectionClaimNames.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -16,76 +16,55 @@
package org.springframework.security.oauth2.server.resource.introspection;
+import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
+
/**
* The names of the "Introspection Claims" defined by an
* Introspection
* Response.
*
+ * @deprecated Use {@link OAuth2TokenIntrospectionClaimNames} instead
* @author Josh Cummings
* @since 5.2
*/
-public interface OAuth2IntrospectionClaimNames {
-
- /**
- * {@code active} - Indicator whether or not the token is currently active
- */
- String ACTIVE = "active";
-
- /**
- * {@code scope} - The scopes for the token
- */
- String SCOPE = "scope";
-
- /**
- * {@code client_id} - The Client identifier for the token
- */
- String CLIENT_ID = "client_id";
-
- /**
- * {@code username} - A human-readable identifier for the resource owner that
- * authorized the token
- */
- String USERNAME = "username";
-
- /**
- * {@code token_type} - The type of the token, for example {@code bearer}.
- */
- String TOKEN_TYPE = "token_type";
+@Deprecated
+public interface OAuth2IntrospectionClaimNames extends OAuth2TokenIntrospectionClaimNames {
/**
* {@code exp} - A timestamp indicating when the token expires
+ * @deprecated use {@link #EXP} instead
*/
- String EXPIRES_AT = "exp";
+ String EXPIRES_AT = EXP;
/**
* {@code iat} - A timestamp indicating when the token was issued
+ * @deprecated use {@link #IAT} instead
*/
- String ISSUED_AT = "iat";
+ String ISSUED_AT = IAT;
/**
* {@code nbf} - A timestamp indicating when the token is not to be used before
+ * @deprecated use {@link #NBF} instead
*/
- String NOT_BEFORE = "nbf";
+ String NOT_BEFORE = NBF;
/**
* {@code sub} - Usually a machine-readable identifier of the resource owner who
* authorized the token
+ * @deprecated use {@link #SUB} instead
*/
- String SUBJECT = "sub";
+ String SUBJECT = SUB;
/**
* {@code aud} - The intended audience for the token
+ * @deprecated use {@link #AUD} instead
*/
- String AUDIENCE = "aud";
+ String AUDIENCE = AUD;
/**
* {@code iss} - The issuer of the token
+ * @deprecated use {@link #ISS} instead
*/
- String ISSUER = "iss";
-
- /**
- * {@code jti} - The identifier for the token
- */
- String JTI = "jti";
+ String ISSUER = ISS;
}
diff --git a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AuthenticatedPrincipals.java b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AuthenticatedPrincipals.java
index 11cfb3bcc7..2f4558738d 100644
--- a/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AuthenticatedPrincipals.java
+++ b/oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/core/TestOAuth2AuthenticatedPrincipals.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -29,7 +29,6 @@ import java.util.function.Consumer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal;
-import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
/**
* Test values of {@link OAuth2AuthenticatedPrincipal}s
@@ -48,15 +47,15 @@ public final class TestOAuth2AuthenticatedPrincipals {
public static OAuth2AuthenticatedPrincipal active(Consumer