2 changed files with 210 additions and 0 deletions
@ -0,0 +1,67 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2019 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.security.oauth2.server.resource.authentication; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority; |
||||||
|
import org.springframework.security.core.SpringSecurityCoreVersion; |
||||||
|
import org.springframework.security.core.Transient; |
||||||
|
import org.springframework.security.oauth2.core.OAuth2AccessToken; |
||||||
|
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; |
||||||
|
import org.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* An {@link org.springframework.security.core.Authentication} token that represents a successful authentication as |
||||||
|
* obtained through a bearer token. |
||||||
|
* |
||||||
|
* @author Josh Cummings |
||||||
|
* @since 5.2 |
||||||
|
*/ |
||||||
|
@Transient |
||||||
|
public class BearerTokenAuthentication extends AbstractOAuth2TokenAuthenticationToken<OAuth2AccessToken> { |
||||||
|
|
||||||
|
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; |
||||||
|
|
||||||
|
private Map<String, Object> attributes; |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructs a {@link BearerTokenAuthentication} with the provided arguments |
||||||
|
* |
||||||
|
* @param principal The OAuth 2.0 attributes |
||||||
|
* @param credentials The verified token |
||||||
|
* @param authorities The authorities associated with the given token |
||||||
|
*/ |
||||||
|
public BearerTokenAuthentication(OAuth2AuthenticatedPrincipal principal, OAuth2AccessToken credentials, |
||||||
|
Collection<? extends GrantedAuthority> authorities) { |
||||||
|
|
||||||
|
super(credentials, principal, credentials, authorities); |
||||||
|
Assert.isTrue(credentials.getTokenType() == OAuth2AccessToken.TokenType.BEARER, "credentials must be a bearer token"); |
||||||
|
this.attributes = Collections.unmodifiableMap(new LinkedHashMap<>(principal.getAttributes())); |
||||||
|
setAuthenticated(true); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* {@inheritDoc} |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public Map<String, Object> getTokenAttributes() { |
||||||
|
return this.attributes; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,143 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2019 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.security.oauth2.server.resource.authentication; |
||||||
|
|
||||||
|
import java.net.URL; |
||||||
|
import java.time.Instant; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import net.minidev.json.JSONObject; |
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority; |
||||||
|
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 static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static org.assertj.core.api.Assertions.assertThatCode; |
||||||
|
import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.CLIENT_ID; |
||||||
|
import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.SUBJECT; |
||||||
|
import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.USERNAME; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests for {@link BearerTokenAuthentication} |
||||||
|
* |
||||||
|
* @author Josh Cummings |
||||||
|
*/ |
||||||
|
public class BearerTokenAuthenticationTests { |
||||||
|
private final OAuth2AccessToken token = |
||||||
|
new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, |
||||||
|
"token", Instant.now(), Instant.now().plusSeconds(3600)); |
||||||
|
private final String name = "sub"; |
||||||
|
private Map<String, Object> attributesMap = new HashMap<>(); |
||||||
|
private DefaultOAuth2AuthenticatedPrincipal principal; |
||||||
|
private final Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("USER"); |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() { |
||||||
|
this.attributesMap.put(SUBJECT, this.name); |
||||||
|
this.attributesMap.put(CLIENT_ID, "client_id"); |
||||||
|
this.attributesMap.put(USERNAME, "username"); |
||||||
|
this.principal = new DefaultOAuth2AuthenticatedPrincipal(this.attributesMap, null); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getNameWhenConfiguredInConstructorThenReturnsName() { |
||||||
|
OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(this.name, this.attributesMap, this.authorities); |
||||||
|
BearerTokenAuthentication authenticated = new BearerTokenAuthentication(principal, this.token, this.authorities); |
||||||
|
assertThat(authenticated.getName()).isEqualTo(this.name); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getNameWhenHasNoSubjectThenReturnsNull() { |
||||||
|
OAuth2AuthenticatedPrincipal principal = |
||||||
|
new DefaultOAuth2AuthenticatedPrincipal(Collections.singletonMap("claim", "value"), null); |
||||||
|
BearerTokenAuthentication authenticated = new BearerTokenAuthentication(principal, this.token, null); |
||||||
|
assertThat(authenticated.getName()).isNull(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getNameWhenTokenHasUsernameThenReturnsUsernameAttribute() { |
||||||
|
BearerTokenAuthentication authenticated = new BearerTokenAuthentication(this.principal, this.token, null); |
||||||
|
assertThat(authenticated.getName()).isEqualTo(this.principal.getAttribute(SUBJECT)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void constructorWhenTokenIsNullThenThrowsException() { |
||||||
|
assertThatCode(() -> new BearerTokenAuthentication(this.principal, null, null)) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("token cannot be null"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void constructorWhenCredentialIsNullThenThrowsException() { |
||||||
|
assertThatCode(() -> new BearerTokenAuthentication(null, this.token, null)) |
||||||
|
.isInstanceOf(IllegalArgumentException.class) |
||||||
|
.hasMessageContaining("principal cannot be null"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void constructorWhenPassingAllAttributesThenTokenIsAuthenticated() { |
||||||
|
OAuth2AuthenticatedPrincipal principal = |
||||||
|
new DefaultOAuth2AuthenticatedPrincipal("harris", Collections.singletonMap("claim", "value"), null); |
||||||
|
BearerTokenAuthentication authenticated = new BearerTokenAuthentication(principal, this.token, null); |
||||||
|
assertThat(authenticated.isAuthenticated()).isTrue(); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getTokenAttributesWhenHasTokenThenReturnsThem() { |
||||||
|
BearerTokenAuthentication authenticated = |
||||||
|
new BearerTokenAuthentication(this.principal, this.token, Collections.emptyList()); |
||||||
|
assertThat(authenticated.getTokenAttributes()).isEqualTo(this.principal.getAttributes()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void getAuthoritiesWhenHasAuthoritiesThenReturnsThem() { |
||||||
|
List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("USER"); |
||||||
|
BearerTokenAuthentication authenticated = |
||||||
|
new BearerTokenAuthentication(this.principal, this.token, authorities); |
||||||
|
assertThat(authenticated.getAuthorities()).isEqualTo(authorities); |
||||||
|
} |
||||||
|
|
||||||
|
// gh-6843
|
||||||
|
@Test |
||||||
|
public void constructorWhenDefaultParametersThenSetsPrincipalToAttributesCopy() { |
||||||
|
JSONObject attributes = new JSONObject(); |
||||||
|
attributes.put("active", true); |
||||||
|
OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(attributes, null); |
||||||
|
BearerTokenAuthentication token = new BearerTokenAuthentication(principal, this.token, null); |
||||||
|
assertThat(token.getPrincipal()).isNotSameAs(attributes); |
||||||
|
assertThat(token.getTokenAttributes()).isNotSameAs(attributes); |
||||||
|
} |
||||||
|
|
||||||
|
// gh-6843
|
||||||
|
@Test |
||||||
|
public void toStringWhenAttributesContainsURLThenDoesNotFail() throws Exception { |
||||||
|
JSONObject attributes = new JSONObject(Collections.singletonMap("iss", new URL("https://idp.example.com"))); |
||||||
|
OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(attributes, null); |
||||||
|
BearerTokenAuthentication token = new BearerTokenAuthentication(principal, this.token, null); |
||||||
|
assertThatCode(token::toString) |
||||||
|
.doesNotThrowAnyException(); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue