Spring Security
Spring Security is the standard framework for authentication and authorization in Spring Boot. It plugs into the servlet (or reactive) request pipeline as a chain of filters that authenticate requests: sessions, form login, HTTP Basic, OAuth2/OIDC login, JWT bearer tokens, API keys. It then enforces authorization rules on URLs and methods, and applies protections like CSRF defense and security headers.
Adding the starter secures everything by default. Real applications then configure a SecurityFilterChain bean describing which endpoints are public, how users authenticate, and who can do what. The modern configuration style is a concise lambda DSL, and most apps delegate authentication to an identity provider via OAuth2 and OpenID Connect.
TL;DR
- Spring Security is a filter chain in front of your controllers. Every request passes through authentication and authorization filters.
- Configure it with one or more
SecurityFilterChainbeans (the lambda DSL);WebSecurityConfigurerAdapteris gone. - Browser apps: session-based login, or OAuth2/OIDC login (
oauth2Login) with an IdP. APIs: resource server validating JWT or opaque bearer tokens. - Authorize URLs with
authorizeHttpRequests, and methods with@PreAuthorize(@EnableMethodSecurity). - Keep CSRF protection for cookie-based auth; configure CORS explicitly for cross-origin frontends.
- Store passwords with
DelegatingPasswordEncoder(bcrypt, Argon2); never roll your own.
Quick Example
A REST API secured as an OAuth2 resource server with JWTs, plus method-level rules:
Core Concepts
The Filter Chain
Spring Security registers a DelegatingFilterProxy, which delegates to a FilterChainProxy holding one or more SecurityFilterChains. The first chain whose securityMatcher matches the request handles it. Each chain is an ordered list of filters: CORS, CSRF, logout, authentication filters (form login, bearer token, OAuth2 login), exception translation, and authorization. Multiple chains let you secure /api/ (stateless JWT) differently from /admin/ (session login).
Authentication
Authentication produces an Authentication object stored in the SecurityContext (per request, or in the session). Core pieces:
AuthenticationManager/ providers: verify credentials (username and password, tokens).UserDetailsService: loads users for username/password login.PasswordEncoder:PasswordEncoderFactories.createDelegatingPasswordEncoder()stores hashes with an{id}prefix ({bcrypt}…), allowing algorithm upgrades. See password security.
Common modes:
For SPAs, the Backend-for-Frontend (BFF) pattern, with the Spring app acting as an OAuth2 client and keeping tokens server-side behind an HttpOnly session cookie, is safer than storing tokens in the browser.
Authorization
- URL rules:
authorizeHttpRequestswithrequestMatchers(...), thenpermitAll(),authenticated(),hasRole(),hasAuthority(), or customAuthorizationManagers. Order matters: the first match wins, so put specific rules before general ones and end withanyRequest(). - Method security:
@EnableMethodSecurityenables@PreAuthorize,@PostAuthorize, and@PreFilter/@PostFilterwith SpEL expressions referencing parameters (#orderId) and beans. - Authorities vs roles: roles are authorities prefixed with
ROLE_. JWT scopes map toSCOPE_xauthorities by default. Customize with aJwtAuthenticationConverterto map IdP groups or roles.
Object-level checks ("can this user refund this order?") belong in method security or the service layer, not just URL patterns. See broken access control.
CSRF and CORS
- CSRF protection is on by default and required when browsers authenticate with cookies (sessions). It's safe to disable only for truly stateless APIs using bearer tokens in headers. See CSRF.
- CORS must be configured when a frontend on another origin calls your API. Define a
CorsConfigurationSourcebean with explicit allowed origins, methods, and headers, and never*with credentials.
Security Headers
Spring Security adds sensible headers by default (X-Content-Type-Options, X-Frame-Options/frame options, cache control, and HSTS over HTTPS), and you can add a Content Security Policy. See security headers.
Testing
spring-security-test provides helpers:
@WithMockUser, jwt(), oidcLogin(), and csrf() post-processors simulate authenticated users. Test both allowed and denied cases for every sensitive endpoint. See Spring Boot testing.
Best Practices
Delegate Authentication to an Identity Provider
Use OAuth2/OIDC with a proper IdP for user login, MFA, and SSO rather than building login flows yourself. Your app becomes a client (web) or resource server (API).
Deny by Default
End URL rules with anyRequest().authenticated() (or denyAll()), and add explicit permitAll() only for public endpoints. New endpoints are then protected automatically.
Enforce Object-Level Authorization
Check ownership and tenancy in services or method security (@PreAuthorize with a bean method), and scope repository queries by the current user or tenant. URL rules alone can't prevent IDOR.
Validate Tokens Fully
Configure the issuer and audience for JWT validation, keep clock skew small, prefer short-lived access tokens, and rely on the IdP's key rotation via JWKS discovery.
Common Mistakes
Disabling CSRF for Session-Based Apps
It's only appropriate for stateless APIs where authentication comes from an Authorization header, not cookies.
Rule Order Mistakes
Put the most specific matchers first.
Trusting Client-Supplied Roles
Reading roles from request parameters, unverified headers, or unsigned tokens lets users grant themselves privileges. Authorities must come from validated tokens or server-side user data.
FAQ
What replaced WebSecurityConfigurerAdapter?
Component-based configuration: declare SecurityFilterChain beans (and UserDetailsService, PasswordEncoder, and similar beans) using the lambda DSL. The adapter was deprecated in Spring Security 5.7 and removed in 6.
Should my API use sessions or JWTs?
For first-party browser apps on the same site, sessions (or a BFF holding tokens server-side) with HttpOnly cookies and CSRF protection are simpler and safer. For APIs consumed by mobile apps, third parties, or other services, OAuth2 bearer tokens (often JWTs) with a resource server configuration fit better.
How do I map roles from my identity provider?
Provide a custom JwtAuthenticationConverter (or GrantedAuthoritiesMapper for OIDC login) that reads the IdP's claim (for example roles, groups, or realm_access.roles) and converts values into GrantedAuthority objects like ROLE_ADMIN.
How do I secure actuator endpoints?
Expose only what you need (management.endpoints.web.exposure.include=health,info,prometheus), put management endpoints on a separate port or path protected by their own SecurityFilterChain, and restrict sensitive ones to operators. See Spring Boot Actuator.
Related Topics
- Spring Boot — The framework overview
- OAuth — The authorization framework behind login and tokens
- JWT — Token format for resource servers
- Authentication — Authentication concepts
- Broken Access Control — Authorization failures to prevent
- CSRF — Why CSRF protection matters with cookies