From 9388002158f18556ceea72f4f4dbd13a459323d3 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Tue, 17 Aug 2021 16:08:57 -0400 Subject: [PATCH] Add javadoc for OAuth2TokenCustomizer Issue gh-199 --- .../security/oauth2/core/context/Context.java | 20 ++++ .../authorization/JwtEncodingContext.java | 46 ++++++++ .../authorization/OAuth2TokenContext.java | 109 ++++++++++++++++++ .../authorization/OAuth2TokenCustomizer.java | 9 ++ ...thorizationCodeAuthenticationProvider.java | 10 +- ...ientCredentialsAuthenticationProvider.java | 8 ++ ...th2RefreshTokenAuthenticationProvider.java | 8 ++ 7 files changed, 209 insertions(+), 1 deletion(-) diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/context/Context.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/context/Context.java index 2592935b..7d5f780f 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/context/Context.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/context/Context.java @@ -26,9 +26,23 @@ import org.springframework.util.Assert; */ public interface Context { + /** + * Returns the value of the attribute associated to the key. + * + * @param key the key for the attribute + * @param the type of the value for the attribute + * @return the value of the attribute associated to the key, or {@code null} if not available + */ @Nullable V get(Object key); + /** + * Returns the value of the attribute associated to the key. + * + * @param key the key for the attribute + * @param the type of the value for the attribute + * @return the value of the attribute associated to the key, or {@code null} if not available or not of the specified type + */ @Nullable default V get(Class key) { Assert.notNull(key, "key cannot be null"); @@ -36,6 +50,12 @@ public interface Context { return key.isInstance(value) ? value : null; } + /** + * Returns {@code true} if an attribute associated to the key exists, {@code false} otherwise. + * + * @param key the key for the attribute + * @return {@code true} if an attribute associated to the key exists, {@code false} otherwise + */ boolean hasKey(Object key); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContext.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContext.java index 33d48ac8..346716d5 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContext.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/JwtEncodingContext.java @@ -22,15 +22,20 @@ import java.util.function.Consumer; import org.springframework.lang.Nullable; import org.springframework.security.oauth2.jwt.JoseHeader; +import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtClaimsSet; +import org.springframework.security.oauth2.jwt.JwtEncoder; import org.springframework.util.Assert; /** + * An {@link OAuth2TokenContext} implementation used when encoding a {@link Jwt}. + * * @author Joe Grandja * @since 0.1.0 * @see OAuth2TokenContext * @see JoseHeader.Builder * @see JwtClaimsSet.Builder + * @see JwtEncoder#encode(JoseHeader, JwtClaimsSet) */ public final class JwtEncodingContext implements OAuth2TokenContext { private final Map context; @@ -52,18 +57,38 @@ public final class JwtEncodingContext implements OAuth2TokenContext { return this.context.containsKey(key); } + /** + * Returns the {@link JoseHeader.Builder headers}. + * + * @return the {@link JoseHeader.Builder} + */ public JoseHeader.Builder getHeaders() { return get(JoseHeader.Builder.class); } + /** + * Returns the {@link JwtClaimsSet.Builder claims}. + * + * @return the {@link JwtClaimsSet.Builder} + */ public JwtClaimsSet.Builder getClaims() { return get(JwtClaimsSet.Builder.class); } + /** + * Constructs a new {@link Builder} with the provided headers and claims. + * + * @param headersBuilder the headers to initialize the builder + * @param claimsBuilder the claims to initialize the builder + * @return the {@link Builder} + */ public static Builder with(JoseHeader.Builder headersBuilder, JwtClaimsSet.Builder claimsBuilder) { return new Builder(headersBuilder, claimsBuilder); } + /** + * A builder for {@link JwtEncodingContext}. + */ public static final class Builder extends AbstractBuilder { private Builder(JoseHeader.Builder headersBuilder, JwtClaimsSet.Builder claimsBuilder) { @@ -73,18 +98,39 @@ public final class JwtEncodingContext implements OAuth2TokenContext { put(JwtClaimsSet.Builder.class, claimsBuilder); } + /** + * A {@code Consumer} of the {@link JoseHeader.Builder headers} + * allowing the ability to add, replace, or remove. + * + * @param headersConsumer a {@code Consumer} of the {@link JoseHeader.Builder headers} + * @return the {@link Builder} for further configuration + */ public Builder headers(Consumer headersConsumer) { headersConsumer.accept(get(JoseHeader.Builder.class)); return this; } + /** + * A {@code Consumer} of the {@link JwtClaimsSet.Builder claims} + * allowing the ability to add, replace, or remove. + * + * @param claimsConsumer a {@code Consumer} of the {@link JwtClaimsSet.Builder claims} + * @return the {@link Builder} for further configuration + */ public Builder claims(Consumer claimsConsumer) { claimsConsumer.accept(get(JwtClaimsSet.Builder.class)); return this; } + /** + * Builds a new {@link JwtEncodingContext}. + * + * @return the {@link JwtEncodingContext} + */ public JwtEncodingContext build() { return new JwtEncodingContext(getContext()); } + } + } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenContext.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenContext.java index d586d2a3..e1882809 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenContext.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenContext.java @@ -30,43 +30,90 @@ import org.springframework.security.oauth2.server.authorization.client.Registere import org.springframework.util.Assert; /** + * A context that holds information associated to an OAuth 2.0 Token + * and is used by an {@link OAuth2TokenCustomizer} for customizing the token attributes. + * * @author Joe Grandja * @since 0.1.0 * @see Context + * @see OAuth2TokenCustomizer */ public interface OAuth2TokenContext extends Context { + /** + * Returns the {@link RegisteredClient registered client}. + * + * @return the {@link RegisteredClient} + */ default RegisteredClient getRegisteredClient() { return get(RegisteredClient.class); } + /** + * Returns the {@link Authentication} representing the {@code Principal} resource owner (or client). + * + * @param the type of the {@code Authentication} + * @return the {@link Authentication} representing the {@code Principal} resource owner (or client) + */ default T getPrincipal() { return get(AbstractBuilder.PRINCIPAL_AUTHENTICATION_KEY); } + /** + * Returns the {@link OAuth2Authorization authorization}. + * + * @return the {@link OAuth2Authorization}, or {@code null} if not available + */ @Nullable default OAuth2Authorization getAuthorization() { return get(OAuth2Authorization.class); } + /** + * Returns the authorized scope(s). + * + * @return the authorized scope(s) + */ default Set getAuthorizedScopes() { return hasKey(OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME) ? get(OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME) : Collections.emptySet(); } + /** + * Returns the {@link OAuth2TokenType token type}. + * + * @return the {@link OAuth2TokenType} + */ default OAuth2TokenType getTokenType() { return get(OAuth2TokenType.class); } + /** + * Returns the {@link AuthorizationGrantType authorization grant type}. + * + * @return the {@link AuthorizationGrantType} + */ default AuthorizationGrantType getAuthorizationGrantType() { return get(AuthorizationGrantType.class); } + /** + * Returns the {@link Authentication} representing the authorization grant. + * + * @param the type of the {@code Authentication} + * @return the {@link Authentication} representing the authorization grant + */ default T getAuthorizationGrant() { return get(AbstractBuilder.AUTHORIZATION_GRANT_AUTHENTICATION_KEY); } + /** + * Base builder for implementations of {@link OAuth2TokenContext}. + * + * @param the type of the context + * @param the type of the builder + */ abstract class AbstractBuilder> { private static final String PRINCIPAL_AUTHENTICATION_KEY = Authentication.class.getName().concat(".PRINCIPAL"); @@ -74,34 +121,83 @@ public interface OAuth2TokenContext extends Context { Authentication.class.getName().concat(".AUTHORIZATION_GRANT"); private final Map context = new HashMap<>(); + /** + * Sets the {@link RegisteredClient registered client}. + * + * @param registeredClient the {@link RegisteredClient} + * @return the {@link AbstractBuilder} for further configuration + */ public B registeredClient(RegisteredClient registeredClient) { return put(RegisteredClient.class, registeredClient); } + /** + * Sets the {@link Authentication} representing the {@code Principal} resource owner (or client). + * + * @param principal the {@link Authentication} representing the {@code Principal} resource owner (or client) + * @return the {@link AbstractBuilder} for further configuration + */ public B principal(Authentication principal) { return put(PRINCIPAL_AUTHENTICATION_KEY, principal); } + /** + * Sets the {@link OAuth2Authorization authorization}. + * + * @param authorization the {@link OAuth2Authorization} + * @return the {@link AbstractBuilder} for further configuration + */ public B authorization(OAuth2Authorization authorization) { return put(OAuth2Authorization.class, authorization); } + /** + * Sets the authorized scope(s). + * + * @param authorizedScopes the authorized scope(s) + * @return the {@link AbstractBuilder} for further configuration + */ public B authorizedScopes(Set authorizedScopes) { return put(OAuth2Authorization.AUTHORIZED_SCOPE_ATTRIBUTE_NAME, authorizedScopes); } + /** + * Sets the {@link OAuth2TokenType token type}. + * + * @param tokenType the {@link OAuth2TokenType} + * @return the {@link AbstractBuilder} for further configuration + */ public B tokenType(OAuth2TokenType tokenType) { return put(OAuth2TokenType.class, tokenType); } + /** + * Sets the {@link AuthorizationGrantType authorization grant type}. + * + * @param authorizationGrantType the {@link AuthorizationGrantType} + * @return the {@link AbstractBuilder} for further configuration + */ public B authorizationGrantType(AuthorizationGrantType authorizationGrantType) { return put(AuthorizationGrantType.class, authorizationGrantType); } + /** + * Sets the {@link Authentication} representing the authorization grant. + * + * @param authorizationGrant the {@link Authentication} representing the authorization grant + * @return the {@link AbstractBuilder} for further configuration + */ public B authorizationGrant(Authentication authorizationGrant) { return put(AUTHORIZATION_GRANT_AUTHENTICATION_KEY, authorizationGrant); } + /** + * Associates an attribute. + * + * @param key the key for the attribute + * @param value the value of the attribute + * @return the {@link AbstractBuilder} for further configuration + */ public B put(Object key, Object value) { Assert.notNull(key, "key cannot be null"); Assert.notNull(value, "value cannot be null"); @@ -109,6 +205,13 @@ public interface OAuth2TokenContext extends Context { return getThis(); } + /** + * A {@code Consumer} of the attributes {@code Map} + * allowing the ability to add, replace, or remove. + * + * @param contextConsumer a {@link Consumer} of the attributes {@code Map} + * @return the {@link AbstractBuilder} for further configuration + */ public B context(Consumer> contextConsumer) { contextConsumer.accept(this.context); return getThis(); @@ -128,7 +231,13 @@ public interface OAuth2TokenContext extends Context { return (B) this; } + /** + * Builds a new {@link OAuth2TokenContext}. + * + * @return the {@link OAuth2TokenContext} + */ public abstract T build(); } + } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenCustomizer.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenCustomizer.java index 4b3fcda5..b1bcb800 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenCustomizer.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenCustomizer.java @@ -16,13 +16,22 @@ package org.springframework.security.oauth2.server.authorization; /** + * Implementations of this interface are responsible for customizing the + * OAuth 2.0 Token attributes contained within the {@link OAuth2TokenContext}. + * * @author Joe Grandja * @since 0.1.0 * @see OAuth2TokenContext + * @param the type of the context containing the OAuth 2.0 Token attributes */ @FunctionalInterface public interface OAuth2TokenCustomizer { + /** + * Customize the OAuth 2.0 Token attributes. + * + * @param context the context containing the OAuth 2.0 Token attributes + */ void customize(C context); } diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java index c94e87af..6bd0ac4a 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationProvider.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Supplier; import org.springframework.beans.factory.annotation.Autowired; @@ -35,6 +36,7 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.ClientAuthenticationMethod; import org.springframework.security.oauth2.core.OAuth2AccessToken; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AuthorizationCode; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.oauth2.core.OAuth2ErrorCodes; import org.springframework.security.oauth2.core.OAuth2RefreshToken; @@ -50,7 +52,6 @@ import org.springframework.security.oauth2.jwt.JwtClaimsSet; import org.springframework.security.oauth2.jwt.JwtEncoder; import org.springframework.security.oauth2.server.authorization.JwtEncodingContext; import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; -import org.springframework.security.oauth2.core.OAuth2AuthorizationCode; import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService; import org.springframework.security.oauth2.server.authorization.OAuth2TokenCustomizer; import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; @@ -102,6 +103,13 @@ public final class OAuth2AuthorizationCodeAuthenticationProvider implements Auth this.jwtEncoder = jwtEncoder; } + /** + * Sets the {@link OAuth2TokenCustomizer} that customizes the + * {@link JwtEncodingContext.Builder#headers(Consumer) headers} and/or + * {@link JwtEncodingContext.Builder#claims(Consumer) claims} for the generated {@link Jwt}. + * + * @param jwtCustomizer the {@link OAuth2TokenCustomizer} that customizes the headers and/or claims for the generated {@code Jwt} + */ public void setJwtCustomizer(OAuth2TokenCustomizer jwtCustomizer) { Assert.notNull(jwtCustomizer, "jwtCustomizer cannot be null"); this.jwtCustomizer = jwtCustomizer; diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java index 758d6e04..763af390 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationProvider.java @@ -17,6 +17,7 @@ package org.springframework.security.oauth2.server.authorization.authentication; import java.util.LinkedHashSet; import java.util.Set; +import java.util.function.Consumer; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; @@ -79,6 +80,13 @@ public final class OAuth2ClientCredentialsAuthenticationProvider implements Auth this.jwtEncoder = jwtEncoder; } + /** + * Sets the {@link OAuth2TokenCustomizer} that customizes the + * {@link JwtEncodingContext.Builder#headers(Consumer) headers} and/or + * {@link JwtEncodingContext.Builder#claims(Consumer) claims} for the generated {@link Jwt}. + * + * @param jwtCustomizer the {@link OAuth2TokenCustomizer} that customizes the headers and/or claims for the generated {@code Jwt} + */ public void setJwtCustomizer(OAuth2TokenCustomizer jwtCustomizer) { Assert.notNull(jwtCustomizer, "jwtCustomizer cannot be null"); this.jwtCustomizer = jwtCustomizer; diff --git a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java index 0f7c3786..981778ad 100644 --- a/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java +++ b/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationProvider.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Supplier; import org.springframework.beans.factory.annotation.Autowired; @@ -96,6 +97,13 @@ public final class OAuth2RefreshTokenAuthenticationProvider implements Authentic this.jwtEncoder = jwtEncoder; } + /** + * Sets the {@link OAuth2TokenCustomizer} that customizes the + * {@link JwtEncodingContext.Builder#headers(Consumer) headers} and/or + * {@link JwtEncodingContext.Builder#claims(Consumer) claims} for the generated {@link Jwt}. + * + * @param jwtCustomizer the {@link OAuth2TokenCustomizer} that customizes the headers and/or claims for the generated {@code Jwt} + */ public void setJwtCustomizer(OAuth2TokenCustomizer jwtCustomizer) { Assert.notNull(jwtCustomizer, "jwtCustomizer cannot be null"); this.jwtCustomizer = jwtCustomizer;