Authentication vs Authorization
Authentication vs Authorization
Every secured system rests on two distinct pillars: authentication (who are you?) and authorization (what are you allowed to do?). These questions are logically sequential and must never be conflated. Confusing them is one of the most common sources of security bugs in real-world applications — a misconfigured authorization rule that lets an authenticated user reach a resource they should never see is a data breach, not a login failure.
Spring Security handles both concerns, but through separate, well-defined subsystems. This lesson gives you the conceptual foundation and the practical Spring Security 6 API surface for each.
Authentication — Proving Identity
Authentication is the process of verifying that a principal (a user, a service, or a device) is who it claims to be. The classic mechanism is a username and password, but the concept is broader: a JSON Web Token, an X.509 client certificate, an OAuth 2 access token, or a SAML assertion are all forms of credentials that can be used to authenticate a principal.
In Spring Security the result of a successful authentication is an Authentication object stored in the SecurityContext. It contains three things:
- Principal — who was authenticated (typically a
UserDetailsobject). - Credentials — what was used to prove identity (erased after authentication for security).
- Authorities — the set of granted permissions (
GrantedAuthorityinstances) associated with this principal.
You can inspect the currently authenticated principal anywhere in your application:
Authentication in a ThreadLocal, so it is automatically available throughout the life of a servlet request without being passed as a parameter. In reactive (WebFlux) applications the context is stored in the reactive pipeline instead — never assume thread-local semantics there.
Authorization — Enforcing What Is Allowed
Authorization runs after authentication. Once the system knows who the caller is, it must decide whether that caller may perform the requested action on the requested resource. Spring Security expresses authorization in terms of granted authorities (roles and permissions) that are checked against rules you configure.
There are two major places where Spring Security enforces authorization:
- HTTP layer — rules applied to incoming requests before they reach a controller, configured via
SecurityFilterChain. - Method layer — annotations like
@PreAuthorizeapplied to individual service or controller methods, enforced via AOP.
A minimal authorization configuration in Spring Security 6 looks like this:
ROLE_. When you call hasRole("ADMIN"), Spring Security checks for an authority named ROLE_ADMIN — it prepends the prefix automatically. When you call hasAuthority("API_READ"), it checks for that exact string. Use roles for broad job functions (ADMIN, USER, MANAGER) and fine-grained authorities for specific capabilities (INVOICE_WRITE, REPORT_READ).
Why the Order Matters — and Why They Must Stay Separate
Authentication always runs first. If a request cannot be authenticated, there is nothing to authorize — the request is rejected with 401 Unauthorized. Only after a valid Authentication object is in the SecurityContext do the authorization rules fire. A rejected authorization returns 403 Forbidden.
These two HTTP status codes carry specific semantic meaning that your API clients depend on:
401— "You have not proven who you are. Present valid credentials."403— "I know who you are, but you are not allowed to do this."
403 Forbidden for an unauthenticated request to a protected endpoint, you are telling attackers that the endpoint exists and is protected. Always return 401 first, reserve 403 for authenticated-but-not-authorized cases. Spring Security does this correctly by default — only override AuthenticationEntryPoint and AccessDeniedHandler if you understand the implications.
Authentication and Authorization in a Stateless REST API
Traditional web applications store the Authentication in an HTTP session (stateful). Stateless REST APIs — and microservices — take a different approach: the client presents a self-contained token (typically a JWT) on every request, and the server verifies it without consulting any session store.
In this model the two pillars shift slightly:
- Authentication happens at the token-verification step: the JWT's signature is verified, its expiry is checked, and the embedded subject and claims are extracted to rebuild an
Authenticationobject in theSecurityContext. - Authorization then proceeds identically: the authorities embedded in the token (or looked up from a database) are checked against the rules.
Spring Security's Internal Contract
Internally, Spring Security separates the two concerns at the API level:
AuthenticationManager/AuthenticationProvider— responsible for authentication. They take an unauthenticated token (e.g.UsernamePasswordAuthenticationTokenwith raw credentials), validate it, and return a fully populated, trustedAuthenticationobject.AccessDecisionManager/AuthorizationManager— responsible for authorization. They receive the authenticatedAuthenticationand a secured object (an HTTP request or a method invocation) and decide whether to grant access.
You will configure and extend these interfaces throughout this tutorial. For now the key takeaway is architectural: Spring Security's design enforces the separation of authentication and authorization at the type level, making it harder to accidentally conflate them.
Summary
Authentication answers "who are you?" and produces a trusted Authentication object in the SecurityContext. Authorization answers "what may you do?" and checks that object's authorities against the rules you define. Authentication always happens first; its failure yields 401, while an authorization failure yields 403. Spring Security enforces the boundary between these two concerns at the API level, both in the HTTP filter chain and in the method-security AOP layer. Keeping this mental model clear will save you from the most common class of security misconfiguration bugs.