Move and rename OAuth2IntrospectionClaimAccessor/Names
Introduced OAuth2TokenIntrospectionClaimAccessor and OAuth2TokenIntrospectionClaimNames with copied implementation from OAuth2IntrospectionClaimAccessor/Names. OAuth2IntrospectionClaimAccessor and OAuth2IntrospectionClaimNames are now deprecated. Also method getScopes() returning list of scopes was introduced and getScope() is now deprecated. Closes gh-9647
This commit is contained in:
parent
b83a4c2985
commit
3ff825576b
|
@ -27,6 +27,7 @@
|
|||
<suppress files="OidcParameterNames\.java" checks="InterfaceIsType"/>
|
||||
<suppress files="BearerTokenErrorCodes\.java" checks="InterfaceIsType"/>
|
||||
<suppress files="OAuth2IntrospectionClaimNames\.java" checks="InterfaceIsType"/>
|
||||
<suppress files="OAuth2TokenIntrospectionClaimNames\.java" checks="InterfaceIsType"/>
|
||||
<suppress files="Saml2ErrorCodes\.java" checks="InterfaceIsType"/>
|
||||
|
||||
<!-- Method Visibility that we can't reduce -->
|
||||
|
|
|
@ -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 <a target="_blank" href=
|
||||
* "https://tools.ietf.org/html/rfc7662#section-2.2">Introspection Response</a>
|
||||
*/
|
||||
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<String> 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<String> 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
* <a target="_blank" href="https://tools.ietf.org/html/rfc7662#section-2.2">Introspection
|
||||
* Response</a>.
|
||||
*
|
||||
* @author Josh Cummings
|
||||
* @since 5.6
|
||||
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7662#section-2.2">OAuth
|
||||
* 2.0 Token Introspection (RFC7662)</a>
|
||||
* @see <a target="_blank" href=
|
||||
* "https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-introspection-response">OAuth
|
||||
* Parameters (IANA)</a>
|
||||
*/
|
||||
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";
|
||||
|
||||
}
|
|
@ -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<String, Object> 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<String> 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<String> 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <a target="_blank" href=
|
||||
* "https://tools.ietf.org/html/rfc7662#section-2.2">Introspection Response</a>
|
||||
*/
|
||||
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<String> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* <a target="_blank" href="https://tools.ietf.org/html/rfc7662#section-2.2">Introspection
|
||||
* Response</a>.
|
||||
*
|
||||
* @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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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<Map<String, Object>> attributesConsumer) {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2IntrospectionClaimNames.ACTIVE, true);
|
||||
attributes.put(OAuth2IntrospectionClaimNames.AUDIENCE, Arrays.asList("https://protected.example.net/resource"));
|
||||
attributes.put(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4");
|
||||
attributes.put(OAuth2IntrospectionClaimNames.EXPIRES_AT, Instant.ofEpochSecond(1419356238));
|
||||
attributes.put(OAuth2IntrospectionClaimNames.NOT_BEFORE, Instant.ofEpochSecond(29348723984L));
|
||||
attributes.put(OAuth2IntrospectionClaimNames.ISSUER, url("https://server.example.com/"));
|
||||
attributes.put(OAuth2IntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"));
|
||||
attributes.put(OAuth2IntrospectionClaimNames.SUBJECT, "Z5O3upPC88QrAjx00dis");
|
||||
attributes.put(OAuth2IntrospectionClaimNames.USERNAME, "jdoe");
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.ACTIVE, true);
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.AUD, Arrays.asList("https://protected.example.net/resource"));
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4");
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.EXP, Instant.ofEpochSecond(1419356238));
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.NBF, Instant.ofEpochSecond(29348723984L));
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.ISS, url("https://server.example.com/"));
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"));
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.SUB, "Z5O3upPC88QrAjx00dis");
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.USERNAME, "jdoe");
|
||||
attributesConsumer.accept(attributes);
|
||||
Collection<GrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority("SCOPE_read"),
|
||||
new SimpleGrantedAuthority("SCOPE_write"), new SimpleGrantedAuthority("SCOPE_dolphin"));
|
||||
|
|
|
@ -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.
|
||||
|
@ -33,7 +33,7 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
|||
import org.springframework.security.oauth2.core.DefaultOAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
@ -58,9 +58,9 @@ public class BearerTokenAuthenticationTests {
|
|||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
this.attributesMap.put(OAuth2IntrospectionClaimNames.SUBJECT, this.name);
|
||||
this.attributesMap.put(OAuth2IntrospectionClaimNames.CLIENT_ID, "client_id");
|
||||
this.attributesMap.put(OAuth2IntrospectionClaimNames.USERNAME, "username");
|
||||
this.attributesMap.put(OAuth2TokenIntrospectionClaimNames.SUB, this.name);
|
||||
this.attributesMap.put(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, "client_id");
|
||||
this.attributesMap.put(OAuth2TokenIntrospectionClaimNames.USERNAME, "username");
|
||||
this.principal = new DefaultOAuth2AuthenticatedPrincipal(this.attributesMap, null);
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ public class BearerTokenAuthenticationTests {
|
|||
BearerTokenAuthentication authenticated = new BearerTokenAuthentication(this.principal, this.token, null);
|
||||
// @formatter:off
|
||||
assertThat(authenticated.getName())
|
||||
.isEqualTo(this.principal.getAttribute(OAuth2IntrospectionClaimNames.SUBJECT));
|
||||
.isEqualTo(this.principal.getAttribute(OAuth2TokenIntrospectionClaimNames.SUB));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
|
|
@ -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.junit.jupiter.api.Test;
|
|||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AuthenticatedPrincipals;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal;
|
||||
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;
|
||||
|
||||
|
@ -61,16 +61,16 @@ public class OpaqueTokenAuthenticationProviderTests {
|
|||
// @formatter:off
|
||||
assertThat(attributes)
|
||||
.isNotNull()
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.AUDIENCE,
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.AUD,
|
||||
Arrays.asList("https://protected.example.net/resource"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.EXPIRES_AT, Instant.ofEpochSecond(1419356238))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ISSUER, new URL("https://server.example.com/"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.NOT_BEFORE, Instant.ofEpochSecond(29348723984L))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.SUBJECT, "Z5O3upPC88QrAjx00dis")
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.USERNAME, "jdoe")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.EXP, Instant.ofEpochSecond(1419356238))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ISS, new URL("https://server.example.com/"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.NBF, Instant.ofEpochSecond(29348723984L))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.SUB, "Z5O3upPC88QrAjx00dis")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.USERNAME, "jdoe")
|
||||
.containsEntry("extension_field", "twenty-seven");
|
||||
assertThat(result.getAuthorities())
|
||||
.extracting("authority")
|
||||
|
@ -92,7 +92,7 @@ public class OpaqueTokenAuthenticationProviderTests {
|
|||
// @formatter:off
|
||||
assertThat(attributes)
|
||||
.isNotNull()
|
||||
.doesNotContainKey(OAuth2IntrospectionClaimNames.SCOPE);
|
||||
.doesNotContainKey(OAuth2TokenIntrospectionClaimNames.SCOPE);
|
||||
// @formatter:on
|
||||
assertThat(result.getAuthorities()).isEmpty();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -28,10 +28,10 @@ import reactor.core.publisher.Mono;
|
|||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AuthenticatedPrincipals;
|
||||
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal;
|
||||
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;
|
||||
|
||||
|
@ -62,16 +62,16 @@ public class OpaqueTokenReactiveAuthenticationManagerTests {
|
|||
// @formatter:off
|
||||
assertThat(attributes)
|
||||
.isNotNull()
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.AUDIENCE,
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.AUD,
|
||||
Arrays.asList("https://protected.example.net/resource"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.EXPIRES_AT, Instant.ofEpochSecond(1419356238))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ISSUER, new URL("https://server.example.com/"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.NOT_BEFORE, Instant.ofEpochSecond(29348723984L))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.SUBJECT, "Z5O3upPC88QrAjx00dis")
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.USERNAME, "jdoe")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.EXP, Instant.ofEpochSecond(1419356238))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ISS, new URL("https://server.example.com/"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.NBF, Instant.ofEpochSecond(29348723984L))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.SUB, "Z5O3upPC88QrAjx00dis")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.USERNAME, "jdoe")
|
||||
.containsEntry("extension_field", "twenty-seven");
|
||||
assertThat(result.getAuthorities())
|
||||
.extracting("authority")
|
||||
|
@ -90,7 +90,7 @@ public class OpaqueTokenReactiveAuthenticationManagerTests {
|
|||
Authentication result = provider.authenticate(new BearerTokenAuthenticationToken("token")).block();
|
||||
assertThat(result.getPrincipal()).isInstanceOf(OAuth2IntrospectionAuthenticatedPrincipal.class);
|
||||
Map<String, Object> attributes = ((OAuth2AuthenticatedPrincipal) result.getPrincipal()).getAttributes();
|
||||
assertThat(attributes).isNotNull().doesNotContainKey(OAuth2IntrospectionClaimNames.SCOPE);
|
||||
assertThat(attributes).isNotNull().doesNotContainKey(OAuth2TokenIntrospectionClaimNames.SCOPE);
|
||||
assertThat(result.getAuthorities()).isEmpty();
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -40,6 +40,7 @@ import org.springframework.http.MediaType;
|
|||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -140,15 +141,15 @@ public class NimbusOpaqueTokenIntrospectorTests {
|
|||
// @formatter:off
|
||||
assertThat(authority.getAttributes())
|
||||
.isNotNull()
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.AUDIENCE,
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.AUD,
|
||||
Arrays.asList("https://protected.example.net/resource"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.EXPIRES_AT, Instant.ofEpochSecond(1419356238))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ISSUER, new URL("https://server.example.com/"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.SUBJECT, "Z5O3upPC88QrAjx00dis")
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.USERNAME, "jdoe")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.EXP, Instant.ofEpochSecond(1419356238))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ISS, new URL("https://server.example.com/"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.SUB, "Z5O3upPC88QrAjx00dis")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.USERNAME, "jdoe")
|
||||
.containsEntry("extension_field", "twenty-seven");
|
||||
// @formatter:on
|
||||
}
|
||||
|
@ -182,9 +183,9 @@ public class NimbusOpaqueTokenIntrospectorTests {
|
|||
@Test
|
||||
public void introspectWhenActiveTokenThenParsesValuesInResponse() {
|
||||
Map<String, Object> introspectedValues = new HashMap<>();
|
||||
introspectedValues.put(OAuth2IntrospectionClaimNames.ACTIVE, true);
|
||||
introspectedValues.put(OAuth2IntrospectionClaimNames.AUDIENCE, Arrays.asList("aud"));
|
||||
introspectedValues.put(OAuth2IntrospectionClaimNames.NOT_BEFORE, 29348723984L);
|
||||
introspectedValues.put(OAuth2TokenIntrospectionClaimNames.ACTIVE, true);
|
||||
introspectedValues.put(OAuth2TokenIntrospectionClaimNames.AUD, Arrays.asList("aud"));
|
||||
introspectedValues.put(OAuth2TokenIntrospectionClaimNames.NBF, 29348723984L);
|
||||
RestOperations restOperations = mock(RestOperations.class);
|
||||
OpaqueTokenIntrospector introspectionClient = new NimbusOpaqueTokenIntrospector(INTROSPECTION_URL,
|
||||
restOperations);
|
||||
|
@ -194,11 +195,11 @@ public class NimbusOpaqueTokenIntrospectorTests {
|
|||
// @formatter:off
|
||||
assertThat(authority.getAttributes())
|
||||
.isNotNull()
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.AUDIENCE, Arrays.asList("aud"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.NOT_BEFORE, Instant.ofEpochSecond(29348723984L))
|
||||
.doesNotContainKey(OAuth2IntrospectionClaimNames.CLIENT_ID)
|
||||
.doesNotContainKey(OAuth2IntrospectionClaimNames.SCOPE);
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.AUD, Arrays.asList("aud"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.NBF, Instant.ofEpochSecond(29348723984L))
|
||||
.doesNotContainKey(OAuth2TokenIntrospectionClaimNames.CLIENT_ID)
|
||||
.doesNotContainKey(OAuth2TokenIntrospectionClaimNames.SCOPE);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.springframework.http.HttpHeaders;
|
|||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
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.WebClient;
|
||||
|
||||
|
@ -111,15 +112,15 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests {
|
|||
// @formatter:off
|
||||
assertThat(authority.getAttributes())
|
||||
.isNotNull()
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.AUDIENCE,
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.AUD,
|
||||
Arrays.asList("https://protected.example.net/resource"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.EXPIRES_AT, Instant.ofEpochSecond(1419356238))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ISSUER, new URL("https://server.example.com/"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.SUBJECT, "Z5O3upPC88QrAjx00dis")
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.USERNAME, "jdoe")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.CLIENT_ID, "l238j323ds-23ij4")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.EXP, Instant.ofEpochSecond(1419356238))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ISS, new URL("https://server.example.com/"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.SCOPE, Arrays.asList("read", "write", "dolphin"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.SUB, "Z5O3upPC88QrAjx00dis")
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.USERNAME, "jdoe")
|
||||
.containsEntry("extension_field", "twenty-seven");
|
||||
// @formatter:on
|
||||
}
|
||||
|
@ -151,9 +152,9 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests {
|
|||
@Test
|
||||
public void authenticateWhenActiveTokenThenParsesValuesInResponse() {
|
||||
Map<String, Object> introspectedValues = new HashMap<>();
|
||||
introspectedValues.put(OAuth2IntrospectionClaimNames.ACTIVE, true);
|
||||
introspectedValues.put(OAuth2IntrospectionClaimNames.AUDIENCE, Arrays.asList("aud"));
|
||||
introspectedValues.put(OAuth2IntrospectionClaimNames.NOT_BEFORE, 29348723984L);
|
||||
introspectedValues.put(OAuth2TokenIntrospectionClaimNames.ACTIVE, true);
|
||||
introspectedValues.put(OAuth2TokenIntrospectionClaimNames.AUD, Arrays.asList("aud"));
|
||||
introspectedValues.put(OAuth2TokenIntrospectionClaimNames.NBF, 29348723984L);
|
||||
WebClient webClient = mockResponse(new JSONObject(introspectedValues).toJSONString());
|
||||
NimbusReactiveOpaqueTokenIntrospector introspectionClient = new NimbusReactiveOpaqueTokenIntrospector(
|
||||
INTROSPECTION_URL, webClient);
|
||||
|
@ -161,11 +162,11 @@ public class NimbusReactiveOpaqueTokenIntrospectorTests {
|
|||
// @formatter:off
|
||||
assertThat(authority.getAttributes())
|
||||
.isNotNull()
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.AUDIENCE, Arrays.asList("aud"))
|
||||
.containsEntry(OAuth2IntrospectionClaimNames.NOT_BEFORE, Instant.ofEpochSecond(29348723984L))
|
||||
.doesNotContainKey(OAuth2IntrospectionClaimNames.CLIENT_ID)
|
||||
.doesNotContainKey(OAuth2IntrospectionClaimNames.SCOPE);
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.ACTIVE, true)
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.AUD, Arrays.asList("aud"))
|
||||
.containsEntry(OAuth2TokenIntrospectionClaimNames.NBF, Instant.ofEpochSecond(29348723984L))
|
||||
.doesNotContainKey(OAuth2TokenIntrospectionClaimNames.CLIENT_ID)
|
||||
.doesNotContainKey(OAuth2TokenIntrospectionClaimNames.SCOPE);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.springframework.security.oauth2.client.web.server.WebSessionServerOAu
|
|||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
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.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
|
@ -71,7 +72,6 @@ import org.springframework.security.oauth2.server.resource.authentication.Bearer
|
|||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
|
||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
|
||||
import org.springframework.security.web.server.csrf.CsrfWebFilter;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
|
||||
|
@ -648,14 +648,14 @@ public final class SecurityMockServerConfigurers {
|
|||
|
||||
private Map<String, Object> defaultAttributes() {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2IntrospectionClaimNames.SUBJECT, "user");
|
||||
attributes.put(OAuth2IntrospectionClaimNames.SCOPE, "read");
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.SUB, "user");
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.SCOPE, "read");
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private Collection<GrantedAuthority> defaultAuthorities() {
|
||||
Map<String, Object> attributes = this.attributes.get();
|
||||
Object scope = attributes.get(OAuth2IntrospectionClaimNames.SCOPE);
|
||||
Object scope = attributes.get(OAuth2TokenIntrospectionClaimNames.SCOPE);
|
||||
if (scope == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -70,6 +70,7 @@ import org.springframework.security.oauth2.client.web.method.annotation.OAuth2Au
|
|||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
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.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
|
||||
|
@ -85,7 +86,6 @@ import org.springframework.security.oauth2.server.resource.authentication.Bearer
|
|||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionAuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
|
||||
import org.springframework.security.test.context.TestSecurityContextHolder;
|
||||
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
|
||||
import org.springframework.security.test.web.support.WebTestUtils;
|
||||
|
@ -1191,14 +1191,14 @@ public final class SecurityMockMvcRequestPostProcessors {
|
|||
|
||||
private Map<String, Object> defaultAttributes() {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put(OAuth2IntrospectionClaimNames.SUBJECT, "user");
|
||||
attributes.put(OAuth2IntrospectionClaimNames.SCOPE, "read");
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.SUB, "user");
|
||||
attributes.put(OAuth2TokenIntrospectionClaimNames.SCOPE, "read");
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private Collection<GrantedAuthority> defaultAuthorities() {
|
||||
Map<String, Object> attributes = this.attributes.get();
|
||||
Object scope = attributes.get(OAuth2IntrospectionClaimNames.SCOPE);
|
||||
Object scope = attributes.get(OAuth2TokenIntrospectionClaimNames.SCOPE);
|
||||
if (scope == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -29,9 +29,9 @@ import org.springframework.security.core.GrantedAuthority;
|
|||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames;
|
||||
import org.springframework.security.oauth2.core.TestOAuth2AuthenticatedPrincipals;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames;
|
||||
import org.springframework.security.web.reactive.result.method.annotation.CurrentSecurityContextArgumentResolver;
|
||||
import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
@ -64,7 +64,7 @@ public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockSe
|
|||
BearerTokenAuthentication token = (BearerTokenAuthentication) context.getAuthentication();
|
||||
assertThat(token.getAuthorities()).isNotEmpty();
|
||||
assertThat(token.getToken()).isNotNull();
|
||||
assertThat(token.getTokenAttributes().get(OAuth2IntrospectionClaimNames.SUBJECT)).isEqualTo("user");
|
||||
assertThat(token.getTokenAttributes().get(OAuth2TokenIntrospectionClaimNames.SUB)).isEqualTo("user");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -83,12 +83,12 @@ public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockSe
|
|||
String sub = new String("my-subject");
|
||||
this.client
|
||||
.mutateWith(SecurityMockServerConfigurers.mockOpaqueToken()
|
||||
.attributes((attributes) -> attributes.put(OAuth2IntrospectionClaimNames.SUBJECT, sub)))
|
||||
.attributes((attributes) -> attributes.put(OAuth2TokenIntrospectionClaimNames.SUB, sub)))
|
||||
.get().exchange().expectStatus().isOk();
|
||||
SecurityContext context = this.securityContextController.removeSecurityContext();
|
||||
assertThat(context.getAuthentication()).isInstanceOf(BearerTokenAuthentication.class);
|
||||
BearerTokenAuthentication token = (BearerTokenAuthentication) context.getAuthentication();
|
||||
assertThat(token.getTokenAttributes().get(OAuth2IntrospectionClaimNames.SUBJECT)).isSameAs(sub);
|
||||
assertThat(token.getTokenAttributes().get(OAuth2TokenIntrospectionClaimNames.SUB)).isSameAs(sub);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -108,23 +108,23 @@ public class SecurityMockServerConfigurerOpaqueTokenTests extends AbstractMockSe
|
|||
.active((a) -> a.put("scope", "user"));
|
||||
this.client
|
||||
.mutateWith(SecurityMockServerConfigurers.mockOpaqueToken()
|
||||
.attributes((a) -> a.put(OAuth2IntrospectionClaimNames.SUBJECT, "foo")).principal(principal))
|
||||
.attributes((a) -> a.put(OAuth2TokenIntrospectionClaimNames.SUB, "foo")).principal(principal))
|
||||
.get().exchange().expectStatus().isOk();
|
||||
SecurityContext context = this.securityContextController.removeSecurityContext();
|
||||
assertThat(context.getAuthentication()).isInstanceOf(BearerTokenAuthentication.class);
|
||||
BearerTokenAuthentication token = (BearerTokenAuthentication) context.getAuthentication();
|
||||
assertThat((String) ((OAuth2AuthenticatedPrincipal) token.getPrincipal())
|
||||
.getAttribute(OAuth2IntrospectionClaimNames.SUBJECT))
|
||||
.isEqualTo(principal.getAttribute(OAuth2IntrospectionClaimNames.SUBJECT));
|
||||
.getAttribute(OAuth2TokenIntrospectionClaimNames.SUB))
|
||||
.isEqualTo(principal.getAttribute(OAuth2TokenIntrospectionClaimNames.SUB));
|
||||
this.client
|
||||
.mutateWith(SecurityMockServerConfigurers.mockOpaqueToken().principal(principal)
|
||||
.attributes((a) -> a.put(OAuth2IntrospectionClaimNames.SUBJECT, "bar")))
|
||||
.attributes((a) -> a.put(OAuth2TokenIntrospectionClaimNames.SUB, "bar")))
|
||||
.get().exchange().expectStatus().isOk();
|
||||
context = this.securityContextController.removeSecurityContext();
|
||||
assertThat(context.getAuthentication()).isInstanceOf(BearerTokenAuthentication.class);
|
||||
token = (BearerTokenAuthentication) context.getAuthentication();
|
||||
assertThat((String) ((OAuth2AuthenticatedPrincipal) token.getPrincipal())
|
||||
.getAttribute(OAuth2IntrospectionClaimNames.SUBJECT)).isEqualTo("bar");
|
||||
.getAttribute(OAuth2TokenIntrospectionClaimNames.SUB)).isEqualTo("bar");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue