Authentication vs. Authorization
Authentication answers 'who are you?' — verifying that a set of credentials belongs to a real, known identity — while authorization answers 'what are you allowed to do?', deciding whether that verified identity can access a particular resource or perform a particular action. In Spring Security, authentication produces an Authentication object stored in the SecurityContext, holding the principal (typically a UserDetails implementation) and a collection of GrantedAuthority objects. Authorization decisions, made later by FilterSecurityInterceptor or method-level annotations, simply inspect those granted authorities against the required role or permission for the resource being accessed.
Cricket analogy: It's like an ICC official first checking a player's passport and team accreditation (authentication) before separately checking whether their playing status permits them to bowl more than the powerplay overs (authorization).
Roles, Authorities, and Method Security
Spring Security models permissions as GrantedAuthority strings, and roles are simply authorities conventionally prefixed with ROLE_, so hasRole('ADMIN') is shorthand for hasAuthority('ROLE_ADMIN'). Beyond URL-based rules in the SecurityFilterChain, you can enforce authorization directly on service or controller methods using @PreAuthorize and @PostAuthorize, enabled via @EnableMethodSecurity. @PreAuthorize evaluates a SpEL expression before the method runs, letting you write fine-grained rules like @PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id") that reference method arguments directly, which URL-pattern-based rules cannot express.
Cricket analogy: It's like a team having both a squad list (roles: batter, bowler, all-rounder) and specific match permissions (authorities: 'can bowl death overs') — @PreAuthorize is the captain checking both before handing over the ball.
Stateless Authentication with JWT
Traditional session-based authentication stores the Authentication object server-side and identifies the client via a session cookie, which works well for browser apps but doesn't scale cleanly across stateless, horizontally-scaled REST APIs. JSON Web Tokens (JWT) solve this by encoding the user's identity and authorities directly into a signed, self-contained token that the client sends in the Authorization: Bearer header on every request; the server verifies the signature and expiration without needing to look up any server-side session state. This requires a custom OncePerFilterRequest-based filter that extracts and validates the JWT, then manually populates the SecurityContext, since Spring Security's default filters expect session or Basic auth, not bearer tokens.
Cricket analogy: It's like a stadium issuing a tamper-evident, pre-validated wristband at the gate instead of checking your name against a guest list every time you re-enter — the wristband itself (JWT) proves your access without a lookup.
@RestController
public class AccountController {
@PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id")
@GetMapping("/api/accounts/{userId}")
public AccountDto getAccount(@PathVariable Long userId) {
return accountService.findById(userId);
}
@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/api/accounts/{userId}")
public void deleteAccount(@PathVariable Long userId) {
accountService.delete(userId);
}
}@EnableMethodSecurity must be added to a @Configuration class before @PreAuthorize and @PostAuthorize annotations take effect. Without it, the annotations are silently ignored and every method executes unguarded, which is an easy mistake to miss during code review since the code compiles and looks correct.
- Authentication verifies identity; authorization decides what a verified identity may do.
- GrantedAuthority strings back both roles (ROLE_ prefixed) and fine-grained permissions.
- @PreAuthorize enables method-level SpEL expressions that can reference method arguments directly.
- @EnableMethodSecurity must be present or @PreAuthorize/@PostAuthorize are silently skipped.
- JWTs enable stateless authentication by embedding identity and authorities in a signed token.
- A custom filter is needed to validate JWTs and populate the SecurityContext manually.
- URL-based rules and method-level annotations can be combined for layered defense.
Practice what you learned
1. What is the key difference between authentication and authorization?
2. What annotation is required at the configuration level to activate @PreAuthorize checks?
3. Why does JWT-based authentication scale well across multiple server instances?
4. In Spring Security, hasRole('ADMIN') is shorthand for which authority check?
5. What is needed to process JWT bearer tokens since Spring Security's default filters don't handle them?
Was this page helpful?
You May Also Like
Spring Security Basics
An introduction to how Spring Security protects a Spring Boot application using the servlet filter chain, HTTP security rules, and password encoding.
Application Properties and Profiles
How Spring Boot externalizes configuration through application.properties/yml, property precedence, and environment-specific profiles.
Logging in Spring Boot
How Spring Boot's default Logback-based logging works, including log levels, per-package configuration, and structured logging for production.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics
Web DevelopmentNext.js Study Notes
JavaScript · 30 topics