or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

aot-native-support.mdauthentication-core.mdauthentication-events.mdauthentication-management.mdauthentication-tokens.mdauthorities.mdauthorization.mdcompromised-password.mdconcurrent-async.mddao-authentication.mdexpression-access-control.mdindex.mdjaas-authentication.mdjackson-serialization.mdmethod-security.mdobservation-metrics.mdone-time-tokens.mdprovisioning.mdsecurity-context.mdsession-management.mduser-details.md
tile.json

authentication-core.mddocs/

Authentication Core

Core authentication interfaces and classes that form the foundation of Spring Security's authentication model. This includes the primary Authentication interface, granted authorities, authentication exceptions, and supporting interfaces for credential management.

Key Information for Agents

Core Concepts:

  • Authentication represents both authentication requests (unauthenticated) and authenticated principals
  • Authentication tokens are immutable after authentication (use toBuilder() to create modified copies since 7.0)
  • setAuthenticated(true) can only be called by trusted AuthenticationManager implementations (throws IllegalArgumentException if called incorrectly)
  • Credentials should be erased after authentication for security (CredentialsContainer interface)
  • getAuthorities() never returns null (returns empty collection if no authorities)
  • Authentication extends Principal (can use getName() to get username)

Default Behaviors:

  • Authentication tokens created via constructors are unauthenticated by default (isAuthenticated() == false)
  • Use static factory methods (authenticated(), unauthenticated()) for clarity and type safety
  • AbstractAuthenticationToken sets authenticated=false in constructor (must be set to true by AuthenticationManager)
  • Credentials are erased after successful authentication by default in ProviderManager (eraseCredentialsAfterAuthentication=true)
  • getPrincipal() returns UserDetails for username/password auth, or String username for other types
  • getCredentials() typically returns null after successful authentication (erased for security)

Common Patterns:

  • Authentication Request: Create unauthenticated token → Authenticate via manager → Set in context
  • Modify Authentication: Use toBuilder() to modify existing authentication (since 7.0) - creates new instance
  • Check Authentication: Always check isAuthenticated() before accessing principal/authorities
  • Exception Handling: Handle AuthenticationException hierarchy for different failure scenarios (catch specific exceptions first)
  • Principal Access: Check if principal is UserDetails before casting: if (auth.getPrincipal() instanceof UserDetails)

Exception Hierarchy:

  • AuthenticationException - Base for all authentication failures (catch last)
  • AccountStatusException - Account-related issues (disabled, locked, expired) - abstract base
  • BadCredentialsException - Invalid credentials (most common, don't reveal if username exists)
  • DisabledException - Account disabled (!user.isEnabled())
  • LockedException - Account locked (!user.isAccountNonLocked())
  • AccountExpiredException - Account expired (!user.isAccountNonExpired())
  • CredentialsExpiredException - Credentials expired (!user.isCredentialsNonExpired())
  • ProviderNotFoundException - No provider supports the authentication type
  • AuthenticationServiceException - Service error (e.g., database unavailable)
  • Always catch specific exceptions before general AuthenticationException

Thread Safety:

  • Authentication objects are immutable after authentication (thread-safe for reading)
  • toBuilder() creates a new builder for modification (no shared state)
  • Multiple threads can safely read the same Authentication instance
  • Modifications should create new instances via toBuilder(), not mutate existing ones
  • AbstractAuthenticationToken is thread-safe for concurrent reads after authentication

Lifecycle:

  • Tokens created as unauthenticated (for requests) or authenticated (for results)
  • Authentication performed by AuthenticationManager (sets authenticated=true)
  • Credentials erased after authentication (via eraseCredentials())
  • Tokens stored in SecurityContext after successful authentication
  • Tokens serialized for session storage (requires Jackson modules for custom types)

Exceptions:

  • IllegalArgumentException - Thrown by setAuthenticated(true) if called on already-authenticated token
  • AuthenticationException - Base exception (catch specific subclasses first)
  • BadCredentialsException - Invalid credentials (most common)
  • AccountStatusException subclasses - Account state issues
  • ProviderNotFoundException - No provider supports authentication type

Edge Cases:

  • Null principal: getPrincipal() may return null (check before use)
  • Principal type: getPrincipal() may return String (username) or UserDetails object (check with instanceof)
  • Null credentials: getCredentials() is typically null after successful authentication (erased for security)
  • Null details: getDetails() may return null (contains request-specific information like IP, session ID)
  • Empty authorities: getAuthorities() returns empty collection, not null, for unauthenticated tokens
  • Already authenticated: setAuthenticated(true) on already-authenticated token throws IllegalArgumentException
  • Null authentication: SecurityContext.getAuthentication() may return null (valid state for unauthenticated users)
  • Token immutability: Cannot modify authenticated tokens directly (use toBuilder() since 7.0)
  • Builder pattern: toBuilder() creates new builder, modifications don't affect original token

Core Interfaces

Authentication

The primary interface representing an authentication request or an authenticated principal. It extends both Principal and Serializable.

package org.springframework.security.core;

interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    Object getCredentials();
    Object getDetails();
    Object getPrincipal();
    boolean isAuthenticated();
    void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
    Builder<?> toBuilder();  // since 7.0

    interface Builder<B extends Builder<B>> {
        B principal(Object principal);
        B credentials(Object credentials);
        B authorities(Consumer<Collection<GrantedAuthority>> authorities);
        B details(Object details);
        B authenticated(boolean authenticated);
        Authentication build();
    }
}

Method Details:

  • getAuthorities() - Returns the authorities granted to the principal. Never returns null (returns empty collection if none). Collection is immutable after authentication.
  • getCredentials() - Returns credentials (usually a password) for authentication. May be null after successful authentication (erased for security). Typically contains raw password before authentication.
  • getDetails() - Returns additional details about the authentication request (e.g., IP address, certificate serial number, session ID). May be null. Set by authentication providers or filters.
  • getPrincipal() - Returns the identity of the principal. Usually a UserDetails instance for username/password authentication, or String username for other types. May be null (check before use).
  • isAuthenticated() - Returns true if the token has been authenticated by an AuthenticationManager. Default is false for tokens created via constructors.
  • setAuthenticated(boolean) - Sets the authenticated status. Throws IllegalArgumentException if attempting to set an authenticated token to trusted without going through an AuthenticationManager. Only trusted managers should call this.
  • toBuilder() - Creates a builder from this authentication (since 7.0). Returns a new builder that can be used to create a modified copy. Original token is not modified (immutability).

Usage Example:

// Creating an authenticated token using concrete implementations
UsernamePasswordAuthenticationToken auth =
    UsernamePasswordAuthenticationToken.authenticated(
        "username",
        null,  // credentials typically null after authentication
        AuthorityUtils.createAuthorityList("ROLE_USER", "ROLE_ADMIN")
    );
// auth.isAuthenticated() == true

// Using toBuilder() to modify existing authentication (since 7.0)
Authentication modified = auth.toBuilder()
    .authorities(authorities -> {
        authorities.clear();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        authorities.add(new SimpleGrantedAuthority("ROLE_MODERATOR"));
    })
    .details(customDetails)
    .build();
// Original 'auth' is unchanged (immutable)

// Getting current authentication (null-safe)
Authentication current = SecurityContextHolder.getContext().getAuthentication();
if (current != null && current.isAuthenticated()) {
    String username = current.getName();  // Works because Authentication extends Principal
    Object principal = current.getPrincipal();
    Collection<? extends GrantedAuthority> authorities = current.getAuthorities();
    
    // Check principal type
    if (principal instanceof UserDetails) {
        UserDetails userDetails = (UserDetails) principal;
        String email = userDetails.getUsername();
    } else if (principal instanceof String) {
        String username = (String) principal;
    }
}

// Creating unauthenticated token for authentication request
UsernamePasswordAuthenticationToken authRequest =
    UsernamePasswordAuthenticationToken.unauthenticated("username", "password");
// authRequest.isAuthenticated() == false

// Authenticating via manager with comprehensive exception handling
try {
    Authentication result = authenticationManager.authenticate(authRequest);
    // result.isAuthenticated() == true
    SecurityContextHolder.getContext().setAuthentication(result);
} catch (BadCredentialsException e) {
    // Invalid credentials - don't reveal if username exists
    Authentication failedRequest = e.getAuthenticationRequest();
    log.error("Authentication failed: invalid credentials for user: {}", 
        failedRequest != null ? failedRequest.getName() : "unknown");
    // Return generic error message to prevent user enumeration
} catch (DisabledException e) {
    // Account disabled
    log.error("Authentication failed: account disabled for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
} catch (LockedException e) {
    // Account locked
    log.error("Authentication failed: account locked for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
} catch (AccountExpiredException e) {
    // Account expired
    log.error("Authentication failed: account expired for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
} catch (CredentialsExpiredException e) {
    // Credentials expired
    log.error("Authentication failed: credentials expired for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
} catch (ProviderNotFoundException e) {
    // No provider supports this authentication type
    log.error("Authentication failed: no provider found for authentication type: {}", 
        authRequest.getClass().getName());
} catch (AuthenticationServiceException e) {
    // Service error (e.g., database unavailable)
    log.error("Authentication service error", e);
} catch (AuthenticationException e) {
    // Other authentication error (catch last)
    log.error("Authentication failed: {}", e.getMessage(), e);
}

GrantedAuthority

Represents an authority granted to an Authentication object.

package org.springframework.security.core;

interface GrantedAuthority extends Serializable {
    @Nullable String getAuthority();
}

Method Details:

  • getAuthority() - Returns a representation of the granted authority (usually a role name or fine-grained permission). Should not return null (though interface allows it for compatibility). Authority string is used for equality checks.

Usage Example:

GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_ADMIN");
String role = authority.getAuthority(); // "ROLE_ADMIN"

// Checking authorities
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
    boolean hasRole = auth.getAuthorities().stream()
        .anyMatch(auth -> auth.getAuthority().equals("ROLE_ADMIN"));
    
    // Checking multiple authorities
    boolean hasAnyRole = auth.getAuthorities().stream()
        .map(GrantedAuthority::getAuthority)
        .anyMatch(auth -> auth.equals("ROLE_ADMIN") || auth.equals("ROLE_USER"));
    
    // Check if user has all required roles
    Set<String> requiredRoles = Set.of("ROLE_ADMIN", "ROLE_MANAGER");
    Set<String> userRoles = auth.getAuthorities().stream()
        .map(GrantedAuthority::getAuthority)
        .collect(Collectors.toSet());
    boolean hasAllRoles = userRoles.containsAll(requiredRoles);
}

AuthenticatedPrincipal

Represents an authenticated principal with a name.

package org.springframework.security.core;

interface AuthenticatedPrincipal {
    String getName();
}

Method Details:

  • getName() - Returns the name that uniquely identifies the principal. Cannot return null.

Usage Example:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
    String name = auth.getName(); // Works because Authentication extends Principal
    
    // Or if principal implements AuthenticatedPrincipal
    if (auth.getPrincipal() instanceof AuthenticatedPrincipal) {
        String principalName = ((AuthenticatedPrincipal) auth.getPrincipal()).getName();
    }
}

CredentialsContainer

Indicates that an implementing object contains credentials that should be erased after successful authentication.

package org.springframework.security.core;

interface CredentialsContainer {
    void eraseCredentials();
}

Method Details:

  • eraseCredentials() - Erases sensitive credential information to minimize the time it's stored in memory. Should recursively erase credentials from nested objects that implement CredentialsContainer. Called automatically by ProviderManager after successful authentication.

Usage Example:

// After successful authentication (typically automatic)
if (authentication instanceof CredentialsContainer) {
    ((CredentialsContainer) authentication).eraseCredentials();
}

// AbstractAuthenticationToken implements CredentialsContainer
// and automatically erases credentials from principal and details
// if they also implement CredentialsContainer

Core Classes

AbstractAuthenticationToken

Abstract base class for Authentication implementations providing common functionality.

package org.springframework.security.authentication;

abstract class AbstractAuthenticationToken implements Authentication, CredentialsContainer {
    protected AbstractAuthenticationToken(
        Collection<? extends GrantedAuthority> authorities);

    Collection<GrantedAuthority> getAuthorities();
    String getName();
    boolean isAuthenticated();
    void setAuthenticated(boolean authenticated) throws IllegalArgumentException;
    Object getDetails();
    void setDetails(Object details);
    void eraseCredentials();
    boolean equals(Object obj);
    int hashCode();
    String toString();
}

Method Details:

  • Constructor takes authorities and sets authenticated to false by default.
  • setAuthenticated(true) can only be called by trusted AuthenticationManager implementations. Throws IllegalArgumentException if called on an already-authenticated token.
  • eraseCredentials() recursively erases credentials from principal and details if they implement CredentialsContainer.
  • getName() extracts name from principal (calls principal.getName() if Principal, or principal.toString() otherwise).

Usage Example:

// Extending AbstractAuthenticationToken for custom authentication
public class ApiKeyAuthenticationToken extends AbstractAuthenticationToken {
    private final String apiKey;
    private final String clientId;

    // Unauthenticated constructor (for requests)
    public ApiKeyAuthenticationToken(String apiKey, String clientId) {
        super(null);  // No authorities yet
        this.apiKey = apiKey;
        this.clientId = clientId;
        setAuthenticated(false);
    }

    // Authenticated constructor (for results)
    public ApiKeyAuthenticationToken(String apiKey, String clientId,
            Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.apiKey = apiKey;
        this.clientId = clientId;
        super.setAuthenticated(true);  // Only in authenticated constructor
    }

    @Override
    public Object getPrincipal() {
        return clientId;
    }

    @Override
    public Object getCredentials() {
        return apiKey;
    }

    @Override
    public void eraseCredentials() {
        super.eraseCredentials();
        // Clear sensitive data (apiKey should be nulled)
        // Note: final fields cannot be nulled, consider using mutable wrapper
    }
}

Exceptions

AuthenticationException

Abstract base class for all authentication-related exceptions.

package org.springframework.security.core;

abstract class AuthenticationException extends RuntimeException {
    AuthenticationException(String msg);
    AuthenticationException(String msg, Throwable cause);

    Authentication getAuthenticationRequest();  // since 6.5
    void setAuthenticationRequest(Authentication authentication);  // since 6.5
}

Method Details:

  • getAuthenticationRequest() - Returns the authentication request that caused the exception (since 6.5). May return null if not set. Useful for logging failed authentication attempts.
  • setAuthenticationRequest(Authentication) - Sets the authentication request (since 6.5). Useful for logging and debugging. Called automatically by authentication providers.

Usage Example:

try {
    Authentication auth = authenticationManager.authenticate(authRequest);
} catch (AuthenticationException e) {
    Authentication failedRequest = e.getAuthenticationRequest();
    if (failedRequest != null) {
        log.error("Authentication failed for user: {}", failedRequest.getName());
        // Log additional context without exposing sensitive data
    }
    throw e;
}

Common Authentication Exceptions

package org.springframework.security.authentication;

// Invalid credentials
class BadCredentialsException extends AuthenticationException {
    BadCredentialsException(String msg);
    BadCredentialsException(String msg, Throwable cause);
}

// User account is disabled
class DisabledException extends AccountStatusException {
    DisabledException(String msg);
    DisabledException(String msg, Throwable cause);
}

// User account is locked
class LockedException extends AccountStatusException {
    LockedException(String msg);
    LockedException(String msg, Throwable cause);
}

// User account has expired
class AccountExpiredException extends AccountStatusException {
    AccountExpiredException(String msg);
    AccountExpiredException(String msg, Throwable cause);
}

// User credentials have expired
class CredentialsExpiredException extends AccountStatusException {
    CredentialsExpiredException(String msg);
    CredentialsExpiredException(String msg, Throwable cause);
}

// Abstract base for account status exceptions
abstract class AccountStatusException extends AuthenticationException {
    AccountStatusException(String msg);
    AccountStatusException(String msg, Throwable cause);
}

// Insufficient authentication (e.g., missing required factor)
class InsufficientAuthenticationException extends AuthenticationException {
    InsufficientAuthenticationException(String msg);
    InsufficientAuthenticationException(String msg, Throwable cause);
}

// Authentication service encountered an error
class AuthenticationServiceException extends AuthenticationException {
    AuthenticationServiceException(String msg);
    AuthenticationServiceException(String msg, Throwable cause);
}

// Internal authentication service error
class InternalAuthenticationServiceException extends AuthenticationException {
    InternalAuthenticationServiceException(String msg);
    InternalAuthenticationServiceException(String msg, Throwable cause);
}

// Authentication credentials not found
class AuthenticationCredentialsNotFoundException extends AuthenticationException {
    AuthenticationCredentialsNotFoundException(String msg);
    AuthenticationCredentialsNotFoundException(String msg, Throwable cause);
}

// No provider found to process authentication
class ProviderNotFoundException extends AuthenticationException {
    ProviderNotFoundException(String msg);
    ProviderNotFoundException(String msg, Throwable cause);
}

Usage Example:

try {
    Authentication auth = authenticationManager.authenticate(authRequest);
} catch (BadCredentialsException e) {
    // Invalid username or password - most common
    // Don't reveal whether username exists (security best practice)
    log.error("Invalid credentials for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
    // Return generic error: "Invalid username or password"
} catch (DisabledException e) {
    // Account is disabled
    log.error("Account disabled for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
} catch (LockedException e) {
    // Account is locked
    log.error("Account locked for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
} catch (AccountExpiredException e) {
    // Account has expired
    log.error("Account expired for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
} catch (CredentialsExpiredException e) {
    // Credentials have expired
    log.error("Credentials expired for user: {}", 
        e.getAuthenticationRequest() != null ? e.getAuthenticationRequest().getName() : "unknown");
} catch (ProviderNotFoundException e) {
    // No provider supports this authentication type
    log.error("No authentication provider found for: {}", 
        authRequest.getClass().getName());
} catch (AuthenticationServiceException e) {
    // Service error (e.g., database unavailable)
    log.error("Authentication service error", e);
} catch (AuthenticationException e) {
    // Other authentication error (catch last)
    log.error("Authentication failed", e);
}

Annotations

@Transient

Marks an Authentication implementation as transient, indicating it should not be persisted across sessions.

package org.springframework.security.core;

@Target(TYPE)
@Retention(RUNTIME)
@interface Transient {
}

Usage Example:

@Transient
public class TemporaryAuthenticationToken extends AbstractAuthenticationToken {
    // This token will not be persisted to HTTP session
    // Useful for temporary authentication that should not survive session serialization
    // Example: API key authentication, temporary access tokens
}

Utility Classes

SpringSecurityCoreVersion

Provides version information for Spring Security Core.

package org.springframework.security.core;

class SpringSecurityCoreVersion {
    static String getVersion();
    static final String SERIAL_VERSION_UID;
}

Method Details:

  • getVersion() - Returns the version string for Spring Security Core (e.g., "7.0.0").

Usage Example:

String version = SpringSecurityCoreVersion.getVersion();
log.info("Spring Security Core version: {}", version);

SpringSecurityMessageSource

Message source implementation for Spring Security messages supporting internationalization.

package org.springframework.security.core;

class SpringSecurityMessageSource extends ReloadableResourceBundleMessageSource {
    SpringSecurityMessageSource();
}

Usage Example:

MessageSource messageSource = new SpringSecurityMessageSource();
String message = messageSource.getMessage(
    "AbstractUserDetailsAuthenticationProvider.badCredentials",
    null,
    "Bad credentials",
    Locale.getDefault()
);

Authority Implementations

SimpleGrantedAuthority

Basic implementation of GrantedAuthority using a String for the role.

package org.springframework.security.core.authority;

final class SimpleGrantedAuthority implements GrantedAuthority {
    SimpleGrantedAuthority(String role);

    @Nullable String getAuthority();
    boolean equals(Object obj);
    int hashCode();
    String toString();
}

Usage Example:

GrantedAuthority adminRole = new SimpleGrantedAuthority("ROLE_ADMIN");
GrantedAuthority userRole = new SimpleGrantedAuthority("ROLE_USER");

List<GrantedAuthority> authorities = Arrays.asList(adminRole, userRole);

// Equality is based on authority string
SimpleGrantedAuthority role1 = new SimpleGrantedAuthority("ROLE_USER");
SimpleGrantedAuthority role2 = new SimpleGrantedAuthority("ROLE_USER");
assert role1.equals(role2); // true
assert role1.hashCode() == role2.hashCode(); // true

FactorGrantedAuthority

Granted authority representing an authentication factor with issued-at timestamp for multi-factor authentication support (new in Spring Security 7.0).

package org.springframework.security.core.authority;

final class FactorGrantedAuthority implements GrantedAuthority {
    // Standard factor authority constants
    public static final String AUTHORIZATION_CODE_AUTHORITY = "FACTOR_AUTHORIZATION_CODE";
    public static final String BEARER_AUTHORITY = "FACTOR_BEARER";
    public static final String CAS_AUTHORITY = "FACTOR_CAS";
    public static final String OTT_AUTHORITY = "FACTOR_OTT";
    public static final String PASSWORD_AUTHORITY = "FACTOR_PASSWORD";
    public static final String SAML_RESPONSE_AUTHORITY = "FACTOR_SAML_RESPONSE";
    public static final String WEBAUTHN_AUTHORITY = "FACTOR_WEBAUTHN";
    public static final String X509_AUTHORITY = "FACTOR_X509";

    // Factory methods for creating instances
    public static Builder withAuthority(String authority);
    public static Builder withFactor(String factor);
    public static FactorGrantedAuthority fromAuthority(String authority);
    public static FactorGrantedAuthority fromFactor(String factor);

    // Instance methods
    String getAuthority();
    Instant getIssuedAt();

    // Builder
    public static final class Builder {
        Builder issuedAt(Instant issuedAt);
        FactorGrantedAuthority build();
    }
}

Factory Methods:

  • fromAuthority(String) - Creates a FactorGrantedAuthority with the given full authority (defaults issued-at to now)
  • fromFactor(String) - Creates a FactorGrantedAuthority, automatically prefixing with "FACTOR_" (defaults issued-at to now)
  • withAuthority(String) - Returns a Builder for custom issued-at time with full authority
  • withFactor(String) - Returns a Builder for custom issued-at time, automatically prefixing with "FACTOR_"

Usage Example:

import org.springframework.security.core.authority.FactorGrantedAuthority;
import java.time.Instant;
import java.time.Duration;

// Using standard factor constants
GrantedAuthority passwordFactor =
    FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY);
GrantedAuthority ottFactor =
    FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.OTT_AUTHORITY);

// Using custom factors (automatically prefixed with "FACTOR_")
GrantedAuthority smsFactor = FactorGrantedAuthority.fromFactor("SMS");  // "FACTOR_SMS"
GrantedAuthority otpFactor = FactorGrantedAuthority.fromFactor("OTP");  // "FACTOR_OTP"

// Using builder for custom issued-at time
GrantedAuthority webauthnFactor = FactorGrantedAuthority
    .withAuthority(FactorGrantedAuthority.WEBAUTHN_AUTHORITY)
    .issuedAt(Instant.now())
    .build();

// Getting issued-at timestamp
if (factor instanceof FactorGrantedAuthority fga) {
    Instant issuedAt = fga.getIssuedAt();
    System.out.println("Factor issued at: " + issuedAt);
}

// Checking factor freshness (e.g., require factor within last 5 minutes)
Instant fiveMinutesAgo = Instant.now().minus(Duration.ofMinutes(5));
boolean isFresh = factor instanceof FactorGrantedAuthority fga &&
    fga.getIssuedAt().isAfter(fiveMinutesAgo);

// Checking for specific factor in authentication
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
boolean hasPasswordFactor = auth != null && auth.getAuthorities().stream()
    .anyMatch(authority ->
        FactorGrantedAuthority.PASSWORD_AUTHORITY.equals(authority.getAuthority()));

// Getting all factor authorities with timestamps
auth.getAuthorities().stream()
    .filter(a -> a instanceof FactorGrantedAuthority)
    .map(a -> (FactorGrantedAuthority) a)
    .forEach(factor -> {
        System.out.println("Factor: " + factor.getAuthority() +
                          ", Issued: " + factor.getIssuedAt());
    });

AuthorityUtils

Utility class for working with granted authorities.

package org.springframework.security.core.authority;

class AuthorityUtils {
    static final List<GrantedAuthority> NO_AUTHORITIES;

    static List<GrantedAuthority> createAuthorityList(String... authorities);
    static Set<String> authorityListToSet(
        Collection<? extends GrantedAuthority> authorities);
    static List<GrantedAuthority> commaSeparatedStringToAuthorityList(
        String authorityString);
}

Method Details:

  • NO_AUTHORITIES - Immutable empty list of authorities. Use this instead of Collections.emptyList() for consistency.
  • createAuthorityList(String...) - Creates a list of SimpleGrantedAuthority from strings. Returns mutable list.
  • authorityListToSet(Collection) - Converts authorities to a set of strings. Useful for set operations (contains, intersection, etc.).
  • commaSeparatedStringToAuthorityList(String) - Parses comma-separated authority string. Handles whitespace automatically.

Usage Example:

// Create authority list
List<GrantedAuthority> authorities =
    AuthorityUtils.createAuthorityList("ROLE_USER", "ROLE_ADMIN");

// Convert to set of strings
Set<String> authorityStrings = AuthorityUtils.authorityListToSet(authorities);
// Returns: ["ROLE_ADMIN", "ROLE_USER"]

// Parse comma-separated string
List<GrantedAuthority> parsed =
    AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN, ROLE_USER");

// Empty authorities
List<GrantedAuthority> none = AuthorityUtils.NO_AUTHORITIES;

// Check if user has any of multiple roles
Set<String> requiredRoles = Set.of("ROLE_ADMIN", "ROLE_MANAGER");
Set<String> userRoles = AuthorityUtils.authorityListToSet(
    authentication.getAuthorities());
boolean hasRequiredRole = !Collections.disjoint(requiredRoles, userRoles);

GrantedAuthoritiesContainer

Interface for objects that contain granted authorities.

package org.springframework.security.core.authority;

interface GrantedAuthoritiesContainer extends Serializable {
    Collection<? extends GrantedAuthority> getGrantedAuthorities();
}

Method Details:

  • getGrantedAuthorities() - Returns the granted authorities contained in this object. Should not return null.

Usage Example:

// Check if object contains authorities
if (object instanceof GrantedAuthoritiesContainer) {
    Collection<? extends GrantedAuthority> authorities =
        ((GrantedAuthoritiesContainer) object).getGrantedAuthorities();
    // Process authorities
}

Authentication Trust

AuthenticationTrustResolver

Evaluates Authentication tokens to determine their trust level.

package org.springframework.security.authentication;

interface AuthenticationTrustResolver {
    boolean isAnonymous(Authentication authentication);
    boolean isRememberMe(Authentication authentication);
}

Method Details:

  • isAnonymous(Authentication) - Returns true if the authentication represents an anonymous user. Returns false if authentication is null.
  • isRememberMe(Authentication) - Returns true if the authentication was created using remember-me. Returns false if authentication is null.

AuthenticationTrustResolverImpl

Default implementation of AuthenticationTrustResolver.

package org.springframework.security.authentication;

class AuthenticationTrustResolverImpl implements AuthenticationTrustResolver {
    AuthenticationTrustResolverImpl();

    boolean isAnonymous(Authentication authentication);
    boolean isRememberMe(Authentication authentication);
    void setAnonymousClass(Class<? extends Authentication> anonymousClass);
    void setRememberMeClass(Class<? extends Authentication> rememberMeClass);
}

Method Details:

  • setAnonymousClass(Class) - Sets the class to check for anonymous authentication (default: AnonymousAuthenticationToken).
  • setRememberMeClass(Class) - Sets the class to check for remember-me authentication (default: RememberMeAuthenticationToken).

Usage Example:

AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

if (auth == null || trustResolver.isAnonymous(auth)) {
    // User is anonymous or not authenticated
    log.info("Anonymous user");
} else if (trustResolver.isRememberMe(auth)) {
    // User authenticated via remember-me
    log.info("Remember-me authentication");
    // May require re-authentication for sensitive operations
} else {
    // Fully authenticated user
    log.info("Fully authenticated user");
}

// Custom trust resolver with different token types
AuthenticationTrustResolverImpl customResolver = new AuthenticationTrustResolverImpl();
customResolver.setAnonymousClass(CustomAnonymousToken.class);
customResolver.setRememberMeClass(CustomRememberMeToken.class);

Parameter Name Discovery

@P Annotation

Annotation for naming method parameters in security expressions.

package org.springframework.security.core.parameters;

@Target(PARAMETER)
@Retention(RUNTIME)
@interface P {
    String value();
}

Usage Example:

@PreAuthorize("#user.name == authentication.name")
public void updateUser(@P("user") User user) {
    // Only users can update their own profile
    // The @P annotation makes "user" available in the SpEL expression
}

// Without @P, parameter names may not be available (depends on compilation settings)
@PreAuthorize("#username == authentication.name")
public void updateUser(@P("username") String username, User user) {
    // username is explicitly named, user may not be available
}

AnnotationParameterNameDiscoverer

Discovers parameter names from @P annotations.

package org.springframework.security.core.parameters;

class AnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {
    AnnotationParameterNameDiscoverer(String annotationClassName);

    String[] getParameterNames(Method method);
    String[] getParameterNames(Constructor<?> constructor);
}

Usage Example:

// Custom annotation for parameter naming
@Target(PARAMETER)
@Retention(RUNTIME)
@interface ParamName {
    String value();
}

// Use custom annotation
AnnotationParameterNameDiscoverer discoverer =
    new AnnotationParameterNameDiscoverer(ParamName.class.getName());
Method method = MyService.class.getMethod("updateUser", User.class);
String[] paramNames = discoverer.getParameterNames(method);

DefaultSecurityParameterNameDiscoverer

Default parameter name discoverer combining multiple strategies.

package org.springframework.security.core.parameters;

class DefaultSecurityParameterNameDiscoverer
    extends PrioritizedParameterNameDiscoverer {

    DefaultSecurityParameterNameDiscoverer();
}

Usage Example:

ParameterNameDiscoverer discoverer = new DefaultSecurityParameterNameDiscoverer();
Method method = MyService.class.getMethod("updateUser", User.class);
String[] paramNames = discoverer.getParameterNames(method);
// Returns parameter names if available, null otherwise