Applications need to verify user identities and control access based on roles. Hard-coded authentication logic is inflexible, insecure, and doesn’t integrate with standard identity providers. Developers need a pluggable authentication system that supports multiple strategies.
Spring Security Authentication verifies user identity via configurable AuthenticationProvider implementations. The UserDetailsService interface loads user data (username, password hash, roles) from any backend. Role-based authorization restricts access to specific endpoints or methods based on granted authorities.
- Authentication request: User submits credentials (username/password, token, certificate)
- AuthenticationProvider chain: Each provider checks if it can handle the authentication type — first match wins
- UserDetailsService: Loads user from database:
loadUserByUsername(String username) → UserDetails - Password verification:
PasswordEncoder.matches(rawPassword, encodedPassword)— should be BCrypt, not plain text - GrantedAuthority: User roles returned as
GrantedAuthorityobjects (prefixROLE_for role-checking) - SecurityContextHolder:
SecurityContextHolder.getContext().setAuthentication(auth)— stored in ThreadLocal - Role-based access:
@PreAuthorize("hasRole('ADMIN')")orhasAuthority('WRITE_PRIVILEGE')
digraph auth_flow {
rankdir=TB
node [shape=box style=filled fillcolor="#f0f4ff" fontname="Helvetica" fontsize=12]
edge [fontname="Helvetica" fontsize=10]
LOGIN [label="User submits\username/password"]
FILTER [label="Authentication Filter\n(e.g., UsernamePasswordAuthFilter)"]
PROVIDER [label="AuthenticationProvider\n(chain of providers)" fillcolor="#ffe5cc]
UDS [label="UserDetailsService\n(load from DB)"]
ENC [label="PasswordEncoder\n(BCrypt match)"]
CTX [label="SecurityContextHolder\n(ThreadLocal)"]
ROLE [label="Role Check\n@PreAuthorize\n(hasRole('ADMIN'))"]
ACCESS [label="Access\nGranted / Denied"]
LOGIN -> FILTER
FILTER -> PROVIDER
PROVIDER -> UDS
UDS -> ENC
ENC -> PROVIDER
PROVIDER -> CTX [label="store auth"]
CTX -> ROLE
ROLE -> ACCESS
}- Multiple providers: DAO, LDAP, OAuth2, remember-me, JWT — configured as a provider chain
- UserDetailsService: Core interface for loading users from any data source (JDBC, JPA, Mongo)
- PasswordEncoder: Never store plain-text passwords; BCrypt, SCrypt, Argon2 recommended
- Role hierarchy:
ROLE_ADMIN > ROLE_USER— admin inherits user permissions - Remember-me: Persistent token-based authentication across browser sessions
- Pre-authentication: For environments where authentication happens upstream (e.g., SSO, X.509 certs)
- Built from: Spring Security — Authentication is a core component of Spring Security
- Related: Spring Security CSRF and JWT — JWT is an alternative authentication mechanism
- Related: JAAS — JAAS is Java’s standard auth; Spring Security abstracts and improves it
- Contrasts with: Session Authentication — Session auth stores state on server; JWT is self-contained
- Builds into: JWT Authentication — JWT can be used as a Spring Security authentication provider
- PasswordEncoder upgrade: Migrating from MD5/SHA to BCrypt requires supporting both encoders simultaneously during transition
- UserDetailsService caching: Without caching, every request to check auth triggers a database load; use caching layer
- ROLE_ prefix:
hasRole('ADMIN')automatically checks forROLE_ADMIN;hasAuthority('ADMIN')checks for exact string - ThreadLocal cleanup: SecurityContextHolder is ThreadLocal — in async processing, the context doesn’t propagate automatically
- Blank passwords:
PasswordEncodershould throw exception for blank/null passwords, not silently accept