Authentication vs Authorization in Spring Security
Fast recall
Quick revision
Core answer
Authentication object stored in the `SecurityContext`. Authorization answers "What are you allowed to do?" — checks the principal's GrantedAuthority collection against required permissions for a resource. Spring enforces them as two distinct, sequential steps: AuthenticationManager first, then AuthorizationManager (or @PreAuthorize). The clearest signal that you understand the difference: 401 means unauthenticated; 403 means authenticated-but-unauthorized — never return 403 to anonymous requests, it leaks resource existence.Whether the candidate can clearly articulate the two-step security model and map it to Spring Security's concrete types.
Conflating the two concepts, or not knowing that Authorization can only work after Authentication populates the SecurityContext.
Reference the Authentication interface, GrantedAuthority, AuthenticationManager, and AccessDecisionManager (or the newer AuthorizationManager in Spring Security 6).
Interview-ready guide
Interview answer
Authentication — identity verification
- 'Who are you?' — user presents credentials (password, JWT, certificate)
AuthenticationManagerverifies- On success:
Authenticationobject stored inSecurityContextHolderwith principal +GrantedAuthoritylist - Failure:
AuthenticationException-> 401
Authorization — permission check
- 'What can you do?' — evaluated after authentication succeeds
- Spring checks
GrantedAuthorityagainst required permission - Failure:
AccessDeniedException-> 403
The Spring Security flow
- Request enters filter chain
- Auth filter (e.g.,
UsernamePasswordAuthenticationFilter) extracts credentials, callsAuthenticationManager DaoAuthenticationProviderloadsUserDetailsviaUserDetailsService, verifies password- On success: stores
AuthenticationinSecurityContextHolder AuthorizationFilterchecks against required authorities for the URL
Method security (`@PreAuthorize`)
- Adds a second authorization layer on service methods
- Even if HTTP-level check is bypassed, method-level still enforces
- SpEL access to parameters, principal, and Spring beans
Common pitfalls
- Returning 403 instead of 401 for anonymous users (leaks resource existence)
- Forgetting
@EnableMethodSecurity->@PreAuthorizesilently does nothing - Self-invocation skips AOP -> method-level security bypassed
- CORS preflight OPTIONS rejected because not
permitAll-> entire API breaks for browsers
Authentication vs Authorization in Spring Security
Direct Answer
Authentication answers "Who are you?" — verifies identity by checking credentials and produces an Authentication object stored in the SecurityContext. Authorization answers "What are you allowed to do?" — checks the principal's GrantedAuthority collection against required permissions for a resource. Spring enforces them as two distinct, sequential steps: AuthenticationManager first, then AuthorizationManager (or @PreAuthorize). The clearest signal that you understand the difference: 401 means unauthenticated; 403 means authenticated-but-unauthorized — never return 403 to anonymous requests, it leaks resource existence.
Code Example
Authentication asks who are you? and produces an Authentication object in the SecurityContext. Authorization asks what can you do? and checks roles/authorities against that object. Spring Security pipelines both in a filter chain.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity // enables @PreAuthorize / @PostAuthorize
public class SecurityConfig {
// ---- AUTHENTICATION ----
@Bean
public UserDetailsService users(PasswordEncoder encoder) {
UserDetails alice = User.withUsername("alice")
.password(encoder.encode("secret"))
.roles("USER").build();
UserDetails admin = User.withUsername("admin")
.password(encoder.encode("secret"))
.roles("USER", "ADMIN").build();
return new InMemoryUserDetailsManager(alice, admin);
}
@Bean PasswordEncoder encoder() { return new BCryptPasswordEncoder(); }
// ---- AUTHORIZATION ----
@Bean
public SecurityFilterChain chain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(a -> a
.requestMatchers("/public/**").permitAll() // no auth required
.requestMatchers("/admin/**").hasRole("ADMIN") // role-based
.requestMatchers(HttpMethod.DELETE, "/api/**").hasAuthority("SCOPE_write")
.anyRequest().authenticated()) // must be logged in
.httpBasic(Customizer.withDefaults()) // AuthN mechanism
.build();
}
}
// Fine-grained authorization on a service method
@Service
public class OrderService {
@PreAuthorize("hasRole('ADMIN') or #order.ownerId == authentication.name")
public void delete(Order order) { /* ... */ }
}
- The AuthenticationManager (invoked by filters such as
UsernamePasswordAuthenticationFilter) validates credentials and returns anAuthenticationwith authorities. On success it lands inSecurityContextHolder.getContext(). - The authorization layer (
AuthorizationManager,@PreAuthorize) is the only thing that decides whether a caller may invoke a method — URL rules are coarse, method annotations are precise, use both. hasRole("ADMIN")is sugar forhasAuthority("ROLE_ADMIN"). Keep the convention consistent or bugs creep in (theROLE_prefix is implicit only onhasRole).- Never rely on the UI hiding a button as authorization — the UI is a hint, the server is the source of truth.
Common Mistakes & Pitfalls
Conflating the two concepts, or not knowing that Authorization can only work after Authentication populates the SecurityContext.
Check your understanding
Answer these without looking back at the article.
- How does Spring Security handle anonymous users who haven't logged in?
- What is the difference between a role and a privilege in Spring Security?
- How would you implement fine-grained, resource-level authorization (e.g., user can only edit their own posts)?
- Why must CORS preflight be permitAll, and how do you configure it without weakening security?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.