Replace usages of deprecated OAuth2IntrospectionClaimNames

Replace all usages of OAuth2IntrospectionClaimNames with
the suggested OAuth2TokenIntrospectionClaimNames.

There does not appear to be any further usages of OAuth2IntrospectionClaimNames,
so it should be suitable for removal when appropriate in accordance with the
deprecation policy.
This commit is contained in:
Ashley Scopes 2021-08-15 15:42:15 +01:00 committed by Josh Cummings
parent 7ccc915b2b
commit 171522ebf2
3 changed files with 30 additions and 25 deletions

View File

@ -121,7 +121,7 @@ public class NimbusReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
MediaType contentType = responseEntity.headers().contentType().orElseThrow(() -> { MediaType contentType = responseEntity.headers().contentType().orElseThrow(() -> {
this.logger.trace("Did not receive Content-Type from introspection endpoint in response"); this.logger.trace("Did not receive Content-Type from introspection endpoint in response");
throw new OAuth2IntrospectionException( return new OAuth2IntrospectionException(
"Introspection endpoint response was invalid, as no Content-Type header was provided"); "Introspection endpoint response was invalid, as no Content-Type header was provided");
}); });

View File

@ -35,6 +35,7 @@ import org.springframework.http.MediaType;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ClientResponse;
@ -122,7 +123,7 @@ public class SpringReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
// relying solely on the authorization server to validate this token (not checking // relying solely on the authorization server to validate this token (not checking
// 'exp', for example) // 'exp', for example)
return responseEntity.bodyToMono(STRING_OBJECT_MAP) return responseEntity.bodyToMono(STRING_OBJECT_MAP)
.filter((body) -> (boolean) body.compute(OAuth2IntrospectionClaimNames.ACTIVE, (k, v) -> { .filter((body) -> (boolean) body.compute(OAuth2TokenIntrospectionClaimNames.ACTIVE, (k, v) -> {
if (v instanceof String) { if (v instanceof String) {
return Boolean.parseBoolean((String) v); return Boolean.parseBoolean((String) v);
} }
@ -134,16 +135,16 @@ public class SpringReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
} }
private OAuth2AuthenticatedPrincipal convertClaimsSet(Map<String, Object> claims) { private OAuth2AuthenticatedPrincipal convertClaimsSet(Map<String, Object> claims) {
claims.computeIfPresent(OAuth2IntrospectionClaimNames.AUDIENCE, (k, v) -> { claims.computeIfPresent(OAuth2TokenIntrospectionClaimNames.AUD, (k, v) -> {
if (v instanceof String) { if (v instanceof String) {
return Collections.singletonList(v); return Collections.singletonList(v);
} }
return v; return v;
}); });
claims.computeIfPresent(OAuth2IntrospectionClaimNames.CLIENT_ID, (k, v) -> v.toString()); claims.computeIfPresent(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, (k, v) -> v.toString());
claims.computeIfPresent(OAuth2IntrospectionClaimNames.EXPIRES_AT, claims.computeIfPresent(OAuth2TokenIntrospectionClaimNames.EXP,
(k, v) -> Instant.ofEpochSecond(((Number) v).longValue())); (k, v) -> Instant.ofEpochSecond(((Number) v).longValue()));
claims.computeIfPresent(OAuth2IntrospectionClaimNames.ISSUED_AT, claims.computeIfPresent(OAuth2TokenIntrospectionClaimNames.IAT,
(k, v) -> Instant.ofEpochSecond(((Number) v).longValue())); (k, v) -> Instant.ofEpochSecond(((Number) v).longValue()));
// RFC-7662 page 7 directs users to RFC-7519 for defining the values of these // RFC-7662 page 7 directs users to RFC-7519 for defining the values of these
// issuer fields. // issuer fields.
@ -163,11 +164,11 @@ public class SpringReactiveOpaqueTokenIntrospector implements ReactiveOpaqueToke
// may be awkward to debug, we do not want to manipulate this value. Previous // may be awkward to debug, we do not want to manipulate this value. Previous
// versions of Spring Security // versions of Spring Security
// would *only* allow valid URLs, which is not what we wish to achieve here. // would *only* allow valid URLs, which is not what we wish to achieve here.
claims.computeIfPresent(OAuth2IntrospectionClaimNames.ISSUER, (k, v) -> v.toString()); claims.computeIfPresent(OAuth2TokenIntrospectionClaimNames.ISS, (k, v) -> v.toString());
claims.computeIfPresent(OAuth2IntrospectionClaimNames.NOT_BEFORE, claims.computeIfPresent(OAuth2TokenIntrospectionClaimNames.NBF,
(k, v) -> Instant.ofEpochSecond(((Number) v).longValue())); (k, v) -> Instant.ofEpochSecond(((Number) v).longValue()));
Collection<GrantedAuthority> authorities = new ArrayList<>(); Collection<GrantedAuthority> authorities = new ArrayList<>();
claims.computeIfPresent(OAuth2IntrospectionClaimNames.SCOPE, (k, v) -> { claims.computeIfPresent(OAuth2TokenIntrospectionClaimNames.SCOPE, (k, v) -> {
if (v instanceof String) { if (v instanceof String) {
Collection<String> scopes = Arrays.asList(((String) v).split(" ")); Collection<String> scopes = Arrays.asList(((String) v).split(" "));
for (String scope : scopes) { for (String scope : scopes) {

View File

@ -37,6 +37,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
@ -106,18 +107,19 @@ public class SpringReactiveOpaqueTokenIntrospectorTests {
SpringReactiveOpaqueTokenIntrospector introspectionClient = new SpringReactiveOpaqueTokenIntrospector( SpringReactiveOpaqueTokenIntrospector introspectionClient = new SpringReactiveOpaqueTokenIntrospector(
introspectUri, CLIENT_ID, CLIENT_SECRET); introspectUri, CLIENT_ID, CLIENT_SECRET);
OAuth2AuthenticatedPrincipal authority = introspectionClient.introspect("token").block(); OAuth2AuthenticatedPrincipal authority = introspectionClient.introspect("token").block();
assertThat(authority).isNotNull();
// @formatter:off // @formatter:off
assertThat(authority.getAttributes()) assertThat(authority.getAttributes())
.isNotNull() .isNotNull()
.containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) .containsEntry(OAuth2TokenIntrospectionClaimNames.ACTIVE, true)
.containsEntry(OAuth2IntrospectionClaimNames.AUDIENCE, .containsEntry(OAuth2TokenIntrospectionClaimNames.AUD,
Arrays.asList("https://protected.example.net/resource")) Arrays.asList("https://protected.example.net/resource"))
.containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4") .containsEntry(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
.containsEntry(OAuth2IntrospectionClaimNames.EXPIRES_AT, Instant.ofEpochSecond(1419356238)) .containsEntry(OAuth2TokenIntrospectionClaimNames.EXP, Instant.ofEpochSecond(1419356238))
.containsEntry(OAuth2IntrospectionClaimNames.ISSUER, "https://server.example.com/") .containsEntry(OAuth2TokenIntrospectionClaimNames.ISS, "https://server.example.com/")
.containsEntry(OAuth2IntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin")) .containsEntry(OAuth2TokenIntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
.containsEntry(OAuth2IntrospectionClaimNames.SUBJECT, "Z5O3upPC88QrAjx00dis") .containsEntry(OAuth2TokenIntrospectionClaimNames.SUB, "Z5O3upPC88QrAjx00dis")
.containsEntry(OAuth2IntrospectionClaimNames.USERNAME, "jdoe") .containsEntry(OAuth2TokenIntrospectionClaimNames.USERNAME, "jdoe")
.containsEntry("extension_field", "twenty-seven"); .containsEntry("extension_field", "twenty-seven");
// @formatter:on // @formatter:on
} }
@ -149,21 +151,22 @@ public class SpringReactiveOpaqueTokenIntrospectorTests {
@Test @Test
public void authenticateWhenActiveTokenThenParsesValuesInResponse() { public void authenticateWhenActiveTokenThenParsesValuesInResponse() {
Map<String, Object> introspectedValues = new HashMap<>(); Map<String, Object> introspectedValues = new HashMap<>();
introspectedValues.put(OAuth2IntrospectionClaimNames.ACTIVE, true); introspectedValues.put(OAuth2TokenIntrospectionClaimNames.ACTIVE, true);
introspectedValues.put(OAuth2IntrospectionClaimNames.AUDIENCE, Arrays.asList("aud")); introspectedValues.put(OAuth2TokenIntrospectionClaimNames.AUD, Arrays.asList("aud"));
introspectedValues.put(OAuth2IntrospectionClaimNames.NOT_BEFORE, 29348723984L); introspectedValues.put(OAuth2TokenIntrospectionClaimNames.NBF, 29348723984L);
WebClient webClient = mockResponse(introspectedValues); WebClient webClient = mockResponse(introspectedValues);
SpringReactiveOpaqueTokenIntrospector introspectionClient = new SpringReactiveOpaqueTokenIntrospector( SpringReactiveOpaqueTokenIntrospector introspectionClient = new SpringReactiveOpaqueTokenIntrospector(
INTROSPECTION_URL, webClient); INTROSPECTION_URL, webClient);
OAuth2AuthenticatedPrincipal authority = introspectionClient.introspect("token").block(); OAuth2AuthenticatedPrincipal authority = introspectionClient.introspect("token").block();
assertThat(authority).isNotNull();
// @formatter:off // @formatter:off
assertThat(authority.getAttributes()) assertThat(authority.getAttributes())
.isNotNull() .isNotNull()
.containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true) .containsEntry(OAuth2TokenIntrospectionClaimNames.ACTIVE, true)
.containsEntry(OAuth2IntrospectionClaimNames.AUDIENCE, Arrays.asList("aud")) .containsEntry(OAuth2TokenIntrospectionClaimNames.AUD, Arrays.asList("aud"))
.containsEntry(OAuth2IntrospectionClaimNames.NOT_BEFORE, Instant.ofEpochSecond(29348723984L)) .containsEntry(OAuth2TokenIntrospectionClaimNames.NBF, Instant.ofEpochSecond(29348723984L))
.doesNotContainKey(OAuth2IntrospectionClaimNames.CLIENT_ID) .doesNotContainKey(OAuth2TokenIntrospectionClaimNames.CLIENT_ID)
.doesNotContainKey(OAuth2IntrospectionClaimNames.SCOPE); .doesNotContainKey(OAuth2TokenIntrospectionClaimNames.SCOPE);
// @formatter:on // @formatter:on
} }
@ -234,6 +237,7 @@ public class SpringReactiveOpaqueTokenIntrospectorTests {
return webClient; return webClient;
} }
@SuppressWarnings("unchecked")
private Map<String, Object> toMap(String string) { private Map<String, Object> toMap(String string) {
try { try {
return this.mapper.readValue(string, Map.class); return this.mapper.readValue(string, Map.class);