SecurityTokenRepository associates SecurityToken to ClientRegistration

Fixes gh-4563
This commit is contained in:
Joe Grandja 2017-09-22 09:51:00 -04:00
parent 8521ca8f94
commit 680984c242
3 changed files with 49 additions and 31 deletions

View File

@ -155,7 +155,7 @@ public class AuthorizationCodeAuthenticationProvider implements AuthenticationPr
}
oauth2UserAuthentication.setDetails(oauth2ClientAuthentication.getDetails());
this.accessTokenRepository.saveSecurityToken(accessToken, oauth2UserAuthentication);
this.accessTokenRepository.saveSecurityToken(accessToken, clientRegistration);
return oauth2UserAuthentication;
}

View File

@ -15,58 +15,73 @@
*/
package org.springframework.security.oauth2.client.token;
import org.springframework.security.oauth2.client.authentication.OAuth2UserAuthenticationToken;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationIdentifierStrategy;
import org.springframework.security.oauth2.core.AccessToken;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.oauth2.oidc.core.user.OidcUser;
import org.springframework.util.Assert;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* A basic implementation of a {@link SecurityTokenRepository}
* that stores {@link AccessToken}(s) <i>in-memory</i>.
* A {@link SecurityTokenRepository} that associates an {@link AccessToken}
* to a {@link ClientRegistration Client} and stores it <i>in-memory</i>.
*
* @author Joe Grandja
* @since 5.0
* @see SecurityTokenRepository
* @see AccessToken
* @see ClientRegistration
*/
public final class InMemoryAccessTokenRepository implements SecurityTokenRepository<AccessToken> {
private final ClientRegistrationIdentifierStrategy<String> identifierStrategy = new AuthorizedClientIdentifierStrategy();
private final Map<String, AccessToken> accessTokens = new HashMap<>();
@Override
public AccessToken loadSecurityToken(OAuth2UserAuthenticationToken authentication) {
Assert.notNull(authentication, "authentication cannot be null");
return this.accessTokens.get(this.resolveAuthenticationKey(authentication));
public AccessToken loadSecurityToken(ClientRegistration registration) {
Assert.notNull(registration, "registration cannot be null");
return this.accessTokens.get(this.identifierStrategy.getIdentifier(registration));
}
@Override
public void saveSecurityToken(AccessToken accessToken, OAuth2UserAuthenticationToken authentication) {
public void saveSecurityToken(AccessToken accessToken, ClientRegistration registration) {
Assert.notNull(accessToken, "accessToken cannot be null");
Assert.notNull(authentication, "authentication cannot be null");
this.accessTokens.put(this.resolveAuthenticationKey(authentication), accessToken);
Assert.notNull(registration, "registration cannot be null");
this.accessTokens.put(this.identifierStrategy.getIdentifier(registration), accessToken);
}
@Override
public void removeSecurityToken(OAuth2UserAuthenticationToken authentication) {
Assert.notNull(authentication, "authentication cannot be null");
this.accessTokens.remove(this.resolveAuthenticationKey(authentication));
public void removeSecurityToken(ClientRegistration registration) {
Assert.notNull(registration, "registration cannot be null");
this.accessTokens.remove(this.identifierStrategy.getIdentifier(registration));
}
private String resolveAuthenticationKey(OAuth2UserAuthenticationToken authentication) {
String authenticationKey;
/**
* A client is considered <i>&quot;authorized&quot;</i>, if it receives a successful response from the <i>Token Endpoint</i>.
*
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1.3">Section 4.1.3 Access Token Request</a>
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-5.1">Section 5.1 Access Token Response</a>
*/
private static class AuthorizedClientIdentifierStrategy implements ClientRegistrationIdentifierStrategy<String> {
OAuth2User oauth2User = (OAuth2User) authentication.getPrincipal();
if (OidcUser.class.isAssignableFrom(oauth2User.getClass())) {
OidcUser oidcUser = (OidcUser)oauth2User;
authenticationKey = oidcUser.getIssuer().toString() + "-" + oidcUser.getSubject();
} else {
authenticationKey = authentication.getClientAuthentication().getClientRegistration()
.getProviderDetails().getUserInfoUri() + "-" + oauth2User.getName();
@Override
public String getIdentifier(ClientRegistration clientRegistration) {
StringBuilder builder = new StringBuilder();
// Access Token Request attributes
builder.append("[").append(clientRegistration.getAuthorizationGrantType().getValue()).append("]");
builder.append("[").append(clientRegistration.getRedirectUri()).append("]");
builder.append("[").append(clientRegistration.getClientId()).append("]");
// Access Token Response attributes
builder.append("[").append(clientRegistration.getScope().toString()).append("]");
// Client alias is unique as well
builder.append("[").append(clientRegistration.getClientAlias()).append("]");
return Base64.getEncoder().encodeToString(builder.toString().getBytes());
}
return authenticationKey;
}
}

View File

@ -15,22 +15,25 @@
*/
package org.springframework.security.oauth2.client.token;
import org.springframework.security.oauth2.client.authentication.OAuth2UserAuthenticationToken;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.core.SecurityToken;
/**
* Implementations of this interface are responsible for the persistence
* of {@link SecurityToken}(s) that are associated to an {@link OAuth2UserAuthenticationToken}.
* and association of an OAuth 2.0 / OpenID Connect 1.0
* {@link SecurityToken} to a {@link ClientRegistration Client}.
*
* @author Joe Grandja
* @since 5.0
* @see SecurityToken
* @see ClientRegistration
*/
public interface SecurityTokenRepository<T extends SecurityToken> {
T loadSecurityToken(OAuth2UserAuthenticationToken authentication);
T loadSecurityToken(ClientRegistration registration);
void saveSecurityToken(T securityToken, OAuth2UserAuthenticationToken authentication);
void saveSecurityToken(T securityToken, ClientRegistration registration);
void removeSecurityToken(OAuth2UserAuthenticationToken authentication);
void removeSecurityToken(ClientRegistration registration);
}