Add documentation for DPoP support
Closes gh-17072
This commit is contained in:
@@ -23,6 +23,9 @@ import org.springframework.security.oauth2.core.OAuth2Token;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A context class that holds a DPoP Proof {@link Jwt} and additional parameters
|
||||
* associated to an Access Token request or a Protected Resource request.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 6.5
|
||||
* @see DPoPProofJwtDecoderFactory
|
||||
@@ -44,28 +47,58 @@ public final class DPoPProofContext {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DPoP Proof {@link Jwt}.
|
||||
* @return the DPoP Proof {@link Jwt}
|
||||
*/
|
||||
public String getDPoPProof() {
|
||||
return this.dPoPProof;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the HTTP method of the request to which the DPoP Proof
|
||||
* {@link Jwt} is attached.
|
||||
* @return the value of the HTTP method of the request to which the DPoP Proof
|
||||
* {@link Jwt} is attached
|
||||
*/
|
||||
public String getMethod() {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the HTTP target URI of the request to which the DPoP Proof
|
||||
* {@link Jwt} is attached, without query and fragment parts.
|
||||
* @return the value of the HTTP target URI of the request to which the DPoP Proof
|
||||
* {@link Jwt} is attached
|
||||
*/
|
||||
public String getTargetUri() {
|
||||
return this.targetUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access token if the request is a Protected Resource request.
|
||||
* @param <T> the type of the access token
|
||||
* @return the access token if the request is a Protected Resource request or
|
||||
* {@code null}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public <T extends OAuth2Token> T getAccessToken() {
|
||||
return (T) this.accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link Builder}, initialized with the DPoP Proof {@link Jwt}.
|
||||
* @param dPoPProof the DPoP Proof {@link Jwt}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public static Builder withDPoPProof(String dPoPProof) {
|
||||
return new Builder(dPoPProof);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for {@link DPoPProofContext}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
|
||||
private String dPoPProof;
|
||||
@@ -81,21 +114,45 @@ public final class DPoPProofContext {
|
||||
this.dPoPProof = dPoPProof;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the HTTP method of the request to which the DPoP Proof
|
||||
* {@link Jwt} is attached.
|
||||
* @param method the value of the HTTP method of the request to which the DPoP
|
||||
* Proof {@link Jwt} is attached
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder method(String method) {
|
||||
this.method = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the HTTP target URI of the request to which the DPoP Proof
|
||||
* {@link Jwt} is attached, without query and fragment parts.
|
||||
* @param targetUri the value of the HTTP target URI of the request to which the
|
||||
* DPoP Proof {@link Jwt} is attached
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder targetUri(String targetUri) {
|
||||
this.targetUri = targetUri;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the access token if the request is a Protected Resource request.
|
||||
* @param accessToken the access token if the request is a Protected Resource
|
||||
* request
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder accessToken(OAuth2Token accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new {@link DPoPProofContext}.
|
||||
* @return a {@link DPoPProofContext}
|
||||
*/
|
||||
public DPoPProofContext build() {
|
||||
validate();
|
||||
return new DPoPProofContext(this.dPoPProof, this.method, this.targetUri, this.accessToken);
|
||||
|
||||
@@ -48,17 +48,29 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link JwtDecoderFactory factory} that provides a {@link JwtDecoder} for the
|
||||
* specified {@link DPoPProofContext} and is used for authenticating a DPoP Proof
|
||||
* {@link Jwt}.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 6.5
|
||||
* @see JwtDecoderFactory
|
||||
* @see DPoPProofContext
|
||||
* @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc9449">RFC 9449
|
||||
* OAuth 2.0 Demonstrating Proof of Possession (DPoP)</a>
|
||||
*/
|
||||
public final class DPoPProofJwtDecoderFactory implements JwtDecoderFactory<DPoPProofContext> {
|
||||
|
||||
/**
|
||||
* The default {@code OAuth2TokenValidator<Jwt>} factory that validates the
|
||||
* {@code htm}, {@code htu}, {@code jti} and {@code iat} claims of the DPoP Proof
|
||||
* {@link Jwt}.
|
||||
*/
|
||||
public static final Function<DPoPProofContext, OAuth2TokenValidator<Jwt>> DEFAULT_JWT_VALIDATOR_FACTORY = defaultJwtValidatorFactory();
|
||||
|
||||
private static final JOSEObjectTypeVerifier<SecurityContext> DPOP_TYPE_VERIFIER = new DefaultJOSEObjectTypeVerifier<>(
|
||||
new JOSEObjectType("dpop+jwt"));
|
||||
|
||||
public static final Function<DPoPProofContext, OAuth2TokenValidator<Jwt>> DEFAULT_JWT_VALIDATOR_FACTORY = defaultJwtValidatorFactory();
|
||||
|
||||
private Function<DPoPProofContext, OAuth2TokenValidator<Jwt>> jwtValidatorFactory = DEFAULT_JWT_VALIDATOR_FACTORY;
|
||||
|
||||
@Override
|
||||
@@ -69,6 +81,14 @@ public final class DPoPProofJwtDecoderFactory implements JwtDecoderFactory<DPoPP
|
||||
return jwtDecoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the factory that provides an {@link OAuth2TokenValidator} for the specified
|
||||
* {@link DPoPProofContext} and is used by the {@link JwtDecoder}. The default
|
||||
* {@code OAuth2TokenValidator<Jwt>} factory is
|
||||
* {@link #DEFAULT_JWT_VALIDATOR_FACTORY}.
|
||||
* @param jwtValidatorFactory the factory that provides an
|
||||
* {@link OAuth2TokenValidator} for the specified {@link DPoPProofContext}
|
||||
*/
|
||||
public void setJwtValidatorFactory(Function<DPoPProofContext, OAuth2TokenValidator<Jwt>> jwtValidatorFactory) {
|
||||
Assert.notNull(jwtValidatorFactory, "jwtValidatorFactory cannot be null");
|
||||
this.jwtValidatorFactory = jwtValidatorFactory;
|
||||
|
||||
@@ -50,10 +50,15 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* An {@link AuthenticationProvider} implementation that is responsible for authenticating
|
||||
* a DPoP-bound access token for a protected resource request.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 6.5
|
||||
* @see DPoPAuthenticationToken
|
||||
* @see DPoPProofJwtDecoderFactory
|
||||
* @see <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc9449">RFC 9449
|
||||
* OAuth 2.0 Demonstrating Proof of Possession (DPoP)</a>
|
||||
*/
|
||||
public final class DPoPAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
@@ -61,6 +66,11 @@ public final class DPoPAuthenticationProvider implements AuthenticationProvider
|
||||
|
||||
private JwtDecoderFactory<DPoPProofContext> dPoPProofVerifierFactory;
|
||||
|
||||
/**
|
||||
* Constructs a {@code DPoPAuthenticationProvider} using the provided parameters.
|
||||
* @param tokenAuthenticationManager the {@link AuthenticationManager} used to
|
||||
* authenticate the DPoP-bound access token
|
||||
*/
|
||||
public DPoPAuthenticationProvider(AuthenticationManager tokenAuthenticationManager) {
|
||||
Assert.notNull(tokenAuthenticationManager, "tokenAuthenticationManager cannot be null");
|
||||
this.tokenAuthenticationManager = tokenAuthenticationManager;
|
||||
@@ -121,6 +131,13 @@ public final class DPoPAuthenticationProvider implements AuthenticationProvider
|
||||
return DPoPAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link JwtDecoderFactory} that provides a {@link JwtDecoder} for the
|
||||
* specified {@link DPoPProofContext} and is used for authenticating a DPoP Proof
|
||||
* {@link Jwt}. The default factory is {@link DPoPProofJwtDecoderFactory}.
|
||||
* @param dPoPProofVerifierFactory the {@link JwtDecoderFactory} that provides a
|
||||
* {@link JwtDecoder} for the specified {@link DPoPProofContext}
|
||||
*/
|
||||
public void setDPoPProofVerifierFactory(JwtDecoderFactory<DPoPProofContext> dPoPProofVerifierFactory) {
|
||||
Assert.notNull(dPoPProofVerifierFactory, "dPoPProofVerifierFactory cannot be null");
|
||||
this.dPoPProofVerifierFactory = dPoPProofVerifierFactory;
|
||||
|
||||
@@ -20,9 +20,14 @@ import java.io.Serial;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An {@link Authentication} representing a protected resource request with a DPoP-bound
|
||||
* access token.
|
||||
*
|
||||
* @author Joe Grandja
|
||||
* @since 6.5
|
||||
* @see DPoPAuthenticationProvider
|
||||
@@ -40,6 +45,14 @@ public class DPoPAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
private final String resourceUri;
|
||||
|
||||
/**
|
||||
* Constructs a {@code DPoPAuthenticationToken} using the provided parameters.
|
||||
* @param accessToken the DPoP-bound access token
|
||||
* @param dPoPProof the DPoP Proof {@link Jwt}
|
||||
* @param method the value of the HTTP method of the request
|
||||
* @param resourceUri the value of the HTTP resource URI of the request, without query
|
||||
* and fragment parts
|
||||
*/
|
||||
public DPoPAuthenticationToken(String accessToken, String dPoPProof, String method, String resourceUri) {
|
||||
super(Collections.emptyList());
|
||||
Assert.hasText(accessToken, "accessToken cannot be empty");
|
||||
@@ -62,18 +75,35 @@ public class DPoPAuthenticationToken extends AbstractAuthenticationToken {
|
||||
return getAccessToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DPoP-bound access token.
|
||||
* @return the DPoP-bound access token
|
||||
*/
|
||||
public String getAccessToken() {
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DPoP Proof {@link Jwt}.
|
||||
* @return the DPoP Proof {@link Jwt}
|
||||
*/
|
||||
public String getDPoPProof() {
|
||||
return this.dPoPProof;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the HTTP method of the request.
|
||||
* @return the value of the HTTP method of the request
|
||||
*/
|
||||
public String getMethod() {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the HTTP resource URI of the request, without query and
|
||||
* fragment parts.
|
||||
* @return the value of the HTTP resource URI of the request
|
||||
*/
|
||||
public String getResourceUri() {
|
||||
return this.resourceUri;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user