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

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:

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

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

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

References