intermediate~2h

Spring Security Fundamentals

Before JWT, before roles — every secured request in Spring passes through the same mechanism. This module is that mechanism.

Learning objectives

  • Beginner: State the difference between authentication and authorization in one sentence each.
  • Intermediate: Trace a request through the security filter chain and identify where authentication actually happens.
  • Advanced: Configure a custom SecurityFilterChain bean that intentionally loosens or tightens Spring Security's secure-by-default posture for a specific use case.
TermQuestion it answers
Authentication"Who are you?" — verifying identity, e.g. via a valid JWT (Module 13).
Authorization"What are you allowed to do?" — verifying permission for a specific action, e.g. via roles (Module 14).

A request can be authenticated (the server knows exactly who you are) and still be unauthorized for a specific action (you're not allowed to delete this resource) — the two checks are related but genuinely separate, and Spring Security models them as separate concerns throughout.

◆ The problem

Security checks (is this request authenticated? does it have the right role?) need to happen before a request reaches your @RestController — putting that logic inside every controller method would be repetitive and trivially easy to forget on a new endpoint.

Spring Security intercepts every request via a chain of servlet filters, positioned in front of the DispatcherServlet from Module 06 §2 — by the time a request reaches your controller, security has already run.

Every request runs through the security filter chain before it ever reaches the DispatcherServlet — by the time your controller method runs, authentication and authorization have already been decided.

@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(csrf -> csrf.disable()) // stateless JWT APIs don't need CSRF protection — see internals box .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/auth/**").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated()) .build(); } }

◆ Under the hood — why CSRF is disabled for a JWT API

CSRF protection defends against an attack that exploits browser-managed session cookies being sent automatically with every request to a site. A stateless JWT API (Module 13) doesn't use cookie-based sessions — the token is sent explicitly in an Authorization header by client code, which a malicious cross-site request can't forge the way it can a cookie. CSRF disabling is correct specifically because of statelessness, not a generic security shortcut — a cookie-based session API would need it enabled.

💻 Code example

@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(csrf -> csrf.disable()) // stateless JWT APIs don't need CSRF protection — see internals box .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/auth/**").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated()) .build(); } }
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); // includes a per-password random salt automatically }

// registering a user user.setPassword(passwordEncoder.encode(rawPassword)); // store only the hash

// verifying a login attempt boolean matches = passwordEncoder.matches(rawPasswordFromLogin, user.getPassword());

▲ Pitfall

Never store or compare plain-text passwords, and never use a fast general-purpose hash like plain SHA-256 for passwords — BCrypt is deliberately slow and includes automatic per-password salting specifically to resist brute-force and rainbow-table attacks, properties a generic hash function doesn't provide.

✓ Quick recap

What's the practical difference between authentication and authorization? Authentication verifies who you are; authorization verifies what you're allowed to do — a request can be authenticated but still unauthorized for a specific action. Why is it correct to disable CSRF protection for a stateless JWT API? CSRF defends against cookie-based session forgery; a stateless API sends its token explicitly in a header, which cross-site requests can't forge the way they can an automatically-sent cookie.

💻 Code example

@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); // includes a per-password random salt automatically }

Want a visual for this concept?

Generate a diagram tailored to “Spring Security Fundamentals” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.

Sign in to generate a visual →

Practice quiz

Next Step

Continue to Authentication with JWT← Back to all Spring Boot chapters