|
@@ -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>"authorized"</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("]");
|
|
|
|
|
|
- return authenticationKey;
|
|
|
+ // Client alias is unique as well
|
|
|
+ builder.append("[").append(clientRegistration.getClientAlias()).append("]");
|
|
|
+
|
|
|
+ return Base64.getEncoder().encodeToString(builder.toString().getBytes());
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|