mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-02-08 22:44:35 +00:00
Enable null-safety in spring-security-oauth2-core
Closes gh-17820
This commit is contained in:
parent
dfed528851
commit
db5310bee8
@ -1,5 +1,6 @@
|
||||
plugins {
|
||||
id 'compile-warnings-error'
|
||||
id 'security-nullability'
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
|
||||
@ -19,7 +19,8 @@ package org.springframework.security.oauth2.core;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@ -37,9 +38,9 @@ public abstract class AbstractOAuth2Token implements OAuth2Token, Serializable {
|
||||
|
||||
private final String tokenValue;
|
||||
|
||||
private final Instant issuedAt;
|
||||
private final @Nullable Instant issuedAt;
|
||||
|
||||
private final Instant expiresAt;
|
||||
private final @Nullable Instant expiresAt;
|
||||
|
||||
/**
|
||||
* Sub-class constructor.
|
||||
@ -78,8 +79,7 @@ public abstract class AbstractOAuth2Token implements OAuth2Token, Serializable {
|
||||
* Returns the time at which the token was issued.
|
||||
* @return the time the token was issued or {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
public Instant getIssuedAt() {
|
||||
public @Nullable Instant getIssuedAt() {
|
||||
return this.issuedAt;
|
||||
}
|
||||
|
||||
@ -87,8 +87,7 @@ public abstract class AbstractOAuth2Token implements OAuth2Token, Serializable {
|
||||
* Returns the expiration time on or after which the token MUST NOT be accepted.
|
||||
* @return the token expiration time or {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
public Instant getExpiresAt() {
|
||||
public @Nullable Instant getExpiresAt() {
|
||||
return this.expiresAt;
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,8 @@ import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.security.oauth2.core.converter.ClaimConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
@ -44,11 +46,11 @@ public interface ClaimAccessor {
|
||||
* type {@code T}.
|
||||
* @param claim the name of the claim
|
||||
* @param <T> the type of the claim value
|
||||
* @return the claim value
|
||||
* @return the claim value, or {@code null} if the claim does not exist
|
||||
* @since 5.2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default <T> T getClaim(String claim) {
|
||||
default <T> @Nullable T getClaim(String claim) {
|
||||
return !hasClaim(claim) ? null : (T) getClaims().get(claim);
|
||||
}
|
||||
|
||||
@ -71,7 +73,7 @@ public interface ClaimAccessor {
|
||||
* @return the claim value or {@code null} if it does not exist or is equal to
|
||||
* {@code null}
|
||||
*/
|
||||
default String getClaimAsString(String claim) {
|
||||
default @Nullable String getClaimAsString(String claim) {
|
||||
return !hasClaim(claim) ? null
|
||||
: ClaimConversionService.getSharedInstance().convert(getClaims().get(claim), String.class);
|
||||
}
|
||||
@ -85,7 +87,8 @@ public interface ClaimAccessor {
|
||||
* {@code Boolean}
|
||||
* @throws NullPointerException if the claim value is {@code null}
|
||||
*/
|
||||
default Boolean getClaimAsBoolean(String claim) {
|
||||
@SuppressWarnings("NullAway")
|
||||
default @Nullable Boolean getClaimAsBoolean(String claim) {
|
||||
if (!hasClaim(claim)) {
|
||||
return null;
|
||||
}
|
||||
@ -100,8 +103,12 @@ public interface ClaimAccessor {
|
||||
* 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
|
||||
* @throws IllegalArgumentException if the claim value cannot be converted to an
|
||||
* {@code Instant}
|
||||
* @throws NullPointerException if the claim value is {@code null}
|
||||
*/
|
||||
default Instant getClaimAsInstant(String claim) {
|
||||
@SuppressWarnings("NullAway")
|
||||
default @Nullable Instant getClaimAsInstant(String claim) {
|
||||
if (!hasClaim(claim)) {
|
||||
return null;
|
||||
}
|
||||
@ -116,8 +123,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
|
||||
* @throws IllegalArgumentException if the claim value cannot be converted to a
|
||||
* {@code URL}
|
||||
* @throws NullPointerException if the claim value is {@code null}
|
||||
*/
|
||||
default URL getClaimAsURL(String claim) {
|
||||
@SuppressWarnings("NullAway")
|
||||
default @Nullable URL getClaimAsURL(String claim) {
|
||||
if (!hasClaim(claim)) {
|
||||
return null;
|
||||
}
|
||||
@ -137,8 +148,8 @@ public interface ClaimAccessor {
|
||||
* {@code Map}
|
||||
* @throws NullPointerException if the claim value is {@code null}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default Map<String, Object> getClaimAsMap(String claim) {
|
||||
@SuppressWarnings({ "unchecked", "NullAway" })
|
||||
default @Nullable Map<String, Object> getClaimAsMap(String claim) {
|
||||
if (!hasClaim(claim)) {
|
||||
return null;
|
||||
}
|
||||
@ -162,8 +173,8 @@ public interface ClaimAccessor {
|
||||
* {@code List}
|
||||
* @throws NullPointerException if the claim value is {@code null}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default List<String> getClaimAsStringList(String claim) {
|
||||
@SuppressWarnings({ "unchecked", "NullAway" })
|
||||
default @Nullable List<String> getClaimAsStringList(String claim) {
|
||||
if (!hasClaim(claim)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@ package org.springframework.security.oauth2.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@ -105,7 +104,6 @@ public final class ClientAuthenticationMethod implements Serializable {
|
||||
* constant, if any
|
||||
* @since 6.5
|
||||
*/
|
||||
@NonNull
|
||||
public static ClientAuthenticationMethod valueOf(String method) {
|
||||
for (ClientAuthenticationMethod m : methods()) {
|
||||
if (m.getValue().equals(method)) {
|
||||
|
||||
@ -22,6 +22,8 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.util.Assert;
|
||||
@ -58,17 +60,21 @@ public final class DefaultOAuth2AuthenticatedPrincipal implements OAuth2Authenti
|
||||
/**
|
||||
* Constructs an {@code DefaultOAuth2AuthenticatedPrincipal} using the provided
|
||||
* parameters.
|
||||
* @param name the name attached to the OAuth 2.0 token
|
||||
* @param name the name attached to the OAuth 2.0 token, may be {@code null}
|
||||
* @param attributes the attributes of the OAuth 2.0 token
|
||||
* @param authorities the authorities of the OAuth 2.0 token
|
||||
* @param authorities the authorities of the OAuth 2.0 token, may be {@code null}
|
||||
*/
|
||||
public DefaultOAuth2AuthenticatedPrincipal(String name, Map<String, Object> attributes,
|
||||
Collection<GrantedAuthority> authorities) {
|
||||
public DefaultOAuth2AuthenticatedPrincipal(@Nullable String name, Map<String, Object> attributes,
|
||||
@Nullable Collection<GrantedAuthority> authorities) {
|
||||
Assert.notEmpty(attributes, "attributes cannot be empty");
|
||||
this.attributes = Collections.unmodifiableMap(attributes);
|
||||
this.authorities = (authorities != null) ? Collections.unmodifiableCollection(authorities)
|
||||
: AuthorityUtils.NO_AUTHORITIES;
|
||||
this.name = (name != null) ? name : (String) this.attributes.get("sub");
|
||||
// Ensure name is never null - use 'sub' attribute as fallback, then empty string
|
||||
// This satisfies AuthenticatedPrincipal.getName() contract which never returns
|
||||
// null
|
||||
String resolvedName = (name != null) ? name : (String) this.attributes.get("sub");
|
||||
this.name = (resolvedName != null) ? resolvedName : "";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -22,6 +22,8 @@ import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@ -52,11 +54,12 @@ public class OAuth2AccessToken extends AbstractOAuth2Token {
|
||||
* 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 issuedAt the time at which the token was issued, may be {@code null}
|
||||
* @param expiresAt the expiration time on or after which the token MUST NOT be
|
||||
* accepted
|
||||
* accepted, may be {@code null}
|
||||
*/
|
||||
public OAuth2AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt) {
|
||||
public OAuth2AccessToken(TokenType tokenType, String tokenValue, @Nullable Instant issuedAt,
|
||||
@Nullable Instant expiresAt) {
|
||||
this(tokenType, tokenValue, issuedAt, expiresAt, Collections.emptySet());
|
||||
}
|
||||
|
||||
@ -64,13 +67,13 @@ public class OAuth2AccessToken extends AbstractOAuth2Token {
|
||||
* 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 issuedAt the time at which the token was issued, may be {@code null}
|
||||
* @param expiresAt the expiration time on or after which the token MUST NOT be
|
||||
* accepted
|
||||
* accepted, may be {@code null}
|
||||
* @param scopes the scope(s) associated to the token
|
||||
*/
|
||||
public OAuth2AccessToken(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt,
|
||||
Set<String> scopes) {
|
||||
public OAuth2AccessToken(TokenType tokenType, String tokenValue, @Nullable Instant issuedAt,
|
||||
@Nullable Instant expiresAt, Set<String> scopes) {
|
||||
super(tokenValue, issuedAt, expiresAt);
|
||||
Assert.notNull(tokenType, "tokenType cannot be null");
|
||||
this.tokenType = tokenType;
|
||||
|
||||
@ -19,7 +19,8 @@ package org.springframework.security.oauth2.core;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.AuthenticatedPrincipal;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
@ -38,9 +39,8 @@ public interface OAuth2AuthenticatedPrincipal extends AuthenticatedPrincipal {
|
||||
* @param <A> the type of the attribute
|
||||
* @return the attribute or {@code null} otherwise
|
||||
*/
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
default <A> A getAttribute(String name) {
|
||||
default <A> @Nullable A getAttribute(String name) {
|
||||
return (A) getAttributes().get(name);
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ package org.springframework.security.oauth2.core;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.util.Assert;
|
||||
@ -77,22 +79,25 @@ public class OAuth2AuthenticationException extends AuthenticationException {
|
||||
/**
|
||||
* Constructs an {@code OAuth2AuthenticationException} using the provided parameters.
|
||||
* @param error the {@link OAuth2Error OAuth 2.0 Error}
|
||||
* @param message the detail message
|
||||
* @param message the detail message, may be {@code null}
|
||||
*/
|
||||
public OAuth2AuthenticationException(OAuth2Error error, String message) {
|
||||
public OAuth2AuthenticationException(OAuth2Error error, @Nullable String message) {
|
||||
this(error, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param message the detail message, may be {@code null}
|
||||
* @param cause the root cause, may be {@code null}
|
||||
*/
|
||||
public OAuth2AuthenticationException(OAuth2Error error, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
public OAuth2AuthenticationException(OAuth2Error error, @Nullable String message, @Nullable Throwable cause) {
|
||||
super(message);
|
||||
Assert.notNull(error, "error cannot be null");
|
||||
this.error = error;
|
||||
if (cause != null) {
|
||||
initCause(cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -18,6 +18,8 @@ package org.springframework.security.oauth2.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@ -41,9 +43,9 @@ public class OAuth2Error implements Serializable {
|
||||
|
||||
private final String errorCode;
|
||||
|
||||
private final String description;
|
||||
private final @Nullable String description;
|
||||
|
||||
private final String uri;
|
||||
private final @Nullable String uri;
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2Error} using the provided parameters.
|
||||
@ -56,10 +58,10 @@ public class OAuth2Error implements Serializable {
|
||||
/**
|
||||
* Constructs an {@code OAuth2Error} using the provided parameters.
|
||||
* @param errorCode the error code
|
||||
* @param description the error description
|
||||
* @param uri the error uri
|
||||
* @param description the error description, may be {@code null}
|
||||
* @param uri the error uri, may be {@code null}
|
||||
*/
|
||||
public OAuth2Error(String errorCode, String description, String uri) {
|
||||
public OAuth2Error(String errorCode, @Nullable String description, @Nullable String uri) {
|
||||
Assert.hasText(errorCode, "errorCode cannot be empty");
|
||||
this.errorCode = errorCode;
|
||||
this.description = description;
|
||||
@ -76,17 +78,17 @@ public class OAuth2Error implements Serializable {
|
||||
|
||||
/**
|
||||
* Returns the error description.
|
||||
* @return the error description
|
||||
* @return the error description, or {@code null} if not available
|
||||
*/
|
||||
public final String getDescription() {
|
||||
public final @Nullable String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error uri.
|
||||
* @return the error uri
|
||||
* @return the error uri, or {@code null} if not available
|
||||
*/
|
||||
public final String getUri() {
|
||||
public final @Nullable String getUri() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,8 @@ package org.springframework.security.oauth2.core;
|
||||
import java.io.Serial;
|
||||
import java.time.Instant;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An implementation of an {@link AbstractOAuth2Token} representing an OAuth 2.0 Refresh
|
||||
* Token.
|
||||
@ -43,20 +45,20 @@ public class OAuth2RefreshToken extends AbstractOAuth2Token {
|
||||
/**
|
||||
* Constructs an {@code OAuth2RefreshToken} using the provided parameters.
|
||||
* @param tokenValue the token value
|
||||
* @param issuedAt the time at which the token was issued
|
||||
* @param issuedAt the time at which the token was issued, may be {@code null}
|
||||
*/
|
||||
public OAuth2RefreshToken(String tokenValue, Instant issuedAt) {
|
||||
public OAuth2RefreshToken(String tokenValue, @Nullable Instant issuedAt) {
|
||||
this(tokenValue, issuedAt, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@code OAuth2RefreshToken} using the provided parameters.
|
||||
* @param tokenValue the token value
|
||||
* @param issuedAt the time at which the token was issued
|
||||
* @param expiresAt the time at which the token expires
|
||||
* @param issuedAt the time at which the token was issued, may be {@code null}
|
||||
* @param expiresAt the time at which the token expires, may be {@code null}
|
||||
* @since 5.5
|
||||
*/
|
||||
public OAuth2RefreshToken(String tokenValue, Instant issuedAt, Instant expiresAt) {
|
||||
public OAuth2RefreshToken(String tokenValue, @Nullable Instant issuedAt, @Nullable Instant expiresAt) {
|
||||
super(tokenValue, issuedAt, expiresAt);
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ package org.springframework.security.oauth2.core;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Core interface representing an OAuth 2.0 Token.
|
||||
@ -39,8 +39,7 @@ public interface OAuth2Token {
|
||||
* Returns the time at which the token was issued.
|
||||
* @return the time the token was issued or {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
default Instant getIssuedAt() {
|
||||
default @Nullable Instant getIssuedAt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -48,8 +47,7 @@ public interface OAuth2Token {
|
||||
* Returns the expiration time on or after which the token MUST NOT be accepted.
|
||||
* @return the token expiration time or {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
default Instant getExpiresAt() {
|
||||
default @Nullable Instant getExpiresAt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ import java.net.URL;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A {@link ClaimAccessor} for the "claims" that may be contained in the
|
||||
@ -45,105 +45,106 @@ public interface OAuth2TokenIntrospectionClaimAccessor extends ClaimAccessor {
|
||||
|
||||
/**
|
||||
* Returns a human-readable identifier {@code (username)} for the resource owner that
|
||||
* authorized the token
|
||||
* authorized the token, or {@code null} if it does not exist.
|
||||
* @return a human-readable identifier for the resource owner that authorized the
|
||||
* token
|
||||
* token, or {@code null} if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default String getUsername() {
|
||||
default @Nullable String getUsername() {
|
||||
return getClaimAsString(OAuth2TokenIntrospectionClaimNames.USERNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client identifier {@code (client_id)} for the token
|
||||
* @return the client identifier for the token
|
||||
* Returns the client identifier {@code (client_id)} for the token, or {@code null} if
|
||||
* it does not exist.
|
||||
* @return the client identifier for the token, or {@code null} if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default String getClientId() {
|
||||
default @Nullable String getClientId() {
|
||||
return getClaimAsString(OAuth2TokenIntrospectionClaimNames.CLIENT_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scopes {@code (scope)} associated with the token
|
||||
* @return the scopes associated with the token
|
||||
* Returns the scopes {@code (scope)} associated with the token, or {@code null} if it
|
||||
* does not exist.
|
||||
* @return the scopes associated with the token, or {@code null} if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default List<String> getScopes() {
|
||||
default @Nullable List<String> getScopes() {
|
||||
return getClaimAsStringList(OAuth2TokenIntrospectionClaimNames.SCOPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the token {@code (token_type)}, for example {@code bearer}.
|
||||
* @return the type of the token, for example {@code bearer}.
|
||||
* Returns the type of the token {@code (token_type)}, for example {@code bearer}, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return the type of the token, for example {@code bearer}, or {@code null} if it
|
||||
* does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default String getTokenType() {
|
||||
default @Nullable String getTokenType() {
|
||||
return getClaimAsString(OAuth2TokenIntrospectionClaimNames.TOKEN_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a timestamp {@code (exp)} indicating when the token expires
|
||||
* @return a timestamp indicating when the token expires
|
||||
* Returns a timestamp {@code (exp)} indicating when the token expires, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return a timestamp indicating when the token expires, or {@code null} if it does
|
||||
* not exist
|
||||
*/
|
||||
@Nullable
|
||||
default Instant getExpiresAt() {
|
||||
default @Nullable Instant getExpiresAt() {
|
||||
return getClaimAsInstant(OAuth2TokenIntrospectionClaimNames.EXP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a timestamp {@code (iat)} indicating when the token was issued
|
||||
* @return a timestamp indicating when the token was issued
|
||||
* Returns a timestamp {@code (iat)} indicating when the token was issued, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return a timestamp indicating when the token was issued, or {@code null} if it
|
||||
* does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default Instant getIssuedAt() {
|
||||
default @Nullable Instant getIssuedAt() {
|
||||
return getClaimAsInstant(OAuth2TokenIntrospectionClaimNames.IAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a timestamp {@code (nbf)} indicating when the token is not to be used
|
||||
* before
|
||||
* @return a timestamp indicating when the token is not to be used before
|
||||
* before, or {@code null} if it does not exist.
|
||||
* @return a timestamp indicating when the token is not to be used before, or
|
||||
* {@code null} if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default Instant getNotBefore() {
|
||||
default @Nullable Instant getNotBefore() {
|
||||
return getClaimAsInstant(OAuth2TokenIntrospectionClaimNames.NBF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns usually a machine-readable identifier {@code (sub)} of the resource owner
|
||||
* who authorized the token
|
||||
* who authorized the token, or {@code null} if it does not exist.
|
||||
* @return usually a machine-readable identifier of the resource owner who authorized
|
||||
* the token
|
||||
* the token, or {@code null} if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default String getSubject() {
|
||||
default @Nullable String getSubject() {
|
||||
return getClaimAsString(OAuth2TokenIntrospectionClaimNames.SUB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the intended audience {@code (aud)} for the token
|
||||
* @return the intended audience for the token
|
||||
* Returns the intended audience {@code (aud)} for the token, or {@code null} if it
|
||||
* does not exist.
|
||||
* @return the intended audience for the token, or {@code null} if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default List<String> getAudience() {
|
||||
default @Nullable List<String> getAudience() {
|
||||
return getClaimAsStringList(OAuth2TokenIntrospectionClaimNames.AUD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the issuer {@code (iss)} of the token
|
||||
* @return the issuer of the token
|
||||
* Returns the issuer {@code (iss)} of the token, or {@code null} if it does not
|
||||
* exist.
|
||||
* @return the issuer of the token, or {@code null} if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default URL getIssuer() {
|
||||
default @Nullable URL getIssuer() {
|
||||
return getClaimAsURL(OAuth2TokenIntrospectionClaimNames.ISS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier {@code (jti)} for the token
|
||||
* @return the identifier for the token
|
||||
* Returns the identifier {@code (jti)} for the token, or {@code null} if it does not
|
||||
* exist.
|
||||
* @return the identifier for the token, or {@code null} if it does not exist
|
||||
*/
|
||||
@Nullable
|
||||
default String getId() {
|
||||
default @Nullable String getId() {
|
||||
return getClaimAsString(OAuth2TokenIntrospectionClaimNames.JTI);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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 provide OAuth 2.0 authorization managers.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.authorization;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.oauth2.core.converter;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
@ -32,7 +34,7 @@ import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||
*/
|
||||
public final class ClaimConversionService extends GenericConversionService {
|
||||
|
||||
private static volatile ClaimConversionService sharedInstance;
|
||||
private static volatile @Nullable ClaimConversionService sharedInstance;
|
||||
|
||||
private ClaimConversionService() {
|
||||
addConverters(this);
|
||||
|
||||
@ -19,6 +19,8 @@ package org.springframework.security.oauth2.core.converter;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
@ -34,7 +36,7 @@ final class ObjectToBooleanConverter implements GenericConverter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
@ -36,7 +38,7 @@ final class ObjectToInstantConverter implements GenericConverter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -23,6 +23,8 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@ -49,7 +51,7 @@ final class ObjectToListStringConverter implements ConditionalGenericConverter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.ConditionalGenericConverter;
|
||||
|
||||
@ -37,12 +39,13 @@ final class ObjectToMapStringObjectConverter implements ConditionalGenericConver
|
||||
|
||||
@Override
|
||||
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
TypeDescriptor mapKeyTypeDescriptor = targetType.getMapKeyTypeDescriptor();
|
||||
return targetType.getElementTypeDescriptor() == null
|
||||
|| targetType.getMapKeyTypeDescriptor().getType().equals(String.class);
|
||||
|| (mapKeyTypeDescriptor != null && mapKeyTypeDescriptor.getType().equals(String.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -19,6 +19,8 @@ package org.springframework.security.oauth2.core.converter;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
@ -34,7 +36,7 @@ final class ObjectToStringConverter implements GenericConverter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return (source != null) ? source.toString() : null;
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,8 @@ import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
@ -36,7 +38,7 @@ final class ObjectToURLConverter implements GenericConverter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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 provide claim type converters for OAuth 2.0 and OpenID Connect.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.converter;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@ -23,6 +23,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.util.StringUtils;
|
||||
@ -44,6 +46,9 @@ public final class DefaultMapOAuth2AccessTokenResponseConverter
|
||||
@Override
|
||||
public OAuth2AccessTokenResponse convert(Map<String, Object> source) {
|
||||
String accessToken = getParameterValue(source, OAuth2ParameterNames.ACCESS_TOKEN);
|
||||
if (accessToken == null) {
|
||||
throw new IllegalArgumentException("Missing required parameter: " + OAuth2ParameterNames.ACCESS_TOKEN);
|
||||
}
|
||||
OAuth2AccessToken.TokenType accessTokenType = getAccessTokenType(source);
|
||||
long expiresIn = getExpiresIn(source);
|
||||
Set<String> scopes = getScopes(source);
|
||||
@ -65,7 +70,8 @@ public final class DefaultMapOAuth2AccessTokenResponseConverter
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static OAuth2AccessToken.TokenType getAccessTokenType(Map<String, Object> tokenResponseParameters) {
|
||||
private static OAuth2AccessToken.@Nullable TokenType getAccessTokenType(
|
||||
Map<String, Object> tokenResponseParameters) {
|
||||
if (OAuth2AccessToken.TokenType.BEARER.getValue()
|
||||
.equalsIgnoreCase(getParameterValue(tokenResponseParameters, OAuth2ParameterNames.TOKEN_TYPE))) {
|
||||
return OAuth2AccessToken.TokenType.BEARER;
|
||||
@ -89,7 +95,8 @@ public final class DefaultMapOAuth2AccessTokenResponseConverter
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
private static String getParameterValue(Map<String, Object> tokenResponseParameters, String parameterName) {
|
||||
private static @Nullable String getParameterValue(Map<String, Object> tokenResponseParameters,
|
||||
String parameterName) {
|
||||
Object obj = tokenResponseParameters.get(parameterName);
|
||||
return (obj != null) ? obj.toString() : null;
|
||||
}
|
||||
|
||||
@ -21,9 +21,11 @@ import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@ -39,11 +41,11 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public final class OAuth2AccessTokenResponse {
|
||||
|
||||
private OAuth2AccessToken accessToken;
|
||||
private @Nullable OAuth2AccessToken accessToken;
|
||||
|
||||
private OAuth2RefreshToken refreshToken;
|
||||
private @Nullable OAuth2RefreshToken refreshToken;
|
||||
|
||||
private Map<String, Object> additionalParameters;
|
||||
private @Nullable Map<String, Object> additionalParameters;
|
||||
|
||||
private OAuth2AccessTokenResponse() {
|
||||
}
|
||||
@ -53,12 +55,14 @@ public final class OAuth2AccessTokenResponse {
|
||||
* @return the {@link OAuth2AccessToken}
|
||||
*/
|
||||
public OAuth2AccessToken getAccessToken() {
|
||||
Assert.notNull(this.accessToken, "accessToken cannot be null");
|
||||
return this.accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link OAuth2RefreshToken Refresh Token}.
|
||||
* @return the {@link OAuth2RefreshToken}
|
||||
* @return the {@link OAuth2RefreshToken}, or {@code null} if not present in the
|
||||
* response
|
||||
* @since 5.1
|
||||
*/
|
||||
public @Nullable OAuth2RefreshToken getRefreshToken() {
|
||||
@ -71,6 +75,7 @@ public final class OAuth2AccessTokenResponse {
|
||||
* empty.
|
||||
*/
|
||||
public Map<String, Object> getAdditionalParameters() {
|
||||
Assert.notNull(this.additionalParameters, "additionalParameters cannot be null");
|
||||
return this.additionalParameters;
|
||||
}
|
||||
|
||||
@ -99,19 +104,19 @@ public final class OAuth2AccessTokenResponse {
|
||||
|
||||
private String tokenValue;
|
||||
|
||||
private OAuth2AccessToken.TokenType tokenType;
|
||||
private OAuth2AccessToken.@Nullable TokenType tokenType;
|
||||
|
||||
private Instant issuedAt;
|
||||
private @Nullable Instant issuedAt;
|
||||
|
||||
private Instant expiresAt;
|
||||
private @Nullable Instant expiresAt;
|
||||
|
||||
private long expiresIn;
|
||||
|
||||
private Set<String> scopes;
|
||||
private @Nullable Set<String> scopes;
|
||||
|
||||
private String refreshToken;
|
||||
private @Nullable String refreshToken;
|
||||
|
||||
private Map<String, Object> additionalParameters;
|
||||
private @Nullable Map<String, Object> additionalParameters;
|
||||
|
||||
private Builder(OAuth2AccessTokenResponse response) {
|
||||
OAuth2AccessToken accessToken = response.getAccessToken();
|
||||
@ -131,10 +136,10 @@ public final class OAuth2AccessTokenResponse {
|
||||
|
||||
/**
|
||||
* Sets the {@link OAuth2AccessToken.TokenType token type}.
|
||||
* @param tokenType the type of token issued
|
||||
* @param tokenType the type of token issued, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder tokenType(OAuth2AccessToken.TokenType tokenType) {
|
||||
public Builder tokenType(OAuth2AccessToken.@Nullable TokenType tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
return this;
|
||||
}
|
||||
@ -152,30 +157,32 @@ public final class OAuth2AccessTokenResponse {
|
||||
|
||||
/**
|
||||
* Sets the scope(s) associated to the access token.
|
||||
* @param scopes the scope(s) associated to the access token.
|
||||
* @param scopes the scope(s) associated to the access token, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder scopes(Set<String> scopes) {
|
||||
public Builder scopes(@Nullable Set<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the refresh token associated to the access token.
|
||||
* @param refreshToken the refresh token associated to the access token.
|
||||
* @param refreshToken the refresh token associated to the access token, may be
|
||||
* {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder refreshToken(String refreshToken) {
|
||||
public Builder refreshToken(@Nullable String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the additional parameters returned in the response.
|
||||
* @param additionalParameters the additional parameters returned in the response
|
||||
* @param additionalParameters the additional parameters returned in the response,
|
||||
* may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder additionalParameters(Map<String, Object> additionalParameters) {
|
||||
public Builder additionalParameters(@Nullable Map<String, Object> additionalParameters) {
|
||||
this.additionalParameters = additionalParameters;
|
||||
return this;
|
||||
}
|
||||
@ -185,11 +192,14 @@ public final class OAuth2AccessTokenResponse {
|
||||
* @return a {@link OAuth2AccessTokenResponse}
|
||||
*/
|
||||
public OAuth2AccessTokenResponse build() {
|
||||
Assert.notNull(this.tokenType, "tokenType cannot be null");
|
||||
Instant issuedAt = getIssuedAt();
|
||||
Instant expiresAt = getExpiresAt();
|
||||
// Convert nullable scopes to non-null for constructor
|
||||
Set<String> scopesToUse = (this.scopes != null) ? this.scopes : Collections.emptySet();
|
||||
OAuth2AccessTokenResponse accessTokenResponse = new OAuth2AccessTokenResponse();
|
||||
accessTokenResponse.accessToken = new OAuth2AccessToken(this.tokenType, this.tokenValue, issuedAt,
|
||||
expiresAt, this.scopes);
|
||||
expiresAt, scopesToUse);
|
||||
if (StringUtils.hasText(this.refreshToken)) {
|
||||
accessTokenResponse.refreshToken = new OAuth2RefreshToken(this.refreshToken, issuedAt);
|
||||
}
|
||||
|
||||
@ -30,6 +30,8 @@ import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@ -65,11 +67,11 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
|
||||
private final String clientId;
|
||||
|
||||
private final String redirectUri;
|
||||
private final @Nullable String redirectUri;
|
||||
|
||||
private final Set<String> scopes;
|
||||
|
||||
private final String state;
|
||||
private final @Nullable String state;
|
||||
|
||||
private final Map<String, Object> additionalParameters;
|
||||
|
||||
@ -80,6 +82,8 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
protected OAuth2AuthorizationRequest(AbstractBuilder<?, ?> builder) {
|
||||
Assert.hasText(builder.authorizationUri, "authorizationUri cannot be empty");
|
||||
Assert.hasText(builder.clientId, "clientId cannot be empty");
|
||||
Assert.notNull(builder.authorizationUri, "authorizationUri cannot be null");
|
||||
Assert.notNull(builder.clientId, "clientId cannot be null");
|
||||
this.authorizationUri = builder.authorizationUri;
|
||||
this.authorizationGrantType = builder.authorizationGrantType;
|
||||
this.responseType = builder.responseType;
|
||||
@ -89,8 +93,9 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
CollectionUtils.isEmpty(builder.scopes) ? Collections.emptySet() : new LinkedHashSet<>(builder.scopes));
|
||||
this.state = builder.state;
|
||||
this.additionalParameters = Collections.unmodifiableMap(builder.additionalParameters);
|
||||
this.authorizationRequestUri = StringUtils.hasText(builder.authorizationRequestUri)
|
||||
? builder.authorizationRequestUri : builder.buildAuthorizationRequestUri();
|
||||
String builderUri = builder.authorizationRequestUri;
|
||||
this.authorizationRequestUri = StringUtils.hasText(builderUri) ? builderUri
|
||||
: builder.buildAuthorizationRequestUri();
|
||||
this.attributes = Collections.unmodifiableMap(builder.attributes);
|
||||
}
|
||||
|
||||
@ -127,10 +132,10 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the uri for the redirection endpoint.
|
||||
* @return the uri for the redirection endpoint
|
||||
* Returns the uri for the redirection endpoint, or {@code null} if not present.
|
||||
* @return the uri for the redirection endpoint, or {@code null}
|
||||
*/
|
||||
public String getRedirectUri() {
|
||||
public @Nullable String getRedirectUri() {
|
||||
return this.redirectUri;
|
||||
}
|
||||
|
||||
@ -143,10 +148,10 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state.
|
||||
* @return the state
|
||||
* Returns the state, or {@code null} if not present.
|
||||
* @return the state, or {@code null}
|
||||
*/
|
||||
public String getState() {
|
||||
public @Nullable String getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
@ -177,7 +182,7 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
* @since 5.2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getAttribute(String name) {
|
||||
public <T> @Nullable T getAttribute(String name) {
|
||||
return (T) this.getAttributes().get(name);
|
||||
}
|
||||
|
||||
@ -277,19 +282,19 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
*/
|
||||
protected abstract static class AbstractBuilder<T extends OAuth2AuthorizationRequest, B extends AbstractBuilder<T, B>> {
|
||||
|
||||
private String authorizationUri;
|
||||
private @Nullable String authorizationUri;
|
||||
|
||||
private final AuthorizationGrantType authorizationGrantType = AuthorizationGrantType.AUTHORIZATION_CODE;
|
||||
|
||||
private final OAuth2AuthorizationResponseType responseType = OAuth2AuthorizationResponseType.CODE;
|
||||
|
||||
private String clientId;
|
||||
private @Nullable String clientId;
|
||||
|
||||
private String redirectUri;
|
||||
private @Nullable String redirectUri;
|
||||
|
||||
private Set<String> scopes;
|
||||
private @Nullable Set<String> scopes;
|
||||
|
||||
private String state;
|
||||
private @Nullable String state;
|
||||
|
||||
private Map<String, Object> additionalParameters = new LinkedHashMap<>();
|
||||
|
||||
@ -298,7 +303,7 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
|
||||
private Map<String, Object> attributes = new LinkedHashMap<>();
|
||||
|
||||
private String authorizationRequestUri;
|
||||
private @Nullable String authorizationRequestUri;
|
||||
|
||||
private Function<UriBuilder, URI> authorizationRequestUriFunction = (builder) -> builder.build();
|
||||
|
||||
@ -341,20 +346,20 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
|
||||
/**
|
||||
* Sets the uri for the redirection endpoint.
|
||||
* @param redirectUri the uri for the redirection endpoint
|
||||
* @param redirectUri the uri for the redirection endpoint, may be {@code null}
|
||||
* @return the {@link AbstractBuilder}
|
||||
*/
|
||||
public B redirectUri(String redirectUri) {
|
||||
public B redirectUri(@Nullable String redirectUri) {
|
||||
this.redirectUri = redirectUri;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scope(s).
|
||||
* @param scope the scope(s)
|
||||
* @param scope the scope(s), may be {@code null}
|
||||
* @return the {@link AbstractBuilder}
|
||||
*/
|
||||
public B scope(String... scope) {
|
||||
public B scope(@Nullable String... scope) {
|
||||
if (scope != null && scope.length > 0) {
|
||||
return scopes(new LinkedHashSet<>(Arrays.asList(scope)));
|
||||
}
|
||||
@ -363,20 +368,20 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
|
||||
/**
|
||||
* Sets the scope(s).
|
||||
* @param scopes the scope(s)
|
||||
* @param scopes the scope(s), may be {@code null}
|
||||
* @return the {@link AbstractBuilder}
|
||||
*/
|
||||
public B scopes(Set<String> scopes) {
|
||||
public B scopes(@Nullable Set<String> scopes) {
|
||||
this.scopes = scopes;
|
||||
return getThis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state.
|
||||
* @param state the state
|
||||
* @param state the state, may be {@code null}
|
||||
* @return the {@link AbstractBuilder}
|
||||
*/
|
||||
public B state(String state) {
|
||||
public B state(@Nullable String state) {
|
||||
this.state = state;
|
||||
return getThis();
|
||||
}
|
||||
@ -502,7 +507,9 @@ public class OAuth2AuthorizationRequest implements Serializable {
|
||||
queryParams.set(key, encodeQueryParam(String.valueOf(v)));
|
||||
}
|
||||
});
|
||||
UriBuilder uriBuilder = this.uriBuilderFactory.uriString(this.authorizationUri).queryParams(queryParams);
|
||||
String uri = this.authorizationUri;
|
||||
Assert.notNull(uri, "authorizationUri cannot be null");
|
||||
UriBuilder uriBuilder = this.uriBuilderFactory.uriString(uri).queryParams(queryParams);
|
||||
return this.authorizationRequestUriFunction.apply(uriBuilder).toString();
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,8 @@ package org.springframework.security.oauth2.core.endpoint;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
@ -39,13 +41,13 @@ public final class OAuth2AuthorizationResponse implements Serializable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 620L;
|
||||
|
||||
private String redirectUri;
|
||||
private @Nullable String redirectUri;
|
||||
|
||||
private String state;
|
||||
private @Nullable String state;
|
||||
|
||||
private String code;
|
||||
private @Nullable String code;
|
||||
|
||||
private OAuth2Error error;
|
||||
private @Nullable OAuth2Error error;
|
||||
|
||||
private OAuth2AuthorizationResponse() {
|
||||
}
|
||||
@ -55,22 +57,24 @@ public final class OAuth2AuthorizationResponse implements Serializable {
|
||||
* @return the uri where the response was redirected to
|
||||
*/
|
||||
public String getRedirectUri() {
|
||||
Assert.notNull(this.redirectUri, "redirectUri cannot be null");
|
||||
return this.redirectUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state.
|
||||
* @return the state
|
||||
* Returns the state, or {@code null} if not present.
|
||||
* @return the state, or {@code null}
|
||||
*/
|
||||
public String getState() {
|
||||
public @Nullable String getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authorization code.
|
||||
* @return the authorization code
|
||||
* Returns the authorization code, or {@code null} if the response is an error
|
||||
* response.
|
||||
* @return the authorization code, or {@code null}
|
||||
*/
|
||||
public String getCode() {
|
||||
public @Nullable String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
@ -80,7 +84,7 @@ public final class OAuth2AuthorizationResponse implements Serializable {
|
||||
* @return the {@link OAuth2Error} if the Authorization Request failed, otherwise
|
||||
* {@code null}
|
||||
*/
|
||||
public OAuth2Error getError() {
|
||||
public @Nullable OAuth2Error getError() {
|
||||
return this.error;
|
||||
}
|
||||
|
||||
@ -127,17 +131,17 @@ public final class OAuth2AuthorizationResponse implements Serializable {
|
||||
*/
|
||||
public static final class Builder {
|
||||
|
||||
private String redirectUri;
|
||||
private @Nullable String redirectUri;
|
||||
|
||||
private String state;
|
||||
private @Nullable String state;
|
||||
|
||||
private String code;
|
||||
private @Nullable String code;
|
||||
|
||||
private String errorCode;
|
||||
private @Nullable String errorCode;
|
||||
|
||||
private String errorDescription;
|
||||
private @Nullable String errorDescription;
|
||||
|
||||
private String errorUri;
|
||||
private @Nullable String errorUri;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
@ -218,6 +222,7 @@ public final class OAuth2AuthorizationResponse implements Serializable {
|
||||
authorizationResponse.code = this.code;
|
||||
}
|
||||
else {
|
||||
Assert.hasText(this.errorCode, "errorCode cannot be empty when code is not present");
|
||||
authorizationResponse.error = new OAuth2Error(this.errorCode, this.errorDescription, this.errorUri);
|
||||
}
|
||||
return authorizationResponse;
|
||||
|
||||
@ -21,6 +21,8 @@ import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.oauth2.core.OAuth2DeviceCode;
|
||||
import org.springframework.security.oauth2.core.OAuth2UserCode;
|
||||
import org.springframework.util.Assert;
|
||||
@ -38,17 +40,17 @@ import org.springframework.util.CollectionUtils;
|
||||
*/
|
||||
public final class OAuth2DeviceAuthorizationResponse {
|
||||
|
||||
private OAuth2DeviceCode deviceCode;
|
||||
private @Nullable OAuth2DeviceCode deviceCode;
|
||||
|
||||
private OAuth2UserCode userCode;
|
||||
private @Nullable OAuth2UserCode userCode;
|
||||
|
||||
private String verificationUri;
|
||||
private @Nullable String verificationUri;
|
||||
|
||||
private String verificationUriComplete;
|
||||
private @Nullable String verificationUriComplete;
|
||||
|
||||
private long interval;
|
||||
|
||||
private Map<String, Object> additionalParameters;
|
||||
private @Nullable Map<String, Object> additionalParameters;
|
||||
|
||||
private OAuth2DeviceAuthorizationResponse() {
|
||||
}
|
||||
@ -58,6 +60,7 @@ public final class OAuth2DeviceAuthorizationResponse {
|
||||
* @return the {@link OAuth2DeviceCode}
|
||||
*/
|
||||
public OAuth2DeviceCode getDeviceCode() {
|
||||
Assert.notNull(this.deviceCode, "deviceCode cannot be null");
|
||||
return this.deviceCode;
|
||||
}
|
||||
|
||||
@ -66,6 +69,7 @@ public final class OAuth2DeviceAuthorizationResponse {
|
||||
* @return the {@link OAuth2UserCode}
|
||||
*/
|
||||
public OAuth2UserCode getUserCode() {
|
||||
Assert.notNull(this.userCode, "userCode cannot be null");
|
||||
return this.userCode;
|
||||
}
|
||||
|
||||
@ -74,14 +78,16 @@ public final class OAuth2DeviceAuthorizationResponse {
|
||||
* @return the end-user verification URI
|
||||
*/
|
||||
public String getVerificationUri() {
|
||||
Assert.notNull(this.verificationUri, "verificationUri cannot be null");
|
||||
return this.verificationUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end-user verification URI that includes the user code.
|
||||
* @return the end-user verification URI that includes the user code
|
||||
* Returns the end-user verification URI that includes the user code, or {@code null}
|
||||
* if not present.
|
||||
* @return the end-user verification URI that includes the user code, or {@code null}
|
||||
*/
|
||||
public String getVerificationUriComplete() {
|
||||
public @Nullable String getVerificationUriComplete() {
|
||||
return this.verificationUriComplete;
|
||||
}
|
||||
|
||||
@ -100,6 +106,7 @@ public final class OAuth2DeviceAuthorizationResponse {
|
||||
* empty.
|
||||
*/
|
||||
public Map<String, Object> getAdditionalParameters() {
|
||||
Assert.notNull(this.additionalParameters, "additionalParameters cannot be null");
|
||||
return this.additionalParameters;
|
||||
}
|
||||
|
||||
@ -138,15 +145,15 @@ public final class OAuth2DeviceAuthorizationResponse {
|
||||
|
||||
private final String userCode;
|
||||
|
||||
private String verificationUri;
|
||||
private @Nullable String verificationUri;
|
||||
|
||||
private String verificationUriComplete;
|
||||
private @Nullable String verificationUriComplete;
|
||||
|
||||
private long expiresIn;
|
||||
|
||||
private long interval;
|
||||
|
||||
private Map<String, Object> additionalParameters;
|
||||
private @Nullable Map<String, Object> additionalParameters;
|
||||
|
||||
private Builder(OAuth2DeviceCode deviceCode, OAuth2UserCode userCode) {
|
||||
this.deviceCode = deviceCode.getTokenValue();
|
||||
@ -172,10 +179,10 @@ public final class OAuth2DeviceAuthorizationResponse {
|
||||
/**
|
||||
* Sets the end-user verification URI that includes the user code.
|
||||
* @param verificationUriComplete the end-user verification URI that includes the
|
||||
* user code
|
||||
* user code, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder verificationUriComplete(String verificationUriComplete) {
|
||||
public Builder verificationUriComplete(@Nullable String verificationUriComplete) {
|
||||
this.verificationUriComplete = verificationUriComplete;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -18,4 +18,7 @@
|
||||
* Support classes that model the OAuth 2.0 Request and Response messages from the
|
||||
* Authorization Endpoint and Token Endpoint.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.endpoint;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.oauth2.core.http.converter;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.http.converter.GenericHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||
@ -54,7 +56,7 @@ final class HttpMessageConverters {
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
static GenericHttpMessageConverter<Object> getJsonMessageConverter() {
|
||||
static @Nullable GenericHttpMessageConverter<Object> getJsonMessageConverter() {
|
||||
if (jacksonPresent) {
|
||||
return new GenericHttpMessageConverterAdapter<>(new JacksonJsonHttpMessageConverter());
|
||||
}
|
||||
|
||||
@ -52,8 +52,7 @@ public class OAuth2AccessTokenResponseHttpMessageConverter
|
||||
private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP = new ParameterizedTypeReference<>() {
|
||||
};
|
||||
|
||||
private final GenericHttpMessageConverter<Object> jsonMessageConverter = HttpMessageConverters
|
||||
.getJsonMessageConverter();
|
||||
private final GenericHttpMessageConverter<Object> jsonMessageConverter;
|
||||
|
||||
private Converter<Map<String, Object>, OAuth2AccessTokenResponse> accessTokenResponseConverter = new DefaultMapOAuth2AccessTokenResponseConverter();
|
||||
|
||||
@ -61,6 +60,9 @@ public class OAuth2AccessTokenResponseHttpMessageConverter
|
||||
|
||||
public OAuth2AccessTokenResponseHttpMessageConverter() {
|
||||
super(DEFAULT_CHARSET, MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));
|
||||
GenericHttpMessageConverter<Object> converter = HttpMessageConverters.getJsonMessageConverter();
|
||||
Assert.notNull(converter, "Unable to locate a supported JSON message converter");
|
||||
this.jsonMessageConverter = converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -25,6 +25,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
@ -56,13 +58,18 @@ public class OAuth2DeviceAuthorizationResponseHttpMessageConverter
|
||||
private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP = new ParameterizedTypeReference<>() {
|
||||
};
|
||||
|
||||
private final GenericHttpMessageConverter<Object> jsonMessageConverter = HttpMessageConverters
|
||||
.getJsonMessageConverter();
|
||||
private final GenericHttpMessageConverter<Object> jsonMessageConverter;
|
||||
|
||||
private Converter<Map<String, Object>, OAuth2DeviceAuthorizationResponse> deviceAuthorizationResponseConverter = new DefaultMapOAuth2DeviceAuthorizationResponseConverter();
|
||||
|
||||
private Converter<OAuth2DeviceAuthorizationResponse, Map<String, Object>> deviceAuthorizationResponseParametersConverter = new DefaultOAuth2DeviceAuthorizationResponseMapConverter();
|
||||
|
||||
public OAuth2DeviceAuthorizationResponseHttpMessageConverter() {
|
||||
GenericHttpMessageConverter<Object> converter = HttpMessageConverters.getJsonMessageConverter();
|
||||
Assert.notNull(converter, "Unable to locate a supported JSON message converter");
|
||||
this.jsonMessageConverter = converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz) {
|
||||
return OAuth2DeviceAuthorizationResponse.class.isAssignableFrom(clazz);
|
||||
@ -139,8 +146,18 @@ public class OAuth2DeviceAuthorizationResponseHttpMessageConverter
|
||||
@Override
|
||||
public OAuth2DeviceAuthorizationResponse convert(Map<String, Object> parameters) {
|
||||
String deviceCode = getParameterValue(parameters, OAuth2ParameterNames.DEVICE_CODE);
|
||||
if (deviceCode == null) {
|
||||
throw new IllegalArgumentException("Missing required parameter: " + OAuth2ParameterNames.DEVICE_CODE);
|
||||
}
|
||||
String userCode = getParameterValue(parameters, OAuth2ParameterNames.USER_CODE);
|
||||
if (userCode == null) {
|
||||
throw new IllegalArgumentException("Missing required parameter: " + OAuth2ParameterNames.USER_CODE);
|
||||
}
|
||||
String verificationUri = getParameterValue(parameters, OAuth2ParameterNames.VERIFICATION_URI);
|
||||
if (verificationUri == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Missing required parameter: " + OAuth2ParameterNames.VERIFICATION_URI);
|
||||
}
|
||||
String verificationUriComplete = getParameterValue(parameters,
|
||||
OAuth2ParameterNames.VERIFICATION_URI_COMPLETE);
|
||||
long expiresIn = getParameterValue(parameters, OAuth2ParameterNames.EXPIRES_IN, 0L);
|
||||
@ -162,7 +179,7 @@ public class OAuth2DeviceAuthorizationResponseHttpMessageConverter
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private static String getParameterValue(Map<String, Object> parameters, String parameterName) {
|
||||
private static @Nullable String getParameterValue(Map<String, Object> parameters, String parameterName) {
|
||||
Object obj = parameters.get(parameterName);
|
||||
return (obj != null) ? obj.toString() : null;
|
||||
}
|
||||
|
||||
@ -52,8 +52,7 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverte
|
||||
private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP = new ParameterizedTypeReference<>() {
|
||||
};
|
||||
|
||||
private final GenericHttpMessageConverter<Object> jsonMessageConverter = HttpMessageConverters
|
||||
.getJsonMessageConverter();
|
||||
private final GenericHttpMessageConverter<Object> jsonMessageConverter;
|
||||
|
||||
protected Converter<Map<String, String>, OAuth2Error> errorConverter = new OAuth2ErrorConverter();
|
||||
|
||||
@ -61,6 +60,9 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverte
|
||||
|
||||
public OAuth2ErrorHttpMessageConverter() {
|
||||
super(DEFAULT_CHARSET, MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));
|
||||
GenericHttpMessageConverter<Object> converter = HttpMessageConverters.getJsonMessageConverter();
|
||||
Assert.notNull(converter, "Unable to locate a supported JSON message converter");
|
||||
this.jsonMessageConverter = converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -133,6 +135,7 @@ public class OAuth2ErrorHttpMessageConverter extends AbstractHttpMessageConverte
|
||||
@Override
|
||||
public OAuth2Error convert(Map<String, String> parameters) {
|
||||
String errorCode = parameters.get(OAuth2ParameterNames.ERROR);
|
||||
Assert.hasText(errorCode, "errorCode cannot be empty");
|
||||
String errorDescription = parameters.get(OAuth2ParameterNames.ERROR_DESCRIPTION);
|
||||
String errorUri = parameters.get(OAuth2ParameterNames.ERROR_URI);
|
||||
return new OAuth2Error(errorCode, errorDescription, errorUri);
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* HTTP message converters for OAuth 2.0 and OpenID Connect protocol messages.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.http.converter;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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 provide HTTP message conversion for OAuth 2.0 and OpenID Connect.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.http;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.security.oauth2.core.oidc;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -34,40 +36,43 @@ package org.springframework.security.oauth2.core.oidc;
|
||||
public interface AddressStandardClaim {
|
||||
|
||||
/**
|
||||
* Returns the full mailing address, formatted for display.
|
||||
* @return the full mailing address
|
||||
* Returns the full mailing address, formatted for display, or {@code null} if it does
|
||||
* not exist.
|
||||
* @return the full mailing address, or {@code null} if it does not exist
|
||||
*/
|
||||
String getFormatted();
|
||||
@Nullable String getFormatted();
|
||||
|
||||
/**
|
||||
* Returns the full street address, which may include house number, street name, P.O.
|
||||
* Box, etc.
|
||||
* @return the full street address
|
||||
* Box, etc., or {@code null} if it does not exist.
|
||||
* @return the full street address, or {@code null} if it does not exist
|
||||
*/
|
||||
String getStreetAddress();
|
||||
@Nullable String getStreetAddress();
|
||||
|
||||
/**
|
||||
* Returns the city or locality.
|
||||
* @return the city or locality
|
||||
* Returns the city or locality, or {@code null} if it does not exist.
|
||||
* @return the city or locality, or {@code null} if it does not exist
|
||||
*/
|
||||
String getLocality();
|
||||
@Nullable String getLocality();
|
||||
|
||||
/**
|
||||
* Returns the state, province, prefecture, or region.
|
||||
* @return the state, province, prefecture, or region
|
||||
* Returns the state, province, prefecture, or region, or {@code null} if it does not
|
||||
* exist.
|
||||
* @return the state, province, prefecture, or region, or {@code null} if it does not
|
||||
* exist
|
||||
*/
|
||||
String getRegion();
|
||||
@Nullable String getRegion();
|
||||
|
||||
/**
|
||||
* Returns the zip code or postal code.
|
||||
* @return the zip code or postal code
|
||||
* Returns the zip code or postal code, or {@code null} if it does not exist.
|
||||
* @return the zip code or postal code, or {@code null} if it does not exist
|
||||
*/
|
||||
String getPostalCode();
|
||||
@Nullable String getPostalCode();
|
||||
|
||||
/**
|
||||
* Returns the country.
|
||||
* @return the country
|
||||
* Returns the country, or {@code null} if it does not exist.
|
||||
* @return the country, or {@code null} if it does not exist
|
||||
*/
|
||||
String getCountry();
|
||||
@Nullable String getCountry();
|
||||
|
||||
}
|
||||
|
||||
@ -18,6 +18,8 @@ package org.springframework.security.oauth2.core.oidc;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* The default implementation of an {@link AddressStandardClaim Address Claim}.
|
||||
*
|
||||
@ -27,48 +29,48 @@ import java.util.Map;
|
||||
*/
|
||||
public final class DefaultAddressStandardClaim implements AddressStandardClaim {
|
||||
|
||||
private String formatted;
|
||||
private @Nullable String formatted;
|
||||
|
||||
private String streetAddress;
|
||||
private @Nullable String streetAddress;
|
||||
|
||||
private String locality;
|
||||
private @Nullable String locality;
|
||||
|
||||
private String region;
|
||||
private @Nullable String region;
|
||||
|
||||
private String postalCode;
|
||||
private @Nullable String postalCode;
|
||||
|
||||
private String country;
|
||||
private @Nullable String country;
|
||||
|
||||
private DefaultAddressStandardClaim() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormatted() {
|
||||
public @Nullable String getFormatted() {
|
||||
return this.formatted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStreetAddress() {
|
||||
public @Nullable String getStreetAddress() {
|
||||
return this.streetAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocality() {
|
||||
public @Nullable String getLocality() {
|
||||
return this.locality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegion() {
|
||||
public @Nullable String getRegion() {
|
||||
return this.region;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPostalCode() {
|
||||
public @Nullable String getPostalCode() {
|
||||
return this.postalCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCountry() {
|
||||
public @Nullable String getCountry() {
|
||||
return this.country;
|
||||
}
|
||||
|
||||
@ -131,17 +133,17 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim {
|
||||
|
||||
private static final String COUNTRY_FIELD_NAME = "country";
|
||||
|
||||
private String formatted;
|
||||
private @Nullable String formatted;
|
||||
|
||||
private String streetAddress;
|
||||
private @Nullable String streetAddress;
|
||||
|
||||
private String locality;
|
||||
private @Nullable String locality;
|
||||
|
||||
private String region;
|
||||
private @Nullable String region;
|
||||
|
||||
private String postalCode;
|
||||
private @Nullable String postalCode;
|
||||
|
||||
private String country;
|
||||
private @Nullable String country;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
@ -165,10 +167,10 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim {
|
||||
|
||||
/**
|
||||
* Sets the full mailing address, formatted for display.
|
||||
* @param formatted the full mailing address
|
||||
* @param formatted the full mailing address, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder formatted(String formatted) {
|
||||
public Builder formatted(@Nullable String formatted) {
|
||||
this.formatted = formatted;
|
||||
return this;
|
||||
}
|
||||
@ -176,50 +178,50 @@ public final class DefaultAddressStandardClaim implements AddressStandardClaim {
|
||||
/**
|
||||
* Sets the full street address, which may include house number, street name, P.O.
|
||||
* Box, etc.
|
||||
* @param streetAddress the full street address
|
||||
* @param streetAddress the full street address, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder streetAddress(String streetAddress) {
|
||||
public Builder streetAddress(@Nullable String streetAddress) {
|
||||
this.streetAddress = streetAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the city or locality.
|
||||
* @param locality the city or locality
|
||||
* @param locality the city or locality, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder locality(String locality) {
|
||||
public Builder locality(@Nullable String locality) {
|
||||
this.locality = locality;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state, province, prefecture, or region.
|
||||
* @param region the state, province, prefecture, or region
|
||||
* @param region the state, province, prefecture, or region, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder region(String region) {
|
||||
public Builder region(@Nullable String region) {
|
||||
this.region = region;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the zip code or postal code.
|
||||
* @param postalCode the zip code or postal code
|
||||
* @param postalCode the zip code or postal code, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder postalCode(String postalCode) {
|
||||
public Builder postalCode(@Nullable String postalCode) {
|
||||
this.postalCode = postalCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the country.
|
||||
* @param country the country
|
||||
* @param country the country, may be {@code null}
|
||||
* @return the {@link Builder}
|
||||
*/
|
||||
public Builder country(String country) {
|
||||
public Builder country(@Nullable String country) {
|
||||
this.country = country;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -20,6 +20,8 @@ import java.net.URL;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||
|
||||
/**
|
||||
@ -43,101 +45,117 @@ import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||
public interface IdTokenClaimAccessor extends StandardClaimAccessor {
|
||||
|
||||
/**
|
||||
* Returns the Issuer identifier {@code (iss)}.
|
||||
* @return the Issuer identifier
|
||||
* Returns the Issuer identifier {@code (iss)}, or {@code null} if it does not exist.
|
||||
* @return the Issuer identifier, or {@code null} if it does not exist
|
||||
*/
|
||||
default URL getIssuer() {
|
||||
default @Nullable URL getIssuer() {
|
||||
return this.getClaimAsURL(IdTokenClaimNames.ISS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Subject identifier {@code (sub)}.
|
||||
* @return the Subject identifier
|
||||
* Returns the Subject identifier {@code (sub)}, or {@code null} if it does not exist.
|
||||
* @return the Subject identifier, or {@code null} if it does not exist
|
||||
*/
|
||||
@Override
|
||||
default String getSubject() {
|
||||
default @Nullable 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
|
||||
* Returns the Audience(s) {@code (aud)} that this ID Token is intended for, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return the Audience(s) that this ID Token is intended for, or {@code null} if it
|
||||
* does not exist
|
||||
*/
|
||||
default List<String> getAudience() {
|
||||
default @Nullable 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
|
||||
* be accepted, or {@code null} if it does not exist.
|
||||
* @return the Expiration time on or after which the ID Token MUST NOT be accepted, or
|
||||
* {@code null} if it does not exist
|
||||
*/
|
||||
default Instant getExpiresAt() {
|
||||
default @Nullable 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
|
||||
* Returns the time at which the ID Token was issued {@code (iat)}, or {@code null} if
|
||||
* it does not exist.
|
||||
* @return the time at which the ID Token was issued, or {@code null} if it does not
|
||||
* exist
|
||||
*/
|
||||
default Instant getIssuedAt() {
|
||||
default @Nullable 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
|
||||
* Returns the time when the End-User authentication occurred {@code (auth_time)}, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return the time when the End-User authentication occurred, or {@code null} if it
|
||||
* does not exist
|
||||
*/
|
||||
default Instant getAuthenticatedAt() {
|
||||
default @Nullable 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
|
||||
* with an ID Token, and to mitigate replay attacks, or {@code null} if it does not
|
||||
* exist.
|
||||
* @return the nonce used to associate a Client session with an ID Token, or
|
||||
* {@code null} if it does not exist
|
||||
*/
|
||||
default String getNonce() {
|
||||
default @Nullable String getNonce() {
|
||||
return this.getClaimAsString(IdTokenClaimNames.NONCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Authentication Context Class Reference {@code (acr)}.
|
||||
* @return the Authentication Context Class Reference
|
||||
* Returns the Authentication Context Class Reference {@code (acr)}, or {@code null}
|
||||
* if it does not exist.
|
||||
* @return the Authentication Context Class Reference, or {@code null} if it does not
|
||||
* exist
|
||||
*/
|
||||
default String getAuthenticationContextClass() {
|
||||
default @Nullable String getAuthenticationContextClass() {
|
||||
return this.getClaimAsString(IdTokenClaimNames.ACR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Authentication Methods References {@code (amr)}.
|
||||
* @return the Authentication Methods References
|
||||
* Returns the Authentication Methods References {@code (amr)}, or {@code null} if it
|
||||
* does not exist.
|
||||
* @return the Authentication Methods References, or {@code null} if it does not exist
|
||||
*/
|
||||
default List<String> getAuthenticationMethods() {
|
||||
default @Nullable 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
|
||||
* Returns the Authorized party {@code (azp)} to which the ID Token was issued, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return the Authorized party to which the ID Token was issued, or {@code null} if
|
||||
* it does not exist
|
||||
*/
|
||||
default String getAuthorizedParty() {
|
||||
default @Nullable String getAuthorizedParty() {
|
||||
return this.getClaimAsString(IdTokenClaimNames.AZP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Access Token hash value {@code (at_hash)}.
|
||||
* @return the Access Token hash value
|
||||
* Returns the Access Token hash value {@code (at_hash)}, or {@code null} if it does
|
||||
* not exist.
|
||||
* @return the Access Token hash value, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getAccessTokenHash() {
|
||||
default @Nullable String getAccessTokenHash() {
|
||||
return this.getClaimAsString(IdTokenClaimNames.AT_HASH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Authorization Code hash value {@code (c_hash)}.
|
||||
* @return the Authorization Code hash value
|
||||
* Returns the Authorization Code hash value {@code (c_hash)}, or {@code null} if it
|
||||
* does not exist.
|
||||
* @return the Authorization Code hash value, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getAuthorizationCodeHash() {
|
||||
default @Nullable String getAuthorizationCodeHash() {
|
||||
return this.getClaimAsString(IdTokenClaimNames.C_HASH);
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.oauth2.core.AbstractOAuth2Token;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@ -57,12 +59,14 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce
|
||||
/**
|
||||
* 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 issuedAt the time at which the ID Token was issued {@code (iat)}, may be
|
||||
* {@code null}
|
||||
* @param expiresAt the expiration time {@code (exp)} on or after which the ID Token
|
||||
* MUST NOT be accepted
|
||||
* MUST NOT be accepted, may be {@code null}
|
||||
* @param claims the claims about the authentication of the End-User
|
||||
*/
|
||||
public OidcIdToken(String tokenValue, Instant issuedAt, Instant expiresAt, Map<String, Object> claims) {
|
||||
public OidcIdToken(String tokenValue, @Nullable Instant issuedAt, @Nullable Instant expiresAt,
|
||||
Map<String, Object> claims) {
|
||||
super(tokenValue, issuedAt, expiresAt);
|
||||
Assert.notEmpty(claims, "claims cannot be empty");
|
||||
this.claims = Collections.unmodifiableMap(new LinkedHashMap<>(claims));
|
||||
@ -246,12 +250,14 @@ public class OidcIdToken extends AbstractOAuth2Token implements IdTokenClaimAcce
|
||||
* @return The constructed {@link OidcIdToken}
|
||||
*/
|
||||
public OidcIdToken build() {
|
||||
Instant iat = toInstant(this.claims.get(IdTokenClaimNames.IAT));
|
||||
Instant exp = toInstant(this.claims.get(IdTokenClaimNames.EXP));
|
||||
Object iatObj = this.claims.get(IdTokenClaimNames.IAT);
|
||||
Object expObj = this.claims.get(IdTokenClaimNames.EXP);
|
||||
Instant iat = toInstant(iatObj);
|
||||
Instant exp = toInstant(expObj);
|
||||
return new OidcIdToken(this.tokenValue, iat, exp, this.claims);
|
||||
}
|
||||
|
||||
private Instant toInstant(Object timestamp) {
|
||||
private @Nullable Instant toInstant(@Nullable Object timestamp) {
|
||||
if (timestamp != null) {
|
||||
Assert.isInstanceOf(Instant.class, timestamp, "timestamps must be of type Instant");
|
||||
}
|
||||
|
||||
@ -19,6 +19,8 @@ package org.springframework.security.oauth2.core.oidc;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.oauth2.core.ClaimAccessor;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@ -41,152 +43,166 @@ import org.springframework.util.CollectionUtils;
|
||||
public interface StandardClaimAccessor extends ClaimAccessor {
|
||||
|
||||
/**
|
||||
* Returns the Subject identifier {@code (sub)}.
|
||||
* @return the Subject identifier
|
||||
* Returns the Subject identifier {@code (sub)}, or {@code null} if it does not exist.
|
||||
* @return the Subject identifier, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getSubject() {
|
||||
default @Nullable String getSubject() {
|
||||
return this.getClaimAsString(StandardClaimNames.SUB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's full name {@code (name)} in displayable form.
|
||||
* @return the user's full name
|
||||
* Returns the user's full name {@code (name)} in displayable form, or {@code null} if
|
||||
* it does not exist.
|
||||
* @return the user's full name, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getFullName() {
|
||||
default @Nullable 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)
|
||||
* Returns the user's given name(s) or first name(s) {@code (given_name)}, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return the user's given name(s), or {@code null} if it does not exist
|
||||
*/
|
||||
default String getGivenName() {
|
||||
default @Nullable 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)
|
||||
* Returns the user's surname(s) or last name(s) {@code (family_name)}, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return the user's family names(s), or {@code null} if it does not exist
|
||||
*/
|
||||
default String getFamilyName() {
|
||||
default @Nullable 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)
|
||||
* Returns the user's middle name(s) {@code (middle_name)}, or {@code null} if it does
|
||||
* not exist.
|
||||
* @return the user's middle name(s), or {@code null} if it does not exist
|
||||
*/
|
||||
default String getMiddleName() {
|
||||
default @Nullable 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
|
||||
* the {@code (given_name)}, or {@code null} if it does not exist.
|
||||
* @return the user's nick name, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getNickName() {
|
||||
default @Nullable 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
|
||||
* be referred to, or {@code null} if it does not exist.
|
||||
* @return the user's preferred user name, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getPreferredUsername() {
|
||||
default @Nullable 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
|
||||
* Returns the URL of the user's profile page {@code (profile)}, or {@code null} if it
|
||||
* does not exist.
|
||||
* @return the URL of the user's profile page, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getProfile() {
|
||||
default @Nullable 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
|
||||
* Returns the URL of the user's profile picture {@code (picture)}, or {@code null} if
|
||||
* it does not exist.
|
||||
* @return the URL of the user's profile picture, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getPicture() {
|
||||
default @Nullable 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
|
||||
* Returns the URL of the user's web page or blog {@code (website)}, or {@code null}
|
||||
* if it does not exist.
|
||||
* @return the URL of the user's web page or blog, or {@code null} if it does not
|
||||
* exist
|
||||
*/
|
||||
default String getWebsite() {
|
||||
default @Nullable 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
|
||||
* Returns the user's preferred e-mail address {@code (email)}, or {@code null} if it
|
||||
* does not exist.
|
||||
* @return the user's preferred e-mail address, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getEmail() {
|
||||
default @Nullable 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}.
|
||||
* {@code (email_verified)}, otherwise {@code false}, or {@code null} if it does not
|
||||
* exist.
|
||||
* @return {@code true} if the user's e-mail address has been verified, otherwise
|
||||
* {@code false}
|
||||
* {@code false}, or {@code null} if it does not exist
|
||||
*/
|
||||
default Boolean getEmailVerified() {
|
||||
default @Nullable Boolean getEmailVerified() {
|
||||
return this.getClaimAsBoolean(StandardClaimNames.EMAIL_VERIFIED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's gender {@code (gender)}.
|
||||
* @return the user's gender
|
||||
* Returns the user's gender {@code (gender)}, or {@code null} if it does not exist.
|
||||
* @return the user's gender, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getGender() {
|
||||
default @Nullable String getGender() {
|
||||
return this.getClaimAsString(StandardClaimNames.GENDER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's birth date {@code (birthdate)}.
|
||||
* @return the user's birth date
|
||||
* Returns the user's birth date {@code (birthdate)}, or {@code null} if it does not
|
||||
* exist.
|
||||
* @return the user's birth date, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getBirthdate() {
|
||||
default @Nullable String getBirthdate() {
|
||||
return this.getClaimAsString(StandardClaimNames.BIRTHDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's time zone {@code (zoneinfo)}.
|
||||
* @return the user's time zone
|
||||
* Returns the user's time zone {@code (zoneinfo)}, or {@code null} if it does not
|
||||
* exist.
|
||||
* @return the user's time zone, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getZoneInfo() {
|
||||
default @Nullable String getZoneInfo() {
|
||||
return this.getClaimAsString(StandardClaimNames.ZONEINFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's locale {@code (locale)}.
|
||||
* @return the user's locale
|
||||
* Returns the user's locale {@code (locale)}, or {@code null} if it does not exist.
|
||||
* @return the user's locale, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getLocale() {
|
||||
default @Nullable String getLocale() {
|
||||
return this.getClaimAsString(StandardClaimNames.LOCALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's preferred phone number {@code (phone_number)}.
|
||||
* @return the user's preferred phone number
|
||||
* Returns the user's preferred phone number {@code (phone_number)}, or {@code null}
|
||||
* if it does not exist.
|
||||
* @return the user's preferred phone number, or {@code null} if it does not exist
|
||||
*/
|
||||
default String getPhoneNumber() {
|
||||
default @Nullable 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}.
|
||||
* {@code (phone_number_verified)}, otherwise {@code false}, or {@code null} if it
|
||||
* does not exist.
|
||||
* @return {@code true} if the user's phone number has been verified, otherwise
|
||||
* {@code false}
|
||||
* {@code false}, or {@code null} if it does not exist
|
||||
*/
|
||||
default Boolean getPhoneNumberVerified() {
|
||||
default @Nullable Boolean getPhoneNumberVerified() {
|
||||
return this.getClaimAsBoolean(StandardClaimNames.PHONE_NUMBER_VERIFIED);
|
||||
}
|
||||
|
||||
@ -201,10 +217,12 @@ public interface StandardClaimAccessor extends ClaimAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time the user's information was last updated {@code (updated_at)}.
|
||||
* @return the time the user's information was last updated
|
||||
* Returns the time the user's information was last updated {@code (updated_at)}, or
|
||||
* {@code null} if it does not exist.
|
||||
* @return the time the user's information was last updated, or {@code null} if it
|
||||
* does not exist
|
||||
*/
|
||||
default Instant getUpdatedAt() {
|
||||
default @Nullable Instant getUpdatedAt() {
|
||||
return this.getClaimAsInstant(StandardClaimNames.UPDATED_AT);
|
||||
}
|
||||
|
||||
|
||||
@ -18,4 +18,7 @@
|
||||
* Support classes that model the OpenID Connect Core 1.0 Request and Response messages
|
||||
* from the Authorization Endpoint and Token Endpoint.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.oidc.endpoint;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Core classes and interfaces providing support for OpenID Connect Core 1.0.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.oidc;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@ -20,6 +20,8 @@ import java.io.Serial;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
@ -48,52 +50,52 @@ public class DefaultOidcUser extends DefaultOAuth2User implements OidcUser {
|
||||
|
||||
private final OidcIdToken idToken;
|
||||
|
||||
private final OidcUserInfo userInfo;
|
||||
private final @Nullable OidcUserInfo userInfo;
|
||||
|
||||
/**
|
||||
* Constructs a {@code DefaultOidcUser} using the provided parameters.
|
||||
* @param authorities the authorities granted to the user
|
||||
* @param authorities the authorities granted to the user, may be {@code null}
|
||||
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
|
||||
*/
|
||||
public DefaultOidcUser(Collection<? extends GrantedAuthority> authorities, OidcIdToken idToken) {
|
||||
public DefaultOidcUser(@Nullable Collection<? extends 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 authorities the authorities granted to the user, may be {@code null}
|
||||
* @param idToken the {@link OidcIdToken ID Token} containing claims about the user
|
||||
* @param nameAttributeKey the key used to access the user's "name" from
|
||||
* {@link #getAttributes()}
|
||||
*/
|
||||
public DefaultOidcUser(Collection<? extends GrantedAuthority> authorities, OidcIdToken idToken,
|
||||
public DefaultOidcUser(@Nullable Collection<? extends 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 authorities the authorities granted to the user, may be {@code null}
|
||||
* @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(Collection<? extends GrantedAuthority> authorities, OidcIdToken idToken,
|
||||
OidcUserInfo userInfo) {
|
||||
public DefaultOidcUser(@Nullable Collection<? extends GrantedAuthority> authorities, OidcIdToken idToken,
|
||||
@Nullable 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 authorities the authorities granted to the user, may be {@code null}
|
||||
* @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 "name" from
|
||||
* {@link #getAttributes()}
|
||||
*/
|
||||
public DefaultOidcUser(Collection<? extends GrantedAuthority> authorities, OidcIdToken idToken,
|
||||
OidcUserInfo userInfo, String nameAttributeKey) {
|
||||
public DefaultOidcUser(@Nullable Collection<? extends GrantedAuthority> authorities, OidcIdToken idToken,
|
||||
@Nullable OidcUserInfo userInfo, String nameAttributeKey) {
|
||||
super(authorities, OidcUserAuthority.collectClaims(idToken, userInfo), nameAttributeKey);
|
||||
this.idToken = idToken;
|
||||
this.userInfo = userInfo;
|
||||
@ -110,7 +112,7 @@ public class DefaultOidcUser extends DefaultOAuth2User implements OidcUser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public OidcUserInfo getUserInfo() {
|
||||
public @Nullable OidcUserInfo getUserInfo() {
|
||||
return this.userInfo;
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ package org.springframework.security.oauth2.core.oidc.user;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.AuthenticatedPrincipal;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.oidc.IdTokenClaimAccessor;
|
||||
@ -65,10 +67,11 @@ public interface OidcUser extends OAuth2User, IdTokenClaimAccessor {
|
||||
Map<String, Object> getClaims();
|
||||
|
||||
/**
|
||||
* Returns the {@link OidcUserInfo UserInfo} containing claims about the user.
|
||||
* @return the {@link OidcUserInfo} containing claims about the user.
|
||||
* Returns the {@link OidcUserInfo UserInfo} containing claims about the user, or
|
||||
* {@code null} if not present.
|
||||
* @return the {@link OidcUserInfo} containing claims about the user, or {@code null}
|
||||
*/
|
||||
OidcUserInfo getUserInfo();
|
||||
@Nullable OidcUserInfo getUserInfo();
|
||||
|
||||
/**
|
||||
* Returns the {@link OidcIdToken ID Token} containing claims about the user.
|
||||
|
||||
@ -19,8 +19,10 @@ package org.springframework.security.oauth2.core.oidc.user;
|
||||
import java.io.Serial;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
|
||||
import org.springframework.security.oauth2.core.oidc.OidcIdToken;
|
||||
@ -42,7 +44,7 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
|
||||
|
||||
private final OidcIdToken idToken;
|
||||
|
||||
private final OidcUserInfo userInfo;
|
||||
private final @Nullable OidcUserInfo userInfo;
|
||||
|
||||
/**
|
||||
* Constructs a {@code OidcUserAuthority} using the provided parameters.
|
||||
@ -59,7 +61,7 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
|
||||
* @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user,
|
||||
* may be {@code null}
|
||||
*/
|
||||
public OidcUserAuthority(OidcIdToken idToken, OidcUserInfo userInfo) {
|
||||
public OidcUserAuthority(OidcIdToken idToken, @Nullable OidcUserInfo userInfo) {
|
||||
this("OIDC_USER", idToken, userInfo);
|
||||
}
|
||||
|
||||
@ -70,10 +72,11 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
|
||||
* @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user,
|
||||
* may be {@code null}
|
||||
* @param userNameAttributeName the attribute name used to access the user's name from
|
||||
* the attributes
|
||||
* the attributes, may be {@code null}
|
||||
* @since 6.4
|
||||
*/
|
||||
public OidcUserAuthority(OidcIdToken idToken, OidcUserInfo userInfo, @Nullable String userNameAttributeName) {
|
||||
public OidcUserAuthority(OidcIdToken idToken, @Nullable OidcUserInfo userInfo,
|
||||
@Nullable String userNameAttributeName) {
|
||||
this("OIDC_USER", idToken, userInfo, userNameAttributeName);
|
||||
}
|
||||
|
||||
@ -84,7 +87,7 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
|
||||
* @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user,
|
||||
* may be {@code null}
|
||||
*/
|
||||
public OidcUserAuthority(String authority, OidcIdToken idToken, OidcUserInfo userInfo) {
|
||||
public OidcUserAuthority(String authority, OidcIdToken idToken, @Nullable OidcUserInfo userInfo) {
|
||||
this(authority, idToken, userInfo, IdTokenClaimNames.SUB);
|
||||
}
|
||||
|
||||
@ -95,10 +98,10 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
|
||||
* @param userInfo the {@link OidcUserInfo UserInfo} containing claims about the user,
|
||||
* may be {@code null}
|
||||
* @param userNameAttributeName the attribute name used to access the user's name from
|
||||
* the attributes
|
||||
* the attributes, may be {@code null}
|
||||
* @since 6.4
|
||||
*/
|
||||
public OidcUserAuthority(String authority, OidcIdToken idToken, OidcUserInfo userInfo,
|
||||
public OidcUserAuthority(String authority, OidcIdToken idToken, @Nullable OidcUserInfo userInfo,
|
||||
@Nullable String userNameAttributeName) {
|
||||
super(authority, collectClaims(idToken, userInfo), userNameAttributeName);
|
||||
this.idToken = idToken;
|
||||
@ -118,7 +121,7 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
|
||||
* {@code null}.
|
||||
* @return the {@link OidcUserInfo} containing claims about the user, or {@code null}
|
||||
*/
|
||||
public OidcUserInfo getUserInfo() {
|
||||
public @Nullable OidcUserInfo getUserInfo() {
|
||||
return this.userInfo;
|
||||
}
|
||||
|
||||
@ -137,8 +140,7 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
|
||||
if (!this.getIdToken().equals(that.getIdToken())) {
|
||||
return false;
|
||||
}
|
||||
return (this.getUserInfo() != null) ? this.getUserInfo().equals(that.getUserInfo())
|
||||
: that.getUserInfo() == null;
|
||||
return Objects.equals(this.getUserInfo(), that.getUserInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,7 +151,7 @@ public class OidcUserAuthority extends OAuth2UserAuthority {
|
||||
return result;
|
||||
}
|
||||
|
||||
static Map<String, Object> collectClaims(OidcIdToken idToken, OidcUserInfo userInfo) {
|
||||
static Map<String, Object> collectClaims(OidcIdToken idToken, @Nullable OidcUserInfo userInfo) {
|
||||
Assert.notNull(idToken, "idToken cannot be null");
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
if (userInfo != null) {
|
||||
|
||||
@ -18,4 +18,7 @@
|
||||
* Provides a model for an OpenID Connect Core 1.0 representation of a user
|
||||
* {@code Principal}.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.oidc.user;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@ -18,4 +18,7 @@
|
||||
* Core classes and interfaces providing support for the OAuth 2.0 Authorization
|
||||
* Framework.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@ -27,6 +27,8 @@ import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.util.Assert;
|
||||
@ -59,17 +61,17 @@ public class DefaultOAuth2User implements OAuth2User, Serializable {
|
||||
|
||||
/**
|
||||
* Constructs a {@code DefaultOAuth2User} using the provided parameters.
|
||||
* @param authorities the authorities granted to the user
|
||||
* @param authorities the authorities granted to the user, may be {@code null}
|
||||
* @param attributes the attributes about the user
|
||||
* @param nameAttributeKey the key used to access the user's "name" from
|
||||
* {@link #getAttributes()}
|
||||
*/
|
||||
public DefaultOAuth2User(Collection<? extends GrantedAuthority> authorities, Map<String, Object> attributes,
|
||||
String nameAttributeKey) {
|
||||
public DefaultOAuth2User(@Nullable Collection<? extends GrantedAuthority> authorities,
|
||||
Map<String, Object> attributes, String nameAttributeKey) {
|
||||
Assert.notEmpty(attributes, "attributes cannot be empty");
|
||||
Assert.hasText(nameAttributeKey, "nameAttributeKey cannot be empty");
|
||||
Assert.notNull(attributes.get(nameAttributeKey),
|
||||
"Attribute value for '" + nameAttributeKey + "' cannot be null");
|
||||
Object nameAttributeValue = attributes.get(nameAttributeKey);
|
||||
Assert.notNull(nameAttributeValue, "Attribute value for '" + nameAttributeKey + "' cannot be null");
|
||||
|
||||
this.authorities = (authorities != null)
|
||||
? Collections.unmodifiableSet(new LinkedHashSet<>(this.sortAuthorities(authorities)))
|
||||
@ -80,7 +82,9 @@ public class DefaultOAuth2User implements OAuth2User, Serializable {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.getAttribute(this.nameAttributeKey).toString();
|
||||
Object nameAttributeValue = this.getAttribute(this.nameAttributeKey);
|
||||
Assert.notNull(nameAttributeValue, "Name attribute value cannot be null");
|
||||
return nameAttributeValue.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -22,7 +22,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@ -41,7 +42,7 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
||||
|
||||
private final Map<String, Object> attributes;
|
||||
|
||||
private final String userNameAttributeName;
|
||||
private final @Nullable String userNameAttributeName;
|
||||
|
||||
/**
|
||||
* Constructs a {@code OAuth2UserAuthority} using the provided parameters and defaults
|
||||
@ -78,10 +79,11 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
||||
* @param authority the authority granted to the user
|
||||
* @param attributes the attributes about the user
|
||||
* @param userNameAttributeName the attribute name used to access the user's name from
|
||||
* the attributes
|
||||
* the attributes, may be {@code null}
|
||||
* @since 6.4
|
||||
*/
|
||||
public OAuth2UserAuthority(String authority, Map<String, Object> attributes, String userNameAttributeName) {
|
||||
public OAuth2UserAuthority(String authority, Map<String, Object> attributes,
|
||||
@Nullable String userNameAttributeName) {
|
||||
Assert.hasText(authority, "authority cannot be empty");
|
||||
Assert.notEmpty(attributes, "attributes cannot be empty");
|
||||
this.authority = authority;
|
||||
@ -104,11 +106,11 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
||||
|
||||
/**
|
||||
* Returns the attribute name used to access the user's name from the attributes.
|
||||
* @return the attribute name used to access the user's name from the attributes
|
||||
* @return the attribute name used to access the user's name from the attributes, or
|
||||
* {@code null} if not available
|
||||
* @since 6.4
|
||||
*/
|
||||
@Nullable
|
||||
public String getUserNameAttributeName() {
|
||||
public @Nullable String getUserNameAttributeName() {
|
||||
return this.userNameAttributeName;
|
||||
}
|
||||
|
||||
@ -137,8 +139,9 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
||||
}
|
||||
}
|
||||
else {
|
||||
Object thatValue = convertURLIfNecessary(thatAttributes.get(key));
|
||||
if (!value.equals(thatValue)) {
|
||||
Object thatValue = thatAttributes.get(key);
|
||||
Object convertedThatValue = convertURLIfNecessary(thatValue);
|
||||
if (!value.equals(convertedThatValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -165,9 +168,10 @@ public class OAuth2UserAuthority implements GrantedAuthority {
|
||||
|
||||
/**
|
||||
* @return {@code URL} converted to a string since {@code URL} shouldn't be used for
|
||||
* equality/hashCode. For other instances the value is returned as is.
|
||||
* equality/hashCode. For other instances the value is returned as is (including
|
||||
* null).
|
||||
*/
|
||||
private static Object convertURLIfNecessary(Object value) {
|
||||
private static @Nullable Object convertURLIfNecessary(@Nullable Object value) {
|
||||
return (value instanceof URL) ? ((URL) value).toExternalForm() : value;
|
||||
}
|
||||
|
||||
|
||||
@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Provides a model for an OAuth 2.0 representation of a user {@code Principal}.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.user;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Web support classes for OAuth 2.0 and OpenID Connect.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.web;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reactive functional web support classes for OAuth 2.0 and OpenID Connect.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.web.reactive.function;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2004-present 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
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Reactive web support classes for OAuth 2.0 and OpenID Connect.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.security.oauth2.core.web.reactive;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@ -76,11 +76,11 @@ public class BearerTokenAuthenticationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNameWhenHasNoSubjectThenReturnsNull() {
|
||||
public void getNameWhenHasNoSubjectThenReturnsEmptyString() {
|
||||
OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(
|
||||
Collections.singletonMap("claim", "value"), null);
|
||||
BearerTokenAuthentication authenticated = new BearerTokenAuthentication(principal, this.token, null);
|
||||
assertThat(authenticated.getName()).isNull();
|
||||
assertThat(authenticated.getName()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user