Add javadoc for spring-security-oauth2-core

Fixes gh-4883
This commit is contained in:
Joe Grandja 2018-01-16 17:33:46 -05:00
parent 91ef7ce1cf
commit e6cac604f3
36 changed files with 1073 additions and 58 deletions

View File

@ -22,10 +22,11 @@ import java.io.Serializable;
import java.time.Instant;
/**
* Base class for <i>OAuth 2.0 Token</i> implementations.
* Base class for OAuth 2.0 Token implementations.
*
* @author Joe Grandja
* @since 5.0
* @see OAuth2AccessToken
*/
public abstract class AbstractOAuth2Token implements Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
@ -33,6 +34,13 @@ public abstract class AbstractOAuth2Token implements Serializable {
private final Instant issuedAt;
private final Instant expiresAt;
/**
* Sub-class constructor.
*
* @param tokenValue the token value
* @param issuedAt the time at which the token was issued
* @param expiresAt the expiration time on or after which the token MUST NOT be accepted
*/
protected AbstractOAuth2Token(String tokenValue, Instant issuedAt, Instant expiresAt) {
Assert.hasText(tokenValue, "tokenValue cannot be empty");
Assert.notNull(issuedAt, "issuedAt cannot be null");
@ -43,14 +51,29 @@ public abstract class AbstractOAuth2Token implements Serializable {
this.expiresAt = expiresAt;
}
/**
* Returns the token value.
*
* @return the token value
*/
public String getTokenValue() {
return this.tokenValue;
}
/**
* Returns the time at which the token was issued.
*
* @return the time the token was issued
*/
public Instant getIssuedAt() {
return this.issuedAt;
}
/**
* Returns the expiration time on or after which the token MUST NOT be accepted.
*
* @return the expiration time of the token
*/
public Instant getExpiresAt() {
return this.expiresAt;
}

View File

@ -25,7 +25,7 @@ import java.io.Serializable;
* (to access it's protected resources) to the client and used by the client to obtain an access token.
*
* <p>
* The <i>OAuth 2.0 Authorization Framework</i> defines four standard grant types:
* The OAuth 2.0 Authorization Framework defines four standard grant types:
* authorization code, implicit, resource owner password credentials, and client credentials.
* It also provides an extensibility mechanism for defining additional grant types.
*
@ -39,11 +39,21 @@ public final class AuthorizationGrantType implements Serializable {
public static final AuthorizationGrantType IMPLICIT = new AuthorizationGrantType("implicit");
private final String value;
/**
* Constructs an {@code AuthorizationGrantType} using the provided value.
*
* @param value the value of the authorization grant type
*/
public AuthorizationGrantType(String value) {
Assert.hasText(value, "value cannot be empty");
this.value = value;
}
/**
* Returns the value of the authorization grant type.
*
* @return the value of the authorization grant type
*/
public String getValue() {
return this.value;
}

View File

@ -33,21 +33,50 @@ import java.util.Map;
*/
public interface ClaimAccessor {
/**
* Returns a set of claims that may be used for assertions.
*
* @return a {@code Map} of claims
*/
Map<String, Object> getClaims();
/**
* Returns {@code true} if the claim exists in {@link #getClaims()}, otherwise {@code false}.
*
* @param claim the name of the claim
* @return {@code true} if the claim exists, otherwise {@code false}
*/
default Boolean containsClaim(String claim) {
Assert.notNull(claim, "claim cannot be null");
return this.getClaims().containsKey(claim);
}
/**
* Returns the claim value as a {@code String} or {@code null} if it does not exist.
*
* @param claim the name of the claim
* @return the claim value or {@code null} if it does not exist
*/
default String getClaimAsString(String claim) {
return (this.containsClaim(claim) ? this.getClaims().get(claim).toString() : null);
}
/**
* Returns the claim value as a {@code Boolean} or {@code null} if it does not exist.
*
* @param claim the name of the claim
* @return the claim value or {@code null} if it does not exist
*/
default Boolean getClaimAsBoolean(String claim) {
return (this.containsClaim(claim) ? Boolean.valueOf(this.getClaimAsString(claim)) : null);
}
/**
* Returns the claim value as an {@code Instant} or {@code null} if it does not exist.
*
* @param claim the name of the claim
* @return the claim value or {@code null} if it does not exist
*/
default Instant getClaimAsInstant(String claim) {
if (!this.containsClaim(claim)) {
return null;
@ -59,6 +88,12 @@ public interface ClaimAccessor {
}
}
/**
* Returns the claim value as an {@code URL} or {@code null} if it does not exist.
*
* @param claim the name of the claim
* @return the claim value or {@code null} if it does not exist
*/
default URL getClaimAsURL(String claim) {
if (!this.containsClaim(claim)) {
return null;
@ -70,6 +105,13 @@ public interface ClaimAccessor {
}
}
/**
* Returns the claim value as a {@code Map<String, Object>}
* or {@code null} if it does not exist or cannot be assigned to a {@code Map}.
*
* @param claim the name of the claim
* @return the claim value or {@code null} if it does not exist or cannot be assigned to a {@code Map}
*/
default Map<String, Object> getClaimAsMap(String claim) {
if (!this.containsClaim(claim) || !Map.class.isAssignableFrom(this.getClaims().get(claim).getClass())) {
return null;
@ -79,6 +121,13 @@ public interface ClaimAccessor {
return claimValues;
}
/**
* Returns the claim value as a {@code List<String>}
* or {@code null} if it does not exist or cannot be assigned to a {@code List}.
*
* @param claim the name of the claim
* @return the claim value or {@code null} if it does not exist or cannot be assigned to a {@code List}
*/
default List<String> getClaimAsStringList(String claim) {
if (!this.containsClaim(claim) || !List.class.isAssignableFrom(this.getClaims().get(claim).getClass())) {
return null;

View File

@ -18,7 +18,7 @@ package org.springframework.security.oauth2.core;
import org.springframework.util.Assert;
/**
* The authentication methods used when authenticating the client with the authorization server.
* The authentication method used when authenticating the client with the authorization server.
*
* @author Joe Grandja
* @since 5.0
@ -29,11 +29,21 @@ public final class ClientAuthenticationMethod {
public static final ClientAuthenticationMethod POST = new ClientAuthenticationMethod("post");
private final String value;
/**
* Constructs a {@code ClientAuthenticationMethod} using the provided value.
*
* @param value the value of the client authentication method
*/
public ClientAuthenticationMethod(String value) {
Assert.hasText(value, "value cannot be empty");
this.value = value;
}
/**
* Returns the value of the client authentication method.
*
* @return the value of the client authentication method
*/
public String getValue() {
return this.value;
}

View File

@ -22,7 +22,7 @@ import java.util.Collections;
import java.util.Set;
/**
* An implementation of an {@link AbstractOAuth2Token} representing an <i>OAuth 2.0 Access Token</i>.
* An implementation of an {@link AbstractOAuth2Token} representing an OAuth 2.0 Access Token.
*
* <p>
* An access token is a credential that represents an authorization
@ -38,10 +38,27 @@ public class OAuth2AccessToken extends AbstractOAuth2Token {
private final TokenType tokenType;
private final Set<String> scopes;
/**
* Constructs an {@code OAuth2AccessToken} using the provided parameters.
*
* @param tokenType the token type
* @param tokenValue the token value
* @param issuedAt the time at which the token was issued
* @param expiresAt the expiration time on or after which the token MUST NOT be accepted
*/
public OAuth2AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt) {
this(tokenType, tokenValue, issuedAt, expiresAt, Collections.emptySet());
}
/**
* Constructs an {@code OAuth2AccessToken} using the provided parameters.
*
* @param tokenType the token type
* @param tokenValue the token value
* @param issuedAt the time at which the token was issued
* @param expiresAt the expiration time on or after which the token MUST NOT be accepted
* @param scopes the scope(s) associated to the token
*/
public OAuth2AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt, Set<String> scopes) {
super(tokenValue, issuedAt, expiresAt);
Assert.notNull(tokenType, "tokenType cannot be null");
@ -50,14 +67,29 @@ public class OAuth2AccessToken extends AbstractOAuth2Token {
scopes != null ? scopes : Collections.emptySet());
}
/**
* Returns the {@link TokenType token type}.
*
* @return the {@link TokenType}
*/
public TokenType getTokenType() {
return this.tokenType;
}
/**
* Returns the scope(s) associated to the token.
*
* @return the scope(s) associated to the token
*/
public Set<String> getScopes() {
return this.scopes;
}
/**
* Access Token Types.
*
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-7.1">Section 7.1 Access Token Types</a>
*/
public static final class TokenType {
public static final TokenType BEARER = new TokenType("Bearer");
private final String value;
@ -67,6 +99,11 @@ public class OAuth2AccessToken extends AbstractOAuth2Token {
this.value = value;
}
/**
* Returns the value of the token type.
*
* @return the value of the token type
*/
public String getValue() {
return this.value;
}

View File

@ -20,7 +20,7 @@ import org.springframework.security.core.AuthenticationException;
import org.springframework.util.Assert;
/**
* This exception is thrown for all <i>OAuth 2.0</i> related {@link Authentication} errors.
* This exception is thrown for all OAuth 2.0 related {@link Authentication} errors.
*
* <p>
* There are a number of scenarios where an error may occur, for example:
@ -40,20 +40,44 @@ import org.springframework.util.Assert;
public class OAuth2AuthenticationException extends AuthenticationException {
private OAuth2Error error;
/**
* Constructs an {@code OAuth2AuthenticationException} using the provided parameters.
*
* @param error the {@link OAuth2Error OAuth 2.0 Error}
* @param cause the root cause
*/
public OAuth2AuthenticationException(OAuth2Error error, Throwable cause) {
this(error, cause.getMessage(), cause);
}
/**
* Constructs an {@code OAuth2AuthenticationException} using the provided parameters.
*
* @param error the {@link OAuth2Error OAuth 2.0 Error}
* @param message the detail message
*/
public OAuth2AuthenticationException(OAuth2Error error, String message) {
super(message);
this.setError(error);
}
/**
* Constructs an {@code OAuth2AuthenticationException} using the provided parameters.
*
* @param error the {@link OAuth2Error OAuth 2.0 Error}
* @param message the detail message
* @param cause the root cause
*/
public OAuth2AuthenticationException(OAuth2Error error, String message, Throwable cause) {
super(message, cause);
this.setError(error);
}
/**
* Returns the {@link OAuth2Error OAuth 2.0 Error}.
*
* @return the {@link OAuth2Error}
*/
public OAuth2Error getError() {
return this.error;
}

View File

@ -21,16 +21,17 @@ import org.springframework.util.Assert;
import java.io.Serializable;
/**
* A representation of an <i>OAuth 2.0 Error</i>.
* A representation of an OAuth 2.0 Error.
*
* <p>
* At a minimum, an error response will contain an error code.
* The error code may be one of the standard codes defined by the specification,
* or a <i>new</i> code defined in the <i>OAuth Extensions Error Registry</i>,
* or a new code defined in the OAuth Extensions Error Registry,
* for cases where protocol extensions require additional error code(s) above the standard codes.
*
* @author Joe Grandja
* @since 5.0
* @see OAuth2ErrorCodes
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-11.4">Section 11.4 OAuth Extensions Error Registry</a>
*/
public final class OAuth2Error implements Serializable {
@ -39,10 +40,22 @@ public final class OAuth2Error implements Serializable {
private final String description;
private final String uri;
/**
* Constructs an {@code OAuth2Error} using the provided parameters.
*
* @param errorCode the error code
*/
public OAuth2Error(String errorCode) {
this(errorCode, null, null);
}
/**
* Constructs an {@code OAuth2Error} using the provided parameters.
*
* @param errorCode the error code
* @param description the error description
* @param uri the error uri
*/
public OAuth2Error(String errorCode, String description, String uri) {
Assert.hasText(errorCode, "errorCode cannot be empty");
this.errorCode = errorCode;
@ -50,14 +63,29 @@ public final class OAuth2Error implements Serializable {
this.uri = uri;
}
/**
* Returns the error code.
*
* @return the error code
*/
public String getErrorCode() {
return this.errorCode;
}
/**
* Returns the error description.
*
* @return the error description
*/
public String getDescription() {
return this.description;
}
/**
* Returns the error uri.
*
* @return the error uri
*/
public String getUri() {
return this.uri;
}

View File

@ -16,31 +16,80 @@
package org.springframework.security.oauth2.core;
/**
* Standard error codes defined by the <i>OAuth 2.0 Authorization Framework</i>.
* Standard error codes defined by the OAuth 2.0 Authorization Framework.
*
* @author Joe Grandja
* @since 5.0
*/
public interface OAuth2ErrorCodes {
/**
* {@code invalid_request} - The request is missing a required parameter,
* includes an invalid parameter value,
* includes a parameter more than once, or is otherwise malformed.
*/
String INVALID_REQUEST = "invalid_request";
/**
* {@code unauthorized_client} - The client is not authorized to request
* an authorization code or access token using this method.
*/
String UNAUTHORIZED_CLIENT = "unauthorized_client";
/**
* {@code access_denied} - The resource owner or authorization server denied the request.
*/
String ACCESS_DENIED = "access_denied";
/**
* {@code unsupported_response_type} - The authorization server does not support
* obtaining an authorization code or access token using this method.
*/
String UNSUPPORTED_RESPONSE_TYPE = "unsupported_response_type";
/**
* {@code invalid_scope} - The requested scope is invalid, unknown, malformed or
* exceeds the scope granted by the resource owner.
*/
String INVALID_SCOPE = "invalid_scope";
/**
* {@code server_error} - The authorization server encountered an
* unexpected condition that prevented it from fulfilling the request.
* (This error code is needed because a 500 Internal Server Error HTTP status code
* cannot be returned to the client via a HTTP redirect.)
*/
String SERVER_ERROR = "server_error";
/**
* {@code temporarily_unavailable} - The authorization server is currently unable
* to handle the request due to a temporary overloading or maintenance of the server.
* (This error code is needed because a 503 Service Unavailable HTTP status code
* cannot be returned to the client via an HTTP redirect.)
*/
String TEMPORARILY_UNAVAILABLE = "temporarily_unavailable";
/**
* {@code invalid_client} - Client authentication failed (e.g., unknown client,
* no client authentication included, or unsupported authentication method).
* The authorization server MAY return a HTTP 401 (Unauthorized) status code
* to indicate which HTTP authentication schemes are supported.
* If the client attempted to authenticate via the &quot;Authorization&quot; request header field,
* the authorization server MUST respond with a HTTP 401 (Unauthorized) status code and
* include the &quot;WWW-Authenticate&quot; response header field matching the authentication scheme used by the client.
*/
String INVALID_CLIENT = "invalid_client";
/**
* {@code invalid_grant} - The provided authorization grant
* (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked,
* does not match the redirection URI used in the authorization request, or was issued to another client.
*/
String INVALID_GRANT = "invalid_grant";
/**
* {@code unsupported_grant_type} - The authorization grant type is not supported by the authorization server.
*/
String UNSUPPORTED_GRANT_TYPE = "unsupported_grant_type";
}

View File

@ -24,7 +24,7 @@ import java.util.Map;
import java.util.Set;
/**
* A representation of an <i>OAuth 2.0 Access Token Response</i>.
* A representation of an OAuth 2.0 Access Token Response.
*
* @author Joe Grandja
* @since 5.0
@ -38,18 +38,37 @@ public final class OAuth2AccessTokenResponse {
private OAuth2AccessTokenResponse() {
}
/**
* Returns the {@link OAuth2AccessToken Access Token}.
*
* @return the {@link OAuth2AccessToken}
*/
public OAuth2AccessToken getAccessToken() {
return this.accessToken;
}
/**
* Returns the additional parameters returned in the response.
*
* @return a {@code Map} of the additional parameters returned in the response, may be empty.
*/
public Map<String, Object> getAdditionalParameters() {
return this.additionalParameters;
}
/**
* Returns a new {@link Builder}, initialized with the provided access token value.
*
* @param tokenValue the value of the access token
* @return the {@link Builder}
*/
public static Builder withToken(String tokenValue) {
return new Builder(tokenValue);
}
/**
* A builder for {@link OAuth2AccessTokenResponse}.
*/
public static class Builder {
private String tokenValue;
private OAuth2AccessToken.TokenType tokenType;
@ -61,26 +80,55 @@ public final class OAuth2AccessTokenResponse {
this.tokenValue = tokenValue;
}
/**
* Sets the {@link OAuth2AccessToken.TokenType token type}.
*
* @param tokenType the type of token issued
* @return the {@link Builder}
*/
public Builder tokenType(OAuth2AccessToken.TokenType tokenType) {
this.tokenType = tokenType;
return this;
}
/**
* Sets the lifetime (in seconds) of the access token.
*
* @param expiresIn the lifetime of the access token, in seconds.
* @return the {@link Builder}
*/
public Builder expiresIn(long expiresIn) {
this.expiresIn = expiresIn;
return this;
}
/**
* Sets the scope(s) associated to the access token.
*
* @param scopes the scope(s) associated to the access token.
* @return the {@link Builder}
*/
public Builder scopes(Set<String> scopes) {
this.scopes = scopes;
return this;
}
/**
* Sets the additional parameters returned in the response.
*
* @param additionalParameters the additional parameters returned in the response
* @return the {@link Builder}
*/
public Builder additionalParameters(Map<String, Object> additionalParameters) {
this.additionalParameters = additionalParameters;
return this;
}
/**
* Builds a new {@link OAuth2AccessTokenResponse}.
*
* @return a {@link OAuth2AccessTokenResponse}
*/
public OAuth2AccessTokenResponse build() {
Instant issuedAt = Instant.now();

View File

@ -18,7 +18,7 @@ package org.springframework.security.oauth2.core.endpoint;
import org.springframework.util.Assert;
/**
* An &quot;<i>exchange</i>&quot; of an <i>OAuth 2.0 Authorization Request and Response</i>
* An &quot;exchange&quot; of an OAuth 2.0 Authorization Request and Response
* for the authorization code grant type.
*
* @author Joe Grandja
@ -30,6 +30,13 @@ public final class OAuth2AuthorizationExchange {
private final OAuth2AuthorizationRequest authorizationRequest;
private final OAuth2AuthorizationResponse authorizationResponse;
/**
* Constructs a new {@code OAuth2AuthorizationExchange} with the provided
* Authorization Request and Authorization Response.
*
* @param authorizationRequest the {@link OAuth2AuthorizationRequest Authorization Request}
* @param authorizationResponse the {@link OAuth2AuthorizationResponse Authorization Response}
*/
public OAuth2AuthorizationExchange(OAuth2AuthorizationRequest authorizationRequest,
OAuth2AuthorizationResponse authorizationResponse) {
Assert.notNull(authorizationRequest, "authorizationRequest cannot be null");
@ -38,10 +45,20 @@ public final class OAuth2AuthorizationExchange {
this.authorizationResponse = authorizationResponse;
}
/**
* Returns the {@link OAuth2AuthorizationRequest Authorization Request}.
*
* @return the {@link OAuth2AuthorizationRequest}
*/
public OAuth2AuthorizationRequest getAuthorizationRequest() {
return this.authorizationRequest;
}
/**
* Returns the {@link OAuth2AuthorizationResponse Authorization Response}.
*
* @return the {@link OAuth2AuthorizationResponse}
*/
public OAuth2AuthorizationResponse getAuthorizationResponse() {
return this.authorizationResponse;
}

View File

@ -30,7 +30,7 @@ import java.util.Set;
import java.util.stream.Collectors;
/**
* A representation of an <i>OAuth 2.0 Authorization Request</i>
* A representation of an OAuth 2.0 Authorization Request
* for the authorization code grant type or implicit grant type.
*
* @author Joe Grandja
@ -54,46 +54,99 @@ public final class OAuth2AuthorizationRequest implements Serializable {
private OAuth2AuthorizationRequest() {
}
/**
* Returns the uri for the authorization endpoint.
*
* @return the uri for the authorization endpoint
*/
public String getAuthorizationUri() {
return this.authorizationUri;
}
/**
* Returns the {@link AuthorizationGrantType grant type}.
*
* @return the {@link AuthorizationGrantType}
*/
public AuthorizationGrantType getGrantType() {
return this.authorizationGrantType;
}
/**
* Returns the {@link OAuth2AuthorizationResponseType response type}.
*
* @return the {@link OAuth2AuthorizationResponseType}
*/
public OAuth2AuthorizationResponseType getResponseType() {
return this.responseType;
}
/**
* Returns the client identifier.
*
* @return the client identifier
*/
public String getClientId() {
return this.clientId;
}
/**
* Returns the uri for the redirect endpoint.
*
* @return the uri for the redirect endpoint
*/
public String getRedirectUri() {
return this.redirectUri;
}
/**
* Returns the scope(s).
*
* @return the scope(s)
*/
public Set<String> getScopes() {
return this.scopes;
}
/**
* Returns the state.
*
* @return the state
*/
public String getState() {
return this.state;
}
/**
* Returns the additional parameters used in the request.
*
* @return a {@code Map} of the additional parameters used in the request
*/
public Map<String, Object> getAdditionalParameters() {
return this.additionalParameters;
}
/**
* Returns a new {@link Builder}, initialized with the authorization code grant type.
*
* @return the {@link Builder}
*/
public static Builder authorizationCode() {
return new Builder(AuthorizationGrantType.AUTHORIZATION_CODE);
}
/**
* Returns a new {@link Builder}, initialized with the implicit grant type.
*
* @return the {@link Builder}
*/
public static Builder implicit() {
return new Builder(AuthorizationGrantType.IMPLICIT);
}
/**
* A builder for {@link OAuth2AuthorizationRequest}.
*/
public static class Builder {
private String authorizationUri;
private AuthorizationGrantType authorizationGrantType;
@ -114,21 +167,45 @@ public final class OAuth2AuthorizationRequest implements Serializable {
}
}
/**
* Sets the uri for the authorization endpoint.
*
* @param authorizationUri the uri for the authorization endpoint
* @return the {@link Builder}
*/
public Builder authorizationUri(String authorizationUri) {
this.authorizationUri = authorizationUri;
return this;
}
/**
* Sets the client identifier.
*
* @param clientId the client identifier
* @return the {@link Builder}
*/
public Builder clientId(String clientId) {
this.clientId = clientId;
return this;
}
/**
* Sets the uri for the redirect endpoint.
*
* @param redirectUri the uri for the redirect endpoint
* @return the {@link Builder}
*/
public Builder redirectUri(String redirectUri) {
this.redirectUri = redirectUri;
return this;
}
/**
* Sets the scope(s).
*
* @param scope the scope(s)
* @return the {@link Builder}
*/
public Builder scope(String... scope) {
if (scope != null && scope.length > 0) {
return this.scopes(Arrays.stream(scope).collect(
@ -137,21 +214,44 @@ public final class OAuth2AuthorizationRequest implements Serializable {
return this;
}
/**
* Sets the scope(s).
*
* @param scopes the scope(s)
* @return the {@link Builder}
*/
public Builder scopes(Set<String> scopes) {
this.scopes = scopes;
return this;
}
/**
* Sets the state.
*
* @param state the state
* @return the {@link Builder}
*/
public Builder state(String state) {
this.state = state;
return this;
}
/**
* Sets the additional parameters used in the request.
*
* @param additionalParameters the additional parameters used in the request
* @return the {@link Builder}
*/
public Builder additionalParameters(Map<String, Object> additionalParameters) {
this.additionalParameters = additionalParameters;
return this;
}
/**
* Builds a new {@link OAuth2AuthorizationRequest}.
*
* @return a {@link OAuth2AuthorizationRequest}
*/
public OAuth2AuthorizationRequest build() {
Assert.hasText(this.authorizationUri, "authorizationUri cannot be empty");
Assert.hasText(this.clientId, "clientId cannot be empty");

View File

@ -20,10 +20,11 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* A representation of an <i>OAuth 2.0 Authorization Response</i> for the authorization code grant type.
* A representation of an OAuth 2.0 Authorization Response for the authorization code grant type.
*
* @author Joe Grandja
* @since 5.0
* @see OAuth2Error
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1.2">Section 4.1.2 Authorization Response</a>
*/
public final class OAuth2AuthorizationResponse {
@ -35,40 +36,85 @@ public final class OAuth2AuthorizationResponse {
private OAuth2AuthorizationResponse() {
}
/**
* Returns the uri where the response was redirected to.
*
* @return the uri where the response was redirected to
*/
public String getRedirectUri() {
return this.redirectUri;
}
/**
* Returns the state.
*
* @return the state
*/
public String getState() {
return this.state;
}
/**
* Returns the authorization code.
*
* @return the authorization code
*/
public String getCode() {
return this.code;
}
/**
* Returns the {@link OAuth2Error OAuth 2.0 Error} if the Authorization Request failed, otherwise {@code null}.
*
* @return the {@link OAuth2Error} if the Authorization Request failed, otherwise {@code null}
*/
public OAuth2Error getError() {
return this.error;
}
/**
* Returns {@code true} if the Authorization Request succeeded, otherwise {@code false}.
*
* @return {@code true} if the Authorization Request succeeded, otherwise {@code false}
*/
public boolean statusOk() {
return !this.statusError();
}
/**
* Returns {@code true} if the Authorization Request failed, otherwise {@code false}.
*
* @return {@code true} if the Authorization Request failed, otherwise {@code false}
*/
public boolean statusError() {
return (this.error != null && this.error.getErrorCode() != null);
}
/**
* Returns a new {@link Builder}, initialized with the authorization code.
*
* @param code the authorization code
* @return the {@link Builder}
*/
public static Builder success(String code) {
Assert.hasText(code, "code cannot be empty");
return new Builder().code(code);
}
/**
* Returns a new {@link Builder}, initialized with the error code.
*
* @param errorCode the error code
* @return the {@link Builder}
*/
public static Builder error(String errorCode) {
Assert.hasText(errorCode, "errorCode cannot be empty");
return new Builder().errorCode(errorCode);
}
/**
* A builder for {@link OAuth2AuthorizationResponse}.
*/
public static class Builder {
private String redirectUri;
private String state;
@ -80,36 +126,77 @@ public final class OAuth2AuthorizationResponse {
private Builder() {
}
/**
* Sets the uri where the response was redirected to.
*
* @param redirectUri the uri where the response was redirected to
* @return the {@link Builder}
*/
public Builder redirectUri(String redirectUri) {
this.redirectUri = redirectUri;
return this;
}
/**
* Sets the state.
*
* @param state the state
* @return the {@link Builder}
*/
public Builder state(String state) {
this.state = state;
return this;
}
/**
* Sets the authorization code.
*
* @param code the authorization code
* @return the {@link Builder}
*/
public Builder code(String code) {
this.code = code;
return this;
}
/**
* Sets the error code.
*
* @param errorCode the error code
* @return the {@link Builder}
*/
public Builder errorCode(String errorCode) {
this.errorCode = errorCode;
return this;
}
/**
* Sets the error description.
*
* @param errorDescription the error description
* @return the {@link Builder}
*/
public Builder errorDescription(String errorDescription) {
this.errorDescription = errorDescription;
return this;
}
/**
* Sets the error uri.
*
* @param errorUri the error uri
* @return the {@link Builder}
*/
public Builder errorUri(String errorUri) {
this.errorUri = errorUri;
return this;
}
/**
* Builds a new {@link OAuth2AuthorizationResponse}.
*
* @return a {@link OAuth2AuthorizationResponse}
*/
public OAuth2AuthorizationResponse build() {
if (StringUtils.hasText(this.code) && StringUtils.hasText(this.errorCode)) {
throw new IllegalArgumentException("code and errorCode cannot both be set");

View File

@ -21,12 +21,12 @@ import org.springframework.util.Assert;
import java.io.Serializable;
/**
* The <i>response_type</i> parameter is consumed by the authorization endpoint which
* The {@code response_type} parameter is consumed by the authorization endpoint which
* is used by the authorization code grant type and implicit grant type.
* The client sets the <i>response_type</i> parameter with the desired grant type before initiating the authorization request.
* The client sets the {@code response_type} parameter with the desired grant type before initiating the authorization request.
*
* <p>
* The <i>response_type</i> parameter value may be one of &quot;code&quot; for requesting an authorization code or
* The {@code response_type} parameter value may be one of &quot;code&quot; for requesting an authorization code or
* &quot;token&quot; for requesting an access token (implicit grant).
* @author Joe Grandja
@ -44,6 +44,11 @@ public final class OAuth2AuthorizationResponseType implements Serializable {
this.value = value;
}
/**
* Returns the value of the authorization response type.
*
* @return the value of the authorization response type
*/
public String getValue() {
return this.value;
}

View File

@ -16,7 +16,7 @@
package org.springframework.security.oauth2.core.endpoint;
/**
* Standard and additional (custom) parameter names defined in the OAuth Parameters Registry
* Standard and custom (non-standard) parameter names defined in the OAuth Parameters Registry
* and used by the authorization endpoint and token endpoint.
*
* @author Joe Grandja
@ -25,24 +25,54 @@ package org.springframework.security.oauth2.core.endpoint;
*/
public interface OAuth2ParameterNames {
/**
* {@code response_type} - used in Authorization Request.
*/
String RESPONSE_TYPE = "response_type";
/**
* {@code client_id} - used in Authorization Request and Access Token Request.
*/
String CLIENT_ID = "client_id";
/**
* {@code redirect_uri} - used in Authorization Request and Access Token Request.
*/
String REDIRECT_URI = "redirect_uri";
/**
* {@code scope} - used in Authorization Request, Authorization Response, Access Token Request and Access Token Response.
*/
String SCOPE = "scope";
/**
* {@code state} - used in Authorization Request and Authorization Response.
*/
String STATE = "state";
/**
* {@code code} - used in Authorization Response and Access Token Request.
*/
String CODE = "code";
/**
* {@code error} - used in Authorization Response and Access Token Response.
*/
String ERROR = "error";
/**
* {@code error_description} - used in Authorization Response and Access Token Response.
*/
String ERROR_DESCRIPTION = "error_description";
/**
* {@code error_uri} - used in Authorization Response and Access Token Response.
*/
String ERROR_URI = "error_uri";
String REGISTRATION_ID = "registration_id"; // Non-standard additional parameter
/**
* Non-standard parameter (used internally).
*/
String REGISTRATION_ID = "registration_id";
}

View File

@ -14,8 +14,7 @@
* limitations under the License.
*/
/**
* Support classes that model the request/response messages from the
* <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-3.1">Authorization Endpoint</a>
* and <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-3.2">Token Endpoint</a>.
* Support classes that model the OAuth 2.0 Request and Response messages
* from the Authorization Endpoint and Token Endpoint.
*/
package org.springframework.security.oauth2.core.endpoint;

View File

@ -16,8 +16,8 @@
package org.springframework.security.oauth2.core.oidc;
/**
* The Address Claim represents a physical mailing address defined by the <i>OpenID Connect Core 1.0</i> specification
* that can be returned either in the <i>UserInfo Response</i> or the <i>ID Token</i>.
* The Address Claim represents a physical mailing address defined by the OpenID Connect Core 1.0 specification
* that can be returned either in the UserInfo Response or the ID Token.
*
* @author Joe Grandja
* @since 5.0
@ -27,16 +27,46 @@ package org.springframework.security.oauth2.core.oidc;
*/
public interface AddressStandardClaim {
/**
* Returns the full mailing address, formatted for display.
*
* @return the full mailing address
*/
String getFormatted();
/**
* Returns the full street address, which may include house number, street name, P.O. Box, etc.
*
* @return the full street address
*/
String getStreetAddress();
/**
* Returns the city or locality.
*
* @return the city or locality
*/
String getLocality();
/**
* Returns the state, province, prefecture, or region.
*
* @return the state, province, prefecture, or region
*/
String getRegion();
/**
* Returns the zip code or postal code.
*
* @return the zip code or postal code
*/
String getPostalCode();
/**
* Returns the country.
*
* @return the country
*/
String getCountry();
}

View File

@ -105,6 +105,9 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim {
return result;
}
/**
* A builder for {@link DefaultAddressStandardClaim}.
*/
public static class Builder {
private static final String FORMATTED_FIELD_NAME = "formatted";
private static final String STREET_ADDRESS_FIELD_NAME = "street_address";
@ -119,9 +122,17 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim {
private String postalCode;
private String country;
/**
* Default constructor.
*/
public Builder() {
}
/**
* Constructs and initializes the address attributes using the provided {@code addressFields}.
*
* @param addressFields the fields used to initialize the address attributes
*/
public Builder(Map<String, Object> addressFields) {
this.formatted((String) addressFields.get(FORMATTED_FIELD_NAME));
this.streetAddress((String) addressFields.get(STREET_ADDRESS_FIELD_NAME));
@ -131,36 +142,77 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim {
this.country((String) addressFields.get(COUNTRY_FIELD_NAME));
}
/**
* Sets the full mailing address, formatted for display.
*
* @param formatted the full mailing address
* @return the {@link Builder}
*/
public Builder formatted(String formatted) {
this.formatted = formatted;
return this;
}
/**
* Sets the full street address, which may include house number, street name, P.O. Box, etc.
*
* @param streetAddress the full street address
* @return the {@link Builder}
*/
public Builder streetAddress(String streetAddress) {
this.streetAddress = streetAddress;
return this;
}
/**
* Sets the city or locality.
*
* @param locality the city or locality
* @return the {@link Builder}
*/
public Builder locality(String locality) {
this.locality = locality;
return this;
}
/**
* Sets the state, province, prefecture, or region.
*
* @param region the state, province, prefecture, or region
* @return the {@link Builder}
*/
public Builder region(String region) {
this.region = region;
return this;
}
/**
* Sets the zip code or postal code.
*
* @param postalCode the zip code or postal code
* @return the {@link Builder}
*/
public Builder postalCode(String postalCode) {
this.postalCode = postalCode;
return this;
}
/**
* Sets the country.
*
* @param country the country
* @return the {@link Builder}
*/
public Builder country(String country) {
this.country = country;
return this;
}
/**
* Builds a new {@link DefaultAddressStandardClaim}.
*
* @return a {@link AddressStandardClaim}
*/
public AddressStandardClaim build() {
DefaultAddressStandardClaim address = new DefaultAddressStandardClaim();
address.formatted = this.formatted;

View File

@ -22,7 +22,7 @@ import java.time.Instant;
import java.util.List;
/**
* A {@link ClaimAccessor} for the &quot;Claims&quot; that can be returned in the <i>ID Token</i>
* A {@link ClaimAccessor} for the &quot;claims&quot; that can be returned in the ID Token,
* which provides information about the authentication of an End-User by an Authorization Server.
*
* @see ClaimAccessor
@ -37,50 +37,111 @@ import java.util.List;
*/
public interface IdTokenClaimAccessor extends StandardClaimAccessor {
/**
* Returns the Issuer identifier {@code (iss)}.
*
* @return the Issuer identifier
*/
default URL getIssuer() {
return this.getClaimAsURL(IdTokenClaimNames.ISS);
}
/**
* Returns the Subject identifier {@code (sub)}.
*
* @return the Subject identifier
*/
default String getSubject() {
return this.getClaimAsString(IdTokenClaimNames.SUB);
}
/**
* Returns the Audience(s) {@code (aud)} that this ID Token is intended for.
*
* @return the Audience(s) that this ID Token is intended for
*/
default List<String> getAudience() {
return this.getClaimAsStringList(IdTokenClaimNames.AUD);
}
/**
* Returns the Expiration time {@code (exp)} on or after which the ID Token MUST NOT be accepted.
*
* @return the Expiration time on or after which the ID Token MUST NOT be accepted
*/
default Instant getExpiresAt() {
return this.getClaimAsInstant(IdTokenClaimNames.EXP);
}
/**
* Returns the time at which the ID Token was issued {@code (iat)}.
*
* @return the time at which the ID Token was issued
*/
default Instant getIssuedAt() {
return this.getClaimAsInstant(IdTokenClaimNames.IAT);
}
/**
* Returns the time when the End-User authentication occurred {@code (auth_time)}.
*
* @return the time when the End-User authentication occurred
*/
default Instant getAuthenticatedAt() {
return this.getClaimAsInstant(IdTokenClaimNames.AUTH_TIME);
}
/**
* Returns a {@code String} value {@code (nonce)} used to associate a Client session with an ID Token,
* and to mitigate replay attacks.
*
* @return the nonce used to associate a Client session with an ID Token
*/
default String getNonce() {
return this.getClaimAsString(IdTokenClaimNames.NONCE);
}
/**
* Returns the Authentication Context Class Reference {@code (acr)}.
*
* @return the Authentication Context Class Reference
*/
default String getAuthenticationContextClass() {
return this.getClaimAsString(IdTokenClaimNames.ACR);
}
/**
* Returns the Authentication Methods References {@code (amr)}.
*
* @return the Authentication Methods References
*/
default List<String> getAuthenticationMethods() {
return this.getClaimAsStringList(IdTokenClaimNames.AMR);
}
/**
* Returns the Authorized party {@code (azp)} to which the ID Token was issued.
*
* @return the Authorized party to which the ID Token was issued
*/
default String getAuthorizedParty() {
return this.getClaimAsString(IdTokenClaimNames.AZP);
}
/**
* Returns the Access Token hash value {@code (at_hash)}.
*
* @return the Access Token hash value
*/
default String getAccessTokenHash() {
return this.getClaimAsString(IdTokenClaimNames.AT_HASH);
}
/**
* Returns the Authorization Code hash value {@code (c_hash)}.
*
* @return the Authorization Code hash value
*/
default String getAuthorizationCodeHash() {
return this.getClaimAsString(IdTokenClaimNames.C_HASH);
}

View File

@ -16,8 +16,8 @@
package org.springframework.security.oauth2.core.oidc;
/**
* The names of the &quot;Claims&quot; defined by the <i>OpenID Connect Core 1.0</i> specification
* that can be returned in the <i>ID Token</i>.
* The names of the &quot;claims&quot; defined by the OpenID Connect Core 1.0 specification
* that can be returned in the ID Token.
*
* @author Joe Grandja
* @since 5.0
@ -27,28 +27,65 @@ package org.springframework.security.oauth2.core.oidc;
public interface IdTokenClaimNames {
/**
* {@code iss} - the Issuer identifier
*/
String ISS = "iss";
/**
* {@code sub} - the Subject identifier
*/
String SUB = "sub";
/**
* {@code aud} - the Audience(s) that the ID Token is intended for
*/
String AUD = "aud";
/**
* {@code exp} - the Expiration time on or after which the ID Token MUST NOT be accepted
*/
String EXP = "exp";
/**
* {@code iat} - the time at which the ID Token was issued
*/
String IAT = "iat";
/**
* {@code auth_time} - the time when the End-User authentication occurred
*/
String AUTH_TIME = "auth_time";
/**
* {@code nonce} - a {@code String} value used to associate a Client session with an ID Token,
* and to mitigate replay attacks.
*/
String NONCE = "nonce";
/**
* {@code acr} - the Authentication Context Class Reference
*/
String ACR = "acr";
/**
* {@code amr} - the Authentication Methods References
*/
String AMR = "amr";
/**
* {@code azp} - the Authorized party to which the ID Token was issued
*/
String AZP = "azp";
/**
* {@code at_hash} - the Access Token hash value
*/
String AT_HASH = "at_hash";
/**
* {@code c_hash} - the Authorization Code hash value
*/
String C_HASH = "c_hash";
}

View File

@ -24,10 +24,10 @@ import java.util.LinkedHashMap;
import java.util.Map;
/**
* An implementation of an {@link AbstractOAuth2Token} representing an <i>OpenID Connect Core 1.0 ID Token</i>.
* An implementation of an {@link AbstractOAuth2Token} representing an OpenID Connect Core 1.0 ID Token.
*
* <p>
* The <code>OidcIdToken</code> is a security token that contains &quot;Claims&quot;
* The {@code OidcIdToken} is a security token that contains &quot;claims&quot;
* about the authentication of an End-User by an Authorization Server.
*
* @author Joe Grandja
@ -41,6 +41,14 @@ import java.util.Map;
public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAccessor {
private final Map<String, Object> claims;
/**
* Constructs a {@code OidcIdToken} using the provided parameters.
*
* @param tokenValue the ID Token value
* @param issuedAt the time at which the ID Token was issued {@code (iat)}
* @param expiresAt the expiration time {@code (exp)} on or after which the ID Token MUST NOT be accepted
* @param claims the claims about the authentication of the End-User
*/
public OidcIdToken(String tokenValue, Instant issuedAt, Instant expiresAt, Map<String, Object> claims) {
super(tokenValue, issuedAt, expiresAt);
Assert.notEmpty(claims, "claims cannot be empty");

View File

@ -18,12 +18,12 @@ package org.springframework.security.oauth2.core.oidc;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
/**
* The <i>scope</i> values defined by the <i>OpenID Connect Core 1.0</i> specification
* that can be used to request {@link StandardClaimNames Claims}.
* The scope values defined by the OpenID Connect Core 1.0 specification
* that can be used to request {@link StandardClaimNames claims}.
* <p>
* The scope(s) associated to an {@link OAuth2AccessToken} determine what claims (resources)
* will be available when they are used to access <i>OAuth 2.0 Protected Endpoints</i>,
* such as the <i>UserInfo Endpoint</i>.
* will be available when they are used to access OAuth 2.0 Protected Endpoints,
* such as the UserInfo Endpoint.
*
* @author Joe Grandja
* @since 5.0
@ -32,14 +32,31 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken;
*/
public interface OidcScopes {
/**
* The {@code openid} scope is required for OpenID Connect Authentication Requests.
*/
String OPENID = "openid";
/**
* The {@code profile} scope requests access to the default profile claims, which are:
* {@code name, family_name, given_name, middle_name, nickname, preferred_username,
* profile, picture, website, gender, birthdate, zoneinfo, locale, updated_at}.
*/
String PROFILE = "profile";
/**
* The {@code email} scope requests access to the {@code email} and {@code email_verified} claims.
*/
String EMAIL = "email";
/**
* The {@code address} scope requests access to the {@code address} claim.
*/
String ADDRESS = "address";
/**
* The {@code phone} scope requests access to the {@code phone_number} and {@code phone_number_verified} claims.
*/
String PHONE = "phone";
}

View File

@ -24,11 +24,11 @@ import java.util.LinkedHashMap;
import java.util.Map;
/**
* A representation of a <i>UserInfo Response</i> that is returned
* from the OAuth 2.0 Protected Resource <i>UserInfo Endpoint</i>.
* A representation of a UserInfo Response that is returned
* from the OAuth 2.0 Protected Resource UserInfo Endpoint.
*
* <p>
* The <code>OidcUserInfo</code> contains a set of &quot;Standard Claims&quot; about the authentication of an End-User.
* The {@code OidcUserInfo} contains a set of &quot;Standard Claims&quot; about the authentication of an End-User.
*
* @author Joe Grandja
* @since 5.0
@ -41,6 +41,11 @@ public class OidcUserInfo implements StandardClaimAccessor, Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final Map<String, Object> claims;
/**
* Constructs a {@code OidcUserInfo} using the provided parameters.
*
* @param claims the claims about the authentication of the End-User
*/
public OidcUserInfo(Map<String, Object> claims) {
Assert.notEmpty(claims, "claims cannot be empty");
this.claims = Collections.unmodifiableMap(new LinkedHashMap<>(claims));

View File

@ -23,7 +23,7 @@ import java.util.Map;
/**
* A {@link ClaimAccessor} for the &quot;Standard Claims&quot; that can be returned
* either in the <i>UserInfo Response</i> or the <i>ID Token</i>.
* either in the UserInfo Response or the ID Token.
*
* @see ClaimAccessor
* @see StandardClaimNames
@ -35,78 +35,173 @@ import java.util.Map;
*/
public interface StandardClaimAccessor extends ClaimAccessor {
/**
* Returns the Subject identifier {@code (sub)}.
*
* @return the Subject identifier
*/
default String getSubject() {
return this.getClaimAsString(StandardClaimNames.SUB);
}
/**
* Returns the user's full name {@code (name)} in displayable form.
*
* @return the user's full name
*/
default String getFullName() {
return this.getClaimAsString(StandardClaimNames.NAME);
}
/**
* Returns the user's given name(s) or first name(s) {@code (given_name)}.
*
* @return the user's given name(s)
*/
default String getGivenName() {
return this.getClaimAsString(StandardClaimNames.GIVEN_NAME);
}
/**
* Returns the user's surname(s) or last name(s) {@code (family_name)}.
*
* @return the user's family names(s)
*/
default String getFamilyName() {
return this.getClaimAsString(StandardClaimNames.FAMILY_NAME);
}
/**
* Returns the user's middle name(s) {@code (middle_name)}.
*
* @return the user's middle name(s)
*/
default String getMiddleName() {
return this.getClaimAsString(StandardClaimNames.MIDDLE_NAME);
}
/**
* Returns the user's nick name {@code (nickname)} that may or may not be the same as the {@code (given_name)}.
*
* @return the user's nick name
*/
default String getNickName() {
return this.getClaimAsString(StandardClaimNames.NICKNAME);
}
/**
* Returns the preferred username {@code (preferred_username)} that the user wishes to be referred to.
*
* @return the user's preferred user name
*/
default String getPreferredUsername() {
return this.getClaimAsString(StandardClaimNames.PREFERRED_USERNAME);
}
/**
* Returns the URL of the user's profile page {@code (profile)}.
*
* @return the URL of the user's profile page
*/
default String getProfile() {
return this.getClaimAsString(StandardClaimNames.PROFILE);
}
/**
* Returns the URL of the user's profile picture {@code (picture)}.
*
* @return the URL of the user's profile picture
*/
default String getPicture() {
return this.getClaimAsString(StandardClaimNames.PICTURE);
}
/**
* Returns the URL of the user's web page or blog {@code (website)}.
*
* @return the URL of the user's web page or blog
*/
default String getWebsite() {
return this.getClaimAsString(StandardClaimNames.WEBSITE);
}
/**
* Returns the user's preferred e-mail address {@code (email)}.
*
* @return the user's preferred e-mail address
*/
default String getEmail() {
return this.getClaimAsString(StandardClaimNames.EMAIL);
}
/**
* Returns {@code true} if the user's e-mail address has been verified {@code (email_verified)}, otherwise {@code false}.
*
* @return {@code true} if the user's e-mail address has been verified, otherwise {@code false}
*/
default Boolean getEmailVerified() {
return this.getClaimAsBoolean(StandardClaimNames.EMAIL_VERIFIED);
}
/**
* Returns the user's gender {@code (gender)}.
*
* @return the user's gender
*/
default String getGender() {
return this.getClaimAsString(StandardClaimNames.GENDER);
}
/**
* Returns the user's birth date {@code (birthdate)}.
*
* @return the user's birth date
*/
default String getBirthdate() {
return this.getClaimAsString(StandardClaimNames.BIRTHDATE);
}
/**
* Returns the user's time zone {@code (zoneinfo)}.
*
* @return the user's time zone
*/
default String getZoneInfo() {
return this.getClaimAsString(StandardClaimNames.ZONEINFO);
}
/**
* Returns the user's locale {@code (locale)}.
*
* @return the user's locale
*/
default String getLocale() {
return this.getClaimAsString(StandardClaimNames.LOCALE);
}
/**
* Returns the user's preferred phone number {@code (phone_number)}.
*
* @return the user's preferred phone number
*/
default String getPhoneNumber() {
return this.getClaimAsString(StandardClaimNames.PHONE_NUMBER);
}
/**
* Returns {@code true} if the user's phone number has been verified {@code (phone_number_verified)}, otherwise {@code false}.
*
* @return {@code true} if the user's phone number has been verified, otherwise {@code false}
*/
default Boolean getPhoneNumberVerified() {
return this.getClaimAsBoolean(StandardClaimNames.PHONE_NUMBER_VERIFIED);
}
/**
* Returns the user's preferred postal address {@code (address)}.
*
* @return the user's preferred postal address
*/
default AddressStandardClaim getAddress() {
Map<String, Object> addressFields = this.getClaimAsMap(StandardClaimNames.ADDRESS);
return (!CollectionUtils.isEmpty(addressFields) ?
@ -114,6 +209,11 @@ public interface StandardClaimAccessor extends ClaimAccessor {
new DefaultAddressStandardClaim.Builder().build());
}
/**
* Returns the time the user's information was last updated {@code (updated_at)}.
*
* @return the time the user's information was last updated
*/
default Instant getUpdatedAt() {
return this.getClaimAsInstant(StandardClaimNames.UPDATED_AT);
}

View File

@ -16,8 +16,8 @@
package org.springframework.security.oauth2.core.oidc;
/**
* The names of the &quot;Standard Claims&quot; defined by the <i>OpenID Connect Core 1.0</i> specification
* that can be returned either in the <i>UserInfo Response</i> or the <i>ID Token</i>.
* The names of the &quot;Standard Claims&quot; defined by the OpenID Connect Core 1.0 specification
* that can be returned either in the UserInfo Response or the ID Token.
*
* @author Joe Grandja
* @since 5.0
@ -27,44 +27,104 @@ package org.springframework.security.oauth2.core.oidc;
*/
public interface StandardClaimNames {
/**
* {@code sub} - the Subject identifier
*/
String SUB = "sub";
/**
* {@code name} - the user's full name
*/
String NAME = "name";
/**
* {@code given_name} - the user's given name(s) or first name(s)
*/
String GIVEN_NAME = "given_name";
/**
* {@code family_name} - the user's surname(s) or last name(s)
*/
String FAMILY_NAME = "family_name";
/**
* {@code middle_name} - the user's middle name(s)
*/
String MIDDLE_NAME = "middle_name";
/**
* {@code nickname} - the user's nick name that may or may not be the same as the {@code given_name}
*/
String NICKNAME = "nickname";
/**
* {@code preferred_username} - the preferred username that the user wishes to be referred to
*/
String PREFERRED_USERNAME = "preferred_username";
/**
* {@code profile} - the URL of the user's profile page
*/
String PROFILE = "profile";
/**
* {@code picture} - the URL of the user's profile picture
*/
String PICTURE = "picture";
/**
* {@code website} - the URL of the user's web page or blog
*/
String WEBSITE = "website";
/**
* {@code email} - the user's preferred e-mail address
*/
String EMAIL = "email";
/**
* {@code email_verified} - {@code true} if the user's e-mail address has been verified, otherwise {@code false}
*/
String EMAIL_VERIFIED = "email_verified";
/**
* {@code gender} - the user's gender
*/
String GENDER = "gender";
/**
* {@code birthdate} - the user's birth date
*/
String BIRTHDATE = "birthdate";
/**
* {@code zoneinfo} - the user's time zone
*/
String ZONEINFO = "zoneinfo";
/**
* {@code locale} - the user's locale
*/
String LOCALE = "locale";
/**
* {@code phone_number} - the user's preferred phone number
*/
String PHONE_NUMBER = "phone_number";
/**
* {@code phone_number_verified} - {@code true} if the user's phone number has been verified, otherwise {@code false}
*/
String PHONE_NUMBER_VERIFIED = "phone_number_verified";
/**
* {@code address} - the user's preferred postal address
*/
String ADDRESS = "address";
/**
* {@code updated_at} - the time the user's information was last updated
*/
String UPDATED_AT = "updated_at";
}

View File

@ -25,6 +25,9 @@ package org.springframework.security.oauth2.core.oidc.endpoint;
*/
public interface OidcParameterNames {
/**
* {@code id_token} - used in the Access Token Response.
*/
String ID_TOKEN = "id_token";
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2002-2017 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
*
* http://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.
*/
/**
* Support classes that model the OpenID Connect Core 1.0 Request and Response messages
* from the Authorization Endpoint and Token Endpoint.
*/
package org.springframework.security.oauth2.core.oidc.endpoint;

View File

@ -14,6 +14,6 @@
* limitations under the License.
*/
/**
* Core classes and interfaces providing support for <i>OpenID Connect Core 1.0</i>.
* Core classes and interfaces providing support for OpenID Connect Core 1.0.
*/
package org.springframework.security.oauth2.core.oidc;

View File

@ -17,10 +17,10 @@
package org.springframework.security.oauth2.core.oidc.user;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
import java.util.Map;
import java.util.Set;
@ -29,9 +29,8 @@ import java.util.Set;
* The default implementation of an {@link OidcUser}.
*
* <p>
* The claim used for accessing the &quot;name&quot; of the
* user <code>Principal</code> via {@link #getClaims()}
* is {@link IdTokenClaimNames#SUB}.
* The default claim used for accessing the &quot;name&quot; of the
* user {@code Principal} from {@link #getClaims()} is {@link IdTokenClaimNames#SUB}.
*
* @author Joe Grandja
* @author Vedran Pavic
@ -45,18 +44,46 @@ public class DefaultOidcUser extends DefaultOAuth2User implements OidcUser {
private final OidcIdToken idToken;
private final OidcUserInfo userInfo;
/**
* Constructs a {@code DefaultOidcUser} using the provided parameters.
*
* @param authorities the authorities granted to the user
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
*/
public DefaultOidcUser(Set<GrantedAuthority> authorities, OidcIdToken idToken) {
this(authorities, idToken, IdTokenClaimNames.SUB);
}
/**
* Constructs a {@code DefaultOidcUser} using the provided parameters.
*
* @param authorities the authorities granted to the user
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
* @param nameAttributeKey the key used to access the user's &quot;name&quot; from {@link #getAttributes()}
*/
public DefaultOidcUser(Set<GrantedAuthority> authorities, OidcIdToken idToken, String nameAttributeKey) {
this(authorities, idToken, null, nameAttributeKey);
}
/**
* Constructs a {@code DefaultOidcUser} using the provided parameters.
*
* @param authorities the authorities granted to the user
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
* @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null}
*/
public DefaultOidcUser(Set<GrantedAuthority> authorities, OidcIdToken idToken, OidcUserInfo userInfo) {
this(authorities, idToken, userInfo, IdTokenClaimNames.SUB);
}
/**
* Constructs a {@code DefaultOidcUser} using the provided parameters.
*
* @param authorities the authorities granted to the user
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
* @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null}
* @param nameAttributeKey the key used to access the user's &quot;name&quot; from {@link #getAttributes()}
*/
public DefaultOidcUser(Set<GrantedAuthority> authorities, OidcIdToken idToken, OidcUserInfo userInfo,
String nameAttributeKey) {
super(authorities, OidcUserAuthority.collectClaims(idToken, userInfo), nameAttributeKey);

View File

@ -26,12 +26,12 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
import java.util.Map;
/**
* A representation of a user <code>Principal</code>
* that is registered with an <i>OpenID Connect 1.0 Provider</i>.
* A representation of a user {@code Principal}
* that is registered with an OpenID Connect 1.0 Provider.
*
* <p>
* An <code>OidcUser</code> contains &quot;Claims&quot; about the Authentication of the End-User.
* The claims are aggregated from the <code>OidcIdToken</code> and optionally the <code>OidcUserInfo</code>.
* An {@code OidcUser} contains &quot;claims&quot; about the authentication of the End-User.
* The claims are aggregated from the {@link OidcIdToken} and the {@link OidcUserInfo} (if available).
*
* <p>
* Implementation instances of this interface represent an {@link AuthenticatedPrincipal}
@ -51,9 +51,25 @@ import java.util.Map;
*/
public interface OidcUser extends OAuth2User, IdTokenClaimAccessor {
/**
* Returns the claims about the user.
* The claims are aggregated from {@link #getIdToken()} and {@link #getUserInfo()} (if available).
*
* @return a {@code Map} of claims about the user
*/
Map<String, Object> getClaims();
/**
* Returns the {@link OidcUserInfo UserInfo} containing claims about the user.
*
* @return the {@link OidcUserInfo} containing claims about the user.
*/
OidcUserInfo getUserInfo();
/**
* Returns the {@link OidcIdToken ID Token} containing claims about the user.
*
* @return the {@link OidcIdToken} containing claims about the user.
*/
OidcIdToken getIdToken();
}

View File

@ -16,16 +16,16 @@
package org.springframework.security.oauth2.core.oidc.user;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
import org.springframework.util.Assert;
import java.util.HashMap;
import java.util.Map;
/**
* A {@link GrantedAuthority} that is associated with an {@link OidcUser}.
* A {@link GrantedAuthority} that may be associated to an {@link OidcUser}.
*
* @author Joe Grandja
* @since 5.0
@ -35,24 +35,53 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
private final OidcIdToken idToken;
private final OidcUserInfo userInfo;
/**
* Constructs a {@code OidcUserAuthority} using the provided parameters.
*
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
*/
public OidcUserAuthority(OidcIdToken idToken) {
this(idToken, null);
}
/**
* Constructs a {@code OidcUserAuthority} using the provided parameters
* and defaults {@link #getAuthority()} to {@code ROLE_USER}.
*
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
* @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null}
*/
public OidcUserAuthority(OidcIdToken idToken, OidcUserInfo userInfo) {
this("ROLE_USER", idToken, userInfo);
}
/**
* Constructs a {@code OidcUserAuthority} using the provided parameters.
*
* @param authority the authority granted to the user
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
* @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null}
*/
public OidcUserAuthority(String authority, OidcIdToken idToken, OidcUserInfo userInfo) {
super(authority, collectClaims(idToken, userInfo));
this.idToken = idToken;
this.userInfo = userInfo;
}
/**
* Returns the {@link OidcIdToken ID Token} containing claims about the user.
*
* @return the {@link OidcIdToken} containing claims about the user.
*/
public OidcIdToken getIdToken() {
return this.idToken;
}
/**
* Returns the {@link OidcUserInfo UserInfo} containing claims about the user, may be {@code null}.
*
* @return the {@link OidcUserInfo} containing claims about the user, or {@code null}
*/
public OidcUserInfo getUserInfo() {
return this.userInfo;
}

View File

@ -14,6 +14,6 @@
* limitations under the License.
*/
/**
* Provides a model for an <i>OpenID Connect Core 1.0</i> representation of a user <code>Principal</code>.
* Provides a model for an OpenID Connect Core 1.0 representation of a user {@code Principal}.
*/
package org.springframework.security.oauth2.core.oidc.user;

View File

@ -14,6 +14,6 @@
* limitations under the License.
*/
/**
* Core classes and interfaces providing support for the <i>OAuth 2.0 Authorization Framework</i>.
* Core classes and interfaces providing support for the OAuth 2.0 Authorization Framework.
*/
package org.springframework.security.oauth2.core;

View File

@ -35,11 +35,11 @@ import java.util.stream.Collectors;
* The default implementation of an {@link OAuth2User}.
*
* <p>
* User attribute names are <b><i>not</i></b> standardized between providers
* and therefore it is required that the user supply the <i>key</i>
* User attribute names are <b>not</b> standardized between providers
* and therefore it is required to supply the <i>key</i>
* for the user's &quot;name&quot; attribute to one of the constructors.
* The <i>key</i> will be used for accessing the &quot;name&quot; of the
* <code>Principal</code> (user) via {@link #getAttributes()}
* {@code Principal} (user) via {@link #getAttributes()}
* and returning it from {@link #getName()}.
*
* @author Joe Grandja
@ -52,6 +52,13 @@ public class DefaultOAuth2User implements OAuth2User, Serializable {
private final Map<String, Object> attributes;
private final String nameAttributeKey;
/**
* Constructs a {@code DefaultOAuth2User} using the provided parameters.
*
* @param authorities the authorities granted to the user
* @param attributes the attributes about the user
* @param nameAttributeKey the key used to access the user's &quot;name&quot; from {@link #getAttributes()}
*/
public DefaultOAuth2User(Set<GrantedAuthority> authorities, Map<String, Object> attributes, String nameAttributeKey) {
Assert.notEmpty(authorities, "authorities cannot be empty");
Assert.notEmpty(attributes, "attributes cannot be empty");

View File

@ -23,8 +23,8 @@ import java.util.Collection;
import java.util.Map;
/**
* A representation of a user <code>Principal</code>
* that is registered with a standard <i>OAuth 2.0 Provider</i>.
* A representation of a user {@code Principal}
* that is registered with an OAuth 2.0 Provider.
*
* <p>
* An OAuth 2.0 user is composed of one or more attributes, for example,
@ -33,7 +33,7 @@ import java.util.Map;
* is keyed by the &quot;name&quot; in {@link #getAttributes()}.
*
* <p>
* <b>NOTE:</b> Attribute names are <b><i>not</i></b> standardized between providers and therefore will vary.
* <b>NOTE:</b> Attribute names are <b>not</b> standardized between providers and therefore will vary.
* Please consult the provider's API documentation for the set of supported user attribute names.
*
* <p>
@ -48,8 +48,18 @@ import java.util.Map;
*/
public interface OAuth2User extends AuthenticatedPrincipal {
/**
* Returns the authorities granted to the user.
*
* @return a {@code Collection} of {@link GrantedAuthority}(s)
*/
Collection<? extends GrantedAuthority> getAuthorities();
/**
* Returns the attributes about the user.
*
* @return a {@code Map} of attributes about the user
*/
Map<String, Object> getAttributes();
}

View File

@ -24,7 +24,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
/**
* A {@link GrantedAuthority} that is associated with an {@link OAuth2User}.
* A {@link GrantedAuthority} that may be associated to an {@link OAuth2User}.
*
* @author Joe Grandja
* @since 5.0
@ -35,10 +35,22 @@ public class OAuth2UserAuthority implements GrantedAuthority {
private final String authority;
private final Map<String, Object> attributes;
/**
* Constructs a {@code OAuth2UserAuthority} using the provided parameters
* and defaults {@link #getAuthority()} to {@code ROLE_USER}.
*
* @param attributes the attributes about the user
*/
public OAuth2UserAuthority(Map<String, Object> attributes) {
this("ROLE_USER", attributes);
}
/**
* Constructs a {@code OAuth2UserAuthority} using the provided parameters.
*
* @param authority the authority granted to the user
* @param attributes the attributes about the user
*/
public OAuth2UserAuthority(String authority, Map<String, Object> attributes) {
Assert.hasText(authority, "authority cannot be empty");
Assert.notEmpty(attributes, "attributes cannot be empty");
@ -51,6 +63,11 @@ public class OAuth2UserAuthority implements GrantedAuthority {
return this.authority;
}
/**
* Returns the attributes about the user.
*
* @return a {@code Map} of attributes about the user
*/
public Map<String, Object> getAttributes() {
return this.attributes;
}

View File

@ -14,6 +14,6 @@
* limitations under the License.
*/
/**
* Provides a model for an <i>OAuth 2.0</i> representation of a user <code>Principal</code>.
* Provides a model for an OAuth 2.0 representation of a user {@code Principal}.
*/
package org.springframework.security.oauth2.core.user;