Skip to content

Commit

Permalink
Add OAuth2TokenAttributesAuthenticationConverter
Browse files Browse the repository at this point in the history
  • Loading branch information
jzheaux committed Aug 1, 2019
1 parent 04d981e commit aee5e27
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,25 @@
* @author Clement Ng
* @since 5.2
*/
public final class OAuth2TokenAttributes {
public class OAuth2TokenAttributes {
private final String token;
private final Map<String, Object> attributes;

/**
* Constructs an {@code OAuth2TokenAttributes} using the provided parameters.
*
* @param token the OAuth 2.0 token
* @param attributes the attributes of the OAuth 2.0 token
*/
public OAuth2TokenAttributes(Map<String, Object> attributes) {
public OAuth2TokenAttributes(String token, Map<String, Object> attributes) {
this.token = token;
this.attributes = Collections.unmodifiableMap(attributes);
}

public String getToken() {
return this.token;
}

/**
* Gets the attributes of the OAuth 2.0 token in map form.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,25 @@
*/
package org.springframework.security.oauth2.server.resource.authentication;

import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2TokenAttributes;
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
import org.springframework.security.oauth2.server.resource.introspection.OAuth2TokenIntrospectionClient;
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
import org.springframework.security.oauth2.server.resource.BearerTokenError;
import org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionException;
import org.springframework.security.oauth2.server.resource.introspection.OAuth2TokenIntrospectionClient;
import org.springframework.util.Assert;

import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.EXPIRES_AT;
import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.ISSUED_AT;
import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.SCOPE;

/**
* An {@link AuthenticationProvider} implementation for opaque
* <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>s,
Expand Down Expand Up @@ -70,6 +61,8 @@ public final class OAuth2IntrospectionAuthenticationProvider implements Authenti
invalidToken("An error occurred while attempting to introspect the token: Invalid token");

private OAuth2TokenIntrospectionClient introspectionClient;
private Converter<OAuth2TokenAttributes, ? extends AbstractAuthenticationToken> tokenAttributesAuthenticationConverter =
new OAuth2TokenAttributesAuthenticationConverter();

/**
* Creates a {@code OAuth2IntrospectionAuthenticationProvider} with the provided parameters
Expand Down Expand Up @@ -110,6 +103,11 @@ public Authentication authenticate(Authentication authentication) throws Authent
return result;
}

public void setTokenAttributesAuthenticationConverter
(Converter<OAuth2TokenAttributes, ? extends AbstractAuthenticationToken> tokenAttributesAuthenticationConverter) {
this.tokenAttributesAuthenticationConverter = tokenAttributesAuthenticationConverter;
}

/**
* {@inheritDoc}
*/
Expand All @@ -119,20 +117,7 @@ public boolean supports(Class<?> authentication) {
}

private AbstractAuthenticationToken convert(String token, Map<String, Object> claims) {
Instant iat = (Instant) claims.get(ISSUED_AT);
Instant exp = (Instant) claims.get(EXPIRES_AT);
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
token, iat, exp);
Collection<GrantedAuthority> authorities = extractAuthorities(claims);
return new OAuth2IntrospectionAuthenticationToken(accessToken, new OAuth2TokenAttributes(claims), authorities);
}

private Collection<GrantedAuthority> extractAuthorities(Map<String, Object> claims) {
Collection<String> scopes = (Collection<String>) claims.get(SCOPE);
return Optional.ofNullable(scopes).orElse(Collections.emptyList())
.stream()
.map(authority -> new SimpleGrantedAuthority("SCOPE_" + authority))
.collect(Collectors.toList());
return this.tokenAttributesAuthenticationConverter.convert(new OAuth2TokenAttributes(token, claims));
}

private static BearerTokenError invalidToken(String message) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.OAuth2TokenAttributes;

import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.EXPIRES_AT;
import static org.springframework.security.oauth2.server.resource.introspection.OAuth2IntrospectionClaimNames.ISSUED_AT;

public class OAuth2TokenAttributesAuthenticationConverter
implements Converter<OAuth2TokenAttributes, AbstractAuthenticationToken> {

private static final String SCOPE = "scope";

@Override
public AbstractAuthenticationToken convert(OAuth2TokenAttributes source) {
Instant iat = source.getAttribute(ISSUED_AT);
Instant exp = source.getAttribute(EXPIRES_AT);
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, source.getToken(), iat, exp);
Collection<GrantedAuthority> authorities = extractAuthorities(source);
return new OAuth2IntrospectionAuthenticationToken(accessToken, source, authorities);
}

private Collection<GrantedAuthority> extractAuthorities(OAuth2TokenAttributes attributes) {
Collection<String> scopes = attributes.getAttribute(SCOPE);
return Optional.ofNullable(scopes).orElse(Collections.emptyList())
.stream()
.map(authority -> new SimpleGrantedAuthority("SCOPE_" + authority))
.collect(Collectors.toList());
}
}

0 comments on commit aee5e27

Please sign in to comment.