I'm always excited to take on new projects and collaborate with innovative minds.

Mail

academy@sogdo.com

Website

https://academy.sogdo.in/

Spring Boot Security

Sogdo Academy

Core Responsibilities of Spring Security

Spring Security is responsible for several distinct concerns:

  1. Authentication – Verifying identity (Who are you?)
  2. Authorization – Determining permissions (What can you do?)
  3. Session Management – Managing authenticated sessions
  4. Security Context – Storing the current authenticated user
  5. Request Protection – Blocking unauthenticated or unauthorized requests
  6. Web Security – CSRF, CORS, security headers, clickjacking protection
  7. Integration – OAuth2, OIDC, JWT, LDAP, SAML, Keycloak, etc.

Authentication Fundamentals

1. What is Authentication?

Authentication is the process of verifying the identity of a user, application, or service before granting access to a system. It ensures that the entity requesting access is who it claims to be.

Purpose

  • Verify user identity
  • Protect sensitive resources
  • Prevent unauthorized access
  • Establish a trusted session

Examples

  • Username and Password
  • OTP (One-Time Password)
  • Fingerprint Authentication
  • Face Recognition
  • Smart Card Login
  • Google Sign-In

2. Authentication vs Authorization

Authentication and authorization are related but perform different functions.

AuthenticationAuthorization
Verifies identityDetermines permissions
Answers "Who are you?"Answers "What can you access?"
Performed before authorizationPerformed after authentication
Validates credentialsValidates roles and privileges

Example

A user logs into an online banking application.

  • Authentication verifies the username and password.
  • Authorization determines whether the user can view account details, transfer funds, or manage other users.

3. Identity vs Principal

Identity

Identity represents the actual user, application, or device registered in the system.

Examples:

  • Customer
  • Employee
  • Administrator
  • Service Account

Identity usually contains:

  • User ID
  • Username
  • Email Address
  • Employee ID
  • Department

Principal

A Principal is the authenticated representation of an identity within the application. Once authentication succeeds, the application works with the Principal instead of the raw identity information.

In Spring Security, the authenticated Principal is available through the Authentication object.


4. Credentials

Credentials are the information presented during authentication to prove identity.

Common credentials include:

  • Username
  • Password
  • PIN
  • OTP
  • Security Certificate
  • Hardware Token
  • Fingerprint
  • Face Recognition
  • Access Token
  • JWT

Best Practices

  • Never store passwords in plain text.
  • Store passwords using secure hashing algorithms such as BCrypt or Argon2.
  • Encrypt sensitive credentials during transmission using HTTPS.

5. Authentication Factors

Authentication factors define the methods used to verify identity.

Something You Know

Information known only to the user.

  • Password
  • PIN
  • Passphrase

Something You Have

A physical object possessed by the user.

  • Mobile Phone
  • Hardware Token
  • Smart Card
  • Security Key

Something You Are

Biometric characteristics.

  • Fingerprint
  • Face Recognition
  • Retina Scan
  • Voice Recognition

Somewhere You Are

Location-based verification.

  • Corporate Network
  • Office Location
  • VPN
  • Trusted Country

Something You Do

Behavior-based authentication.

  • Typing Pattern
  • Mouse Movement
  • Touch Pattern

Using multiple authentication factors significantly improves security.

 

1. Username & Password Authentication

Introduction

Authentication is the process of verifying the identity of a user before granting access to protected resources. Among all authentication mechanisms, username and password authentication remains the most widely adopted approach in enterprise applications.

Despite the availability of OAuth2, OpenID Connect, Passkeys, and biometric authentication, almost every enterprise system still supports username and password authentication either as a primary authentication method or as part of a multi-factor authentication process.

Examples include:

  • Internet Banking
  • Hospital Management Systems
  • ERP Applications
  • CRM Systems
  • Government Portals
  • HRMS
  • Employee Portals
  • College ERP
  • E-Commerce Admin Panels

Why Username & Password Authentication Exists

Every system needs a reliable way to uniquely identify users.

Without authentication:

  • Anyone can access confidential information.
  • Sensitive business data can be exposed.
  • Unauthorized transactions become possible.
  • Auditing becomes impossible.

Authentication establishes trust between the user and the application.


Authentication Lifecycle

A typical authentication lifecycle consists of the following stages:

  1. User enters credentials.
  2. Credentials are transmitted securely over HTTPS.
  3. Spring Security intercepts the request.
  4. AuthenticationManager receives the authentication request.
  5. AuthenticationProvider validates the credentials.
  6. UserDetailsService loads user information from the database.
  7. PasswordEncoder compares the submitted password with the stored hash.
  8. On success, an Authentication object is created.
  9. The Authentication object is stored in the SecurityContext.
  10. A session or token is generated.
  11. The user is allowed to access secured resources.

Authentication Architecture

 
Client
   │
   ▼
Login Form
   │
   ▼
UsernamePasswordAuthenticationFilter
   │
   ▼
AuthenticationManager
   │
   ▼
AuthenticationProvider
   │
   ▼
UserDetailsService
   │
   ▼
Database
   │
   ▼
PasswordEncoder
   │
   ▼
Authentication Success
   │
   ▼
SecurityContext
 

Internal Spring Security Classes

ClassResponsibility
UsernamePasswordAuthenticationFilterReads login request
UsernamePasswordAuthenticationTokenHolds username and password
AuthenticationManagerCoordinates authentication
ProviderManagerDefault AuthenticationManager implementation
DaoAuthenticationProviderDatabase-based authentication
UserDetailsServiceLoads user from database
UserDetailsRepresents authenticated user
PasswordEncoderPassword hashing and verification
SecurityContextHolderStores authenticated user
AuthenticationRepresents logged-in user

How Spring Security Authenticates a User

(Then explain every internal class one by one.)


UsernamePasswordAuthenticationFilter

Purpose

Responsibilities

Internal Source Code

Method Flow

Filter Execution

Request Interception

Authentication Token Creation

Success Handler

Failure Handler

Exception Handling

Filter Ordering

Thread Safety

Production Considerations


AuthenticationManager

Definition

Responsibilities

Internal Working

ProviderManager

authenticate() Method

Authentication Object

Exception Handling

Custom AuthenticationManager

Best Practices

Production Flow


DaoAuthenticationProvider

Definition

Responsibilities

supports()

retrieveUser()

additionalAuthenticationChecks()

Password Matching

UserDetailsService Integration

PasswordEncoder Integration

Authentication Success

Authentication Failure

Custom Provider

Enterprise Example


Password Validation

How BCrypt compares passwords

Why plain text passwords are never compared

Salt generation

Hash comparison

Constant time comparison

Password upgrade strategy


Authentication Success Flow

SecurityContext Creation

Authentication Object

Session Creation

Remember Me

Redirect Strategy

Success Handler

Audit Logging


Authentication Failure Flow

Bad Credentials

Disabled User

Locked User

Expired Account

Credentials Expired

Exception Translation

Failure Handler

Audit Logging


Security Risks

Credential Stuffing

Password Spraying

Brute Force Attack

Replay Attack

Session Hijacking

MITM

Key Logging

Phishing

CSRF

XSS

SQL Injection

 

Spring Security Architecture

Chapter 1: What is Spring Security?

Learning Objectives

After completing this chapter, you should understand:

  • Why Spring Security was created
  • What problems it solves
  • Why it is different from other security frameworks
  • Its architecture
  • How it integrates with Spring Boot
  • What happens internally when a request reaches your application

What is Spring Security?

Spring Security is a comprehensive security framework for Java applications built on the Spring Framework.

It provides authentication, authorization, protection against common web attacks, session management, OAuth2, JWT, LDAP, SAML, OAuth2 Login, Method Security, CSRF protection, CORS support, and many other security features.

Instead of developers implementing security from scratch, Spring Security provides a flexible and extensible architecture that integrates with the Spring ecosystem.


Official Definition

Spring Security is a framework that provides authentication, authorization, and protection against common security vulnerabilities for Java applications.

This definition is correct, but it does not explain what Spring Security actually does internally.


Understanding the Real Problem

Imagine you create a Spring Boot application.

 
Browser
    │
    ▼
Spring Boot
    │
    ▼
Controller
 

Without Spring Security:

 
@GetMapping("/profile")
public String profile() {
    return "Profile";
}
 

Anyone can call:

 
GET /profile
 

There is no verification of:

  • Who the user is
  • Whether the user is logged in
  • Whether the user has permission
  • Whether the request is malicious

The application simply executes the controller method.


Problems Without Spring Security

Consider an Employee Management System.

Modules:

  • Employee
  • Payroll
  • HR
  • Finance
  • Administration

Without security:

 
GET /employees
 

Anyone can access employee records.

 
GET /salary
 

Anyone can view salary details.

 
DELETE /employee/15
 

Anyone can delete employees.

This is unacceptable in any production application.


Traditional Solution

Before Spring Security, developers often wrote authentication logic in every controller.

Example:

 
@GetMapping("/employees")
public List<Employee> getEmployees(HttpSession session) {

    if(session.getAttribute("USER") == null) {
        throw new RuntimeException("Login Required");
    }

    return employeeService.findAll();
}
 

Then the next controller:

 
@GetMapping("/salary")
 

Again:

 
if(session.getAttribute("USER") == null)
 

Then:

 
@PostMapping("/payroll")
 

Again:

 
if(session.getAttribute("USER") == null)
 

The same code is repeated everywhere.

Problems:

  • Code duplication
  • Difficult maintenance
  • Easy to make mistakes
  • Inconsistent security
  • Hard to extend
  • No centralized control

Spring Security's Idea

Instead of every controller checking security:

 
Controller
    │
Check Login
 

Spring Security says:

"Intercept the request before it reaches the controller."

So the architecture becomes:

 
Browser
    │
    ▼
Spring Security
    │
    ▼
Controller
 

Every request must pass through Spring Security first.

If security checks fail, the controller is never called.


Real Request Flow

Suppose a user requests:

 
GET /employees
 

Without Spring Security:

 
Browser
    │
    ▼
DispatcherServlet
    │
    ▼
EmployeeController
 

With Spring Security:

 
Browser
    │
    ▼
Spring Security Filters
    │
    ▼
DispatcherServlet
    │
    ▼
EmployeeController
 

Notice something important:

Spring Security executes before Spring MVC.

This is one of the most fundamental concepts in Spring Security.


Why Filters?

Spring Security is built on the Servlet Filter mechanism.

A filter sits between the client and the application.

 
Client
   │
   ▼
Filter
   │
   ▼
Application
 

A filter can:

  • Read the request
  • Modify the request
  • Reject the request
  • Add headers
  • Authenticate users
  • Authorize users
  • Log requests
  • Encrypt data
  • Validate tokens

Because filters execute before controllers, they are the ideal place to enforce security.

 

1. What is Authentication?

Authentication is the process of verifying the identity of a user, application, service, or device before allowing access to protected resources.

Simply put,

Authentication answers one question: "Who are you?"

The system does not care what you can do yet. It first wants to know whether you are really the person you claim to be.


Real-Life Example

Imagine you enter an airport.

The security officer asks for your passport.

You show your passport.

The officer compares:

  • Passport photo
  • Your face
  • Passport validity

If everything matches,

You are identified.

Only after that can you proceed to immigration.

This is authentication.


Software Example

Suppose you visit

 
https://company.com/dashboard
 

Spring Security asks

 
Who are you?
 

You enter

 
Username:
john

Password:
123456
 

Spring Security verifies

  • Does user exist?
  • Is password correct?
  • Is account locked?
  • Is account disabled?
  • Is password expired?

If every answer is valid

Authentication succeeds.


Authentication is NOT Authorization

Many developers confuse these.

Authentication

 
Who are you?
 

Authorization

 
What can you access?
 

Example

Employee logs in.

Authentication says

 
You are John.
 

Authorization says

 
John can view payroll.

John cannot delete employees.
 

Two completely different responsibilities.


Why Authentication Exists

Suppose authentication didn't exist.

Anyone could access

 
GET /salary
 

Anyone could access

 
GET /admin
 

Anyone could transfer money.

Anyone could delete data.

Clearly impossible.

Authentication protects identity.


Problem Before Authentication

Imagine this controller.

 
@RestController
public class EmployeeController {

    @GetMapping("/employees")
    public List<Employee> getEmployees() {
        return employeeRepository.findAll();
    }

}
 

Anyone can call

 
GET /employees
 

No login.

No password.

No identity.

No verification.


Poor Manual Authentication

Many beginners write

 
@RestController
public class EmployeeController {

    @GetMapping("/employees")
    public String getEmployees(HttpServletRequest request){

        String username=request.getParameter("username");
        String password=request.getParameter("password");

        if(username.equals("admin") &&
                password.equals("admin123")){
            return "Employee List";
        }

        return "Access Denied";

    }

}
 

Problems

Huge problems.

Password visible.

 
GET /employees?username=admin&password=admin123
 

Password appears in

  • Browser History
  • Proxy
  • Logs
  • Server Logs

Very insecure.


Another problem

Every controller now contains login logic.

 
@GetMapping("/employee")
 

Again

 
if(...)
 

Next controller

 
@GetMapping("/salary")
 

Again

 
if(...)
 

Next

 
@GetMapping("/admin")
 

Again

 
if(...)
 

Same code everywhere.


Problems Become Huge

Imagine company has

 
300 Controllers

420 REST APIs

150 Developers
 

Every controller

 
Check login

Check password

Check role

Check account

Check expiration
 

Nightmare.


Spring Security's Idea

Move authentication outside controllers.

Instead of

 
Controller

↓

Authenticate

↓

Business Logic
 

Spring Security changes architecture to

 
Browser

↓

Spring Security

↓

Controller

↓

Business Logic
 

Now

Controller only contains business logic.

Authentication becomes centralized.


Internal Authentication Flow

Suppose user logs in.

 
Username

john
 

Password

 
admin123
 

What happens internally?

 
Browser

↓

POST /login

↓

UsernamePasswordAuthenticationFilter

↓

AuthenticationManager

↓

AuthenticationProvider

↓

UserDetailsService

↓

Database

↓

PasswordEncoder

↓

Authentication Success

↓

SecurityContext

↓

Controller
 

Every box above is a Spring Security class.

We will study every one individually.


Authentication Lifecycle

Let's understand the complete lifecycle.

Step 1

User enters

 
Username

Password
 

Step 2

Browser sends

 
POST /login

username=john
password=admin123
 

Step 3

Spring Security intercepts the request.

Controller has not executed yet.


Step 4

Spring Security creates

 
UsernamePasswordAuthenticationToken
 

Object.

Initially

 
authenticated=false
 

Step 5

AuthenticationManager receives

 
Authentication
 

object.


Step 6

AuthenticationManager asks

 
Which AuthenticationProvider can authenticate this request?
 

Step 7

DaoAuthenticationProvider says

 
I support UsernamePasswordAuthenticationToken
 

Step 8

Provider calls

 
UserDetailsService
 

Step 9

UserDetailsService loads

 
User

↓

Database
 

Step 10

PasswordEncoder compares

 
Entered Password

↓

Stored Password Hash
 

If matches

Authentication successful.

Otherwise

Throw exception.


Step 11

Spring creates

 
Authentication
 

object.

Now

 
authenticated=true
 

Step 12

Authentication stored inside

 
SecurityContext
 

Step 13

Request continues.

Controller finally executes.


What if Password is Wrong?

 
Username

john

Password

123
 

PasswordEncoder returns

 
false
 

Provider throws

 
BadCredentialsException
 

Request stops.

Controller never executes.


Authentication Success

Spring creates

 
Authentication
 

containing

 
Principal

Authorities

Credentials

Authenticated=true
 

Authentication Failure

Possible exceptions

 
BadCredentialsException

UsernameNotFoundException

DisabledException

LockedException

AccountExpiredException

CredentialsExpiredException
 

Each exception represents a different authentication failure.

 

Why Is This Design Better?

Instead of every controller checking credentials, Spring Security authenticates once at the start of the request pipeline. This provides:

  • Centralized security: One authentication mechanism for the entire application.
  • Consistency: Every protected endpoint follows the same rules.
  • Extensibility: Switch from database login to LDAP, OAuth2, JWT, or SAML with minimal changes to business code.
  • Maintainability: Authentication logic stays out of controllers and services.
  • Security: Password handling, exception processing, and session/token management are implemented using well-tested components.

Enterprise Example

Consider an online banking application.

Users include:

  • Customer
  • Teller
  • Branch Manager
  • Auditor
  • Administrator

All of them log in through the same authentication pipeline:

 
POST /login
        │
        ▼
Spring Security
        │
        ▼
AuthenticationManager
        │
        ▼
AuthenticationProvider
        │
        ▼
UserDetailsService
        │
        ▼
Database / LDAP / Active Directory
 

The authentication process is identical regardless of the user's role. Only after authentication succeeds does authorization determine what each user is allowed to access.

 

 

Spring Security Has Only Two Main Jobs

Incoming Request
      │
      ▼
Authenticate User
      │
      ▼
Authorize User
      │
      ▼
Controller

 

Everything else (JWT, OAuth2, LDAP, Session, SAML...) plugs into this pipeline.

 

Core Architecture

HTTP Request

Tomcat

Servlet Filter

DelegatingFilterProxy

FilterChainProxy

SecurityFilterChain

Authentication

Authorization

Controller

 

===================================================================

Spring Security Fundamentals

Spring Security is the standard security framework for Java Spring applications. It provides authentication, authorization, and protection against common web security vulnerabilities.

1. Core Concepts

Authentication

Authentication answers the question:

Who are you?

It verifies the user's identity using:

  • Username & Password
  • JWT Token
  • OAuth2
  • LDAP
  • SAML
  • Biometric (through external providers)

Example:

 
Username: john
Password: ********
 

If valid, Spring creates an authenticated user.


Authorization

Authorization answers:

What are you allowed to do?

Example:

UserRolePermission
JohnUSERRead Products
AliceADMINRead, Create, Delete

Spring checks permissions before allowing access.

Example:

 
@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminPage() {
    return "Admin";
}
 

Principal

The authenticated user is called the Principal.

Example:

 
Authentication auth =
SecurityContextHolder.getContext().getAuthentication();

System.out.println(auth.getName());
 

Output:

 
john
 

2. Authentication Flow

 
User
   │
   ▼
Login Request
   │
   ▼
Authentication Filter
   │
   ▼
Authentication Manager
   │
   ▼
UserDetailsService
   │
   ▼
Database
   │
   ▼
Password Encoder
   │
   ▼
Authentication Success
   │
   ▼
Security Context
 

3. Important Components

Security Filter Chain

Every request first goes through the Security Filter Chain.

 
Browser
    │
    ▼
Security Filters
    │
    ▼
Controller
 

It performs:

  • Authentication
  • Authorization
  • CSRF check
  • Session handling
  • Exception handling

UserDetailsService

Responsible for loading users.

Example:

 
@Service
public class MyUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) {

        return User.withUsername("john")
                .password("$2a$...")
                .roles("USER")
                .build();
    }
}
 

PasswordEncoder

Never store plain-text passwords.

Example:

 
@Bean
PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}
 

Encoding:

 
passwordEncoder.encode("password123");
 

Verification:

 
passwordEncoder.matches(rawPassword, encodedPassword);
 

AuthenticationManager

Responsible for authenticating users.

 
Username
Password
      │
      ▼
AuthenticationManager
      │
      ▼
UserDetailsService
 

SecurityContext

Stores authenticated user information during the request.

Example:

 
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
 

4. Default Spring Security Behavior

Without any configuration:

  • All endpoints require authentication.
  • A default login page is provided.
  • A default user is created.
  • A random password is printed in the console.
  • CSRF protection is enabled.

5. Configuring Security

Example:

 
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http)
            throws Exception {

        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .formLogin(Customizer.withDefaults());

        return http.build();
    }
}
 

6. Roles vs Authorities

Roles

 
ROLE_ADMIN
ROLE_USER
ROLE_MANAGER
 

Check:

 
.hasRole("ADMIN")
 

Spring automatically adds the ROLE_ prefix.


Authorities

More granular permissions.

 
READ_PRODUCT
CREATE_PRODUCT
DELETE_PRODUCT
 

Check:

 
.hasAuthority("DELETE_PRODUCT")
 

7. Authentication Methods

Form Login

 
Username
Password
 

Good for web applications.


HTTP Basic

 
Authorization:
Basic base64(username:password)
 

Commonly used for testing and internal APIs.


JWT Authentication

 
Login
   │
   ▼
JWT Token
   │
   ▼
Store Token
   │
   ▼
Send Token
 

Header:

 
Authorization:
Bearer eyJhbGciOi...
 

Best for REST APIs.


OAuth2 Login

Use third-party identity providers like:

  • Google
  • GitHub
  • Facebook

8. CSRF Protection

CSRF (Cross-Site Request Forgery) prevents unauthorized actions performed on behalf of an authenticated user.

Enabled by default for browser-based applications.

Disabled in many stateless REST APIs using JWT:

 
http.csrf(csrf -> csrf.disable());
 

Only disable CSRF when appropriate, such as for stateless APIs protected by tokens.


9. Session Management

By default:

 
User
   │
Login
   │
Session Created
   │
Session ID stored in Cookie
 

For JWT:

 
User
   │
JWT Token
   │
No Session
 

Configure stateless sessions:

 
http.sessionManagement(session ->
    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);
 

10. Method Security

Enable:

 
@EnableMethodSecurity
 

Examples:

 
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser() {}
 
 
@PreAuthorize("hasAuthority('WRITE')")
public void saveProduct() {}
 

11. Exception Handling

Customize responses:

 
http.exceptionHandling(ex -> ex
    .authenticationEntryPoint(new CustomAuthenticationEntryPoint())
    .accessDeniedHandler(new CustomAccessDeniedHandler())
);
 
  • 401 Unauthorized: User is not authenticated.
  • 403 Forbidden: User is authenticated but lacks permission.

12. Security Best Practices

  • Use strong password hashing (e.g., BCrypt).
  • Never store plain-text passwords.
  • Use HTTPS in production.
  • Use least-privilege authorization.
  • Validate all inputs.
  • Keep dependencies up to date.
  • Use JWT or OAuth2 for stateless APIs.
  • Enable method-level security where appropriate.
  • Avoid disabling CSRF unless your architecture justifies it.

13. Typical Request Lifecycle

 
Client Request
      │
      ▼
Security Filter Chain
      │
      ▼
Authentication Filter
      │
      ▼
AuthenticationManager
      │
      ▼
UserDetailsService
      │
      ▼
PasswordEncoder
      │
      ▼
Authentication Success
      │
      ▼
SecurityContext
      │
      ▼
Authorization Check
      │
      ▼
Controller
      │
      ▼
Response

 

Form Login Authentication

 

Form Login is the most common authentication method for web applications.

The user enters a username and password in a login form. Spring Security verifies the credentials and creates a session. After login, the user stays authenticated until they log out or the session expires.

 
User
  │
  ▼
Login Page
  │
Username + Password
  │
  ▼
Spring Security
  │
Verify User
  │
  ▼
Session Created
  │
  ▼
Access Protected Pages

 

Project Structure

 
src
 ├── config
 │    └── SecurityConfig.java
 ├── controller
 │    └── HomeController.java
 ├── SpringSecurityApplication.java
 └── pom.xml
 

Step 1: Dependency

 
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
 

Step 2: Security Configuration

 
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public UserDetailsService userDetailsService() {

        UserDetails user = User.builder()
                .username("admin")
                .password(passwordEncoder().encode("1234"))
                .roles("ADMIN")
                .build();

        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(Customizer.withDefaults()) // Default Login Page
            .logout(Customizer.withDefaults());

        return http.build();
    }
}
 

Step 3: Controller

 
@RestController
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "Public Home";
    }

    @GetMapping("/dashboard")
    public String dashboard() {
        return "Welcome Admin";
    }
}
 

Step 4: Run the Application

Open:

 
http://localhost:8080/
 

Output:

 
Public Home
 

Now open:

 
http://localhost:8080/dashboard
 

Spring Security automatically redirects to:

 
http://localhost:8080/login
 

Enter:

 
Username : admin
Password : 1234
 

Output:

 
Welcome Admin
 

Flow

 
Browser
   │
   ▼
GET /dashboard
   │
   ▼
Not Logged In
   │
   ▼
Redirect to /login
   │
   ▼
Enter Username & Password
   │
   ▼
Authentication Success
   │
   ▼
Session Created
   │
   ▼
Redirect to /dashboard
 

Default Login Page

Spring Security provides a login page automatically.

No HTML or controller is required.

 
Username : admin
Password : 1234
 

Logout

Visit:

 
http://localhost:8080/logout
 

or call:

 
.logout(Customizer.withDefaults())
 

After logout:

  • Session is invalidated.
  • User must log in again.

Advantages

  • Very easy to configure.
  • Built-in login page.
  • Session-based authentication.
  • Ideal for Spring MVC and Thymeleaf applications.
  • No JWT or token management required.

Best Use Cases

  • Admin Panels
  • Employee Portals
  • Banking Dashboards
  • ERP Systems
  • CRM Applications
  • Traditional Web Applications

=> Form Login uses a username/password form, authenticates the user, creates an HTTP session, and protects pages until the user logs out or the session expires.

 
HTTP Basic Authentication
 
 

What is HTTP Basic Authentication?

HTTP Basic Authentication is a simple authentication method where the client sends the username and password with every HTTP request.

The credentials are Base64 encoded (not encrypted), so it should always be used with HTTPS.

 
Client
   │
   ▼
Username + Password
   │
Base64 Encode
   │
   ▼
Authorization Header
   │
   ▼
Spring Security
   │
Verify User
   │
   ▼
Response
 

No Login Page and No Session (commonly used for REST APIs).


Project Structure

 
src
 ├── config
 │    └── SecurityConfig.java
 ├── controller
 │    └── HomeController.java
 └── pom.xml
 

Step 1: Dependency

 
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
 

Step 2: Security Configuration

 
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public UserDetailsService userDetailsService() {

        UserDetails user = User.builder()
                .username("admin")
                .password(passwordEncoder().encode("1234"))
                .roles("ADMIN")
                .build();

        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/").permitAll()
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults())
            .csrf(csrf -> csrf.disable());

        return http.build();
    }
}
 

Step 3: Controller

 
@RestController
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "Public Home";
    }

    @GetMapping("/api/data")
    public String data() {
        return "Secure Data";
    }
}
 

Step 4: Run the Application

Open:

 
http://localhost:8080/
 

Output:

 
Public Home
 

Now access:

 
http://localhost:8080/api/data
 

Browser asks for credentials.

Enter:

 
Username : admin
Password : 1234
 

Output:

 
Secure Data
 

HTTP Request

 
GET /api/data HTTP/1.1
Host: localhost:8080
Authorization: Basic YWRtaW46MTIzNA==
 

admin:1234

Base64 Encoding

 
YWRtaW46MTIzNA==
 

Authentication Flow

 
Client
   │
   ▼
GET /api/data
   │
Authorization Header
   │
Basic admin:1234
   │
   ▼
BasicAuthenticationFilter
   │
   ▼
AuthenticationManager
   │
   ▼
UserDetailsService
   │
   ▼
Password Verification
   │
   ▼
Response
 

Testing with cURL

 
curl -u admin:1234 http://localhost:8080/api/data
 

Testing with Postman

  • Authorization → Basic Auth
  • Username: admin
  • Password: 1234
  • Click Send

Advantages

  • Very easy to implement.
  • No login page required.
  • Good for testing APIs.
  • Supported by browsers, Postman, and cURL.

Disadvantages

  • Username and password are sent with every request.
  • Base64 is encoding, not encryption.
  • Must be used over HTTPS.
  • Not suitable for public production APIs.

Best Use Cases

  • Internal REST APIs
  • Development and Testing
  • Microservice-to-Microservice communication (with HTTPS)
  • Small internal applications

Form Login vs HTTP Basic

FeatureForm LoginHTTP Basic
Login PageYesNo
SessionYesTypically No
Credentials SentOnce (during login)Every Request
Browser RedirectYesNo
Best ForWeb ApplicationsREST APIs
 
=> HTTP Basic Authentication sends the username and password in the Authorization: Basic header with every request. Spring Security validates the credentials using BasicAuthenticationFilter and grants access if they are correct. It is simple and useful for internal or testing APIs but should always be used over HTTPS.
 
 
Session Management

What is Session Management?

Session Management is the process of keeping a user logged in after successful authentication.

When a user logs in, Spring Security creates an HTTP Session and stores the authenticated user's information. The browser receives a Session ID (JSESSIONID) cookie and sends it with every subsequent request.

The user does not need to log in again until they log out or the session expires.

 

Authentication Flow

User


Login (Username + Password)


Authentication Success


Create HTTP Session


Generate JSESSIONID


Browser Stores Cookie


Every Request Sends JSESSIONID


Spring Security Identifies User

 

How It Works

1. User Logs In

 
Username : admin
Password : 1234
 

Spring Security authenticates the user.


2. Session is Created

 
HTTP Session

Session ID : ABC123XYZ
User       : admin
Role       : ADMIN
 

3. Browser Receives Cookie

 
Set-Cookie: JSESSIONID=ABC123XYZ
 

Browser stores the cookie automatically.


4. Next Request

 
GET /dashboard

Cookie: JSESSIONID=ABC123XYZ
 

Spring finds the session and recognizes the user.


Session Lifecycle

 
Login
   │
   ▼
Session Created
   │
   ▼
User Browses Website
   │
   ▼
Session Active
   │
   ▼
Logout / Timeout
   │
   ▼
Session Destroyed
 

Configure Session Management

 
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

    http
        .authorizeHttpRequests(auth -> auth
            .anyRequest().authenticated()
        )
        .formLogin(Customizer.withDefaults())
        .sessionManagement(session ->
            session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
        );

    return http.build();
}
 

Session Creation Policies

1. ALWAYS

Always creates a session.

 
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
 

2. IF_REQUIRED (Default)

Creates a session only when needed.

 
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
 

3. NEVER

Spring Security does not create a session but can use an existing one.

 
.sessionCreationPolicy(SessionCreationPolicy.NEVER)
 

4. STATELESS

No session is created or used.

 
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
 

Used with:

  • JWT
  • OAuth2 Bearer Tokens
  • REST APIs

Limit One Session Per User

 
http.sessionManagement(session -> session
    .maximumSessions(1)
    .maxSessionsPreventsLogin(false)
);
 

If the same user logs in from another device:

  • Old session is removed (default behavior), or
  • New login is blocked if maxSessionsPreventsLogin(true) is used.

Logout

 
http.logout(logout -> logout
    .logoutUrl("/logout")
    .invalidateHttpSession(true)
    .deleteCookies("JSESSIONID")
);
 

When the user logs out:

  • Session is invalidated.
  • JSESSIONID cookie is deleted.
  • User must log in again.

Session vs JWT

FeatureSessionJWT
Server Stores Login Yes No
Cookie Used Yes (JSESSIONID) No
Session Created Yes No
Best ForWeb ApplicationsREST APIs
LogoutEasy (invalidate session)Client removes token or token expires

 

Advantages

  • Easy to use.
  • Built into Spring Security.
  • User logs in only once.
  • Good for traditional web applications.

Disadvantages

  • Server memory is used for sessions.
  • Harder to scale across multiple servers without session sharing.
  • Not ideal for stateless REST APIs.

Best Use Cases

  • Spring MVC applications
  • Admin dashboards
  • Banking portals
  • ERP systems
  • CRM applications
  • Any session-based web application

 

=> Session Management keeps users authenticated by creating an HTTP Session after login. The browser stores a JSESSIONID cookie and sends it with each request. Spring Security uses this session to identify the authenticated user. For traditional web applications, sessions are the standard approach, while modern REST APIs commonly use SessionCreationPolicy.STATELESS with JWT instead.

 

JWT (JSON Web Token)

What is JWT?

JWT (JSON Web Token) is a compact, self-contained, and digitally signed token used to securely transfer user identity and authorization information between two parties.

Unlike session authentication, the server does not store user login information. Instead, all required user information is stored inside the token itself.

JWT is an authentication token, not encryption.

It is signed to detect tampering but its payload is usually readable by anyone who has the token.


Why JWT?

Without JWT (Session):

 
Client
   │
Login
   │
   ▼
Server
   │
Create Session
   │
Store User in Memory/Redis/DB
   │
Session ID
 

Every request:

 
Client
   │
Cookie(JSESSIONID)
   │
   ▼
Server
   │
Find Session
   │
Find User
 

Server must maintain state.


With JWT

 
Client
   │
Login
   │
   ▼
Auth Server
   │
Generate JWT
   │
Return Token
 

Every request

 
Authorization:
Bearer eyJhbGciOiJIUzI1Ni...
 

Server verifies token.

No session lookup.

No database lookup (in most cases).


JWT Authentication Flow

 
                    LOGIN

+---------+                             +----------------+
| Client  |----Username/Password------->| Authentication |
|         |                             | Service        |
+---------+                             +----------------+
                                             │
                                             │ Validate User
                                             ▼
                                     +----------------+
                                     | Database       |
                                     +----------------+
                                             │
                                      User Verified
                                             │
                                             ▼
                                    Generate JWT
                                             │
                                             ▼
<------------- JWT Token ----------------------


=================================================

             ACCESSING PROTECTED APIs

Client
   │
Authorization: Bearer JWT
   │
   ▼
Spring Security JWT Filter
   │
Extract Token
   │
Verify Signature
   │
Check Expiry
   │
Extract Username & Roles
   │
Create Authentication Object
   │
Store in SecurityContext
   │
Authorization Check
   │
Controller
 

JWT Structure

A JWT has 3 parts.

 
xxxxx.yyyyy.zzzzz
 
 
Header
.
Payload
.
Signature
 

Example

 
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

.

eyJzdWIiOiJuaXRlc2giLCJyb2xlIjoiQURNSU4iLCJleHAiOjE3MzAwMDAwMDB9

.

A8jd92jdlkjs9823jskdj8234...
 

1. Header

Contains algorithm.

 
{
  "alg":"HS256",
  "typ":"JWT"
}
 

2. Payload

Contains claims.

 
{
   "sub":"roman",
   "role":"ADMIN",
   "email":"abc@gmail.com",
   "exp":1730000000
}
 

Anyone can decode this.

Never store

  • Password
  • OTP
  • Credit card
  • Secrets

inside JWT.


3. Signature

 
HMACSHA256(

Header

+

Payload

+

SecretKey

)
 

Example

 
Signature =

HMACSHA256(
Base64(Header)
+
Base64(Payload),
SECRET_KEY
)
 

Only server knows

 
SECRET_KEY
 

Is JWT Encrypted?

No.

JWT is Signed ,Not Encrypted

Anyone can decode Header & Payload.

Only Signature cannot be forged without the secret key.


Can JWT be Modified?

Suppose attacker changes

 
{
"role":"USER"
}
 

to

 
{
"role":"ADMIN"
}
 

New payload

Old signature

Signature mismatch

Rejected.


JWT Verification

 
Incoming JWT
      │
      ▼
Split Token
Header
Payload
Signature
      │
      ▼
Recalculate Signature
using Secret Key
      │
      ▼
Compare
      │
      ├── Same
      │      │
      │      ▼
      │   Valid Token
      │
      └── Different
             │
             ▼
        Invalid Token
 

Is JWT Breakable?

If implemented correctly:

  • Strong secret (HS256) or RSA/ECDSA keys
  • HTTPS
  • Short expiration
  • Key rotation

Then forging a valid JWT is computationally infeasible.

JWTs are commonly compromised through:

  • Stolen tokens (XSS, malware, insecure storage)
  • Weak secret keys
  • Algorithm misconfiguration
  • Expired key management

Not by "cracking" the signature.

JWT Expiration

Example

 
Access Token

15 Minutes
 

After 15 minutes

401 Unauthorized

Need Refresh Token

 

Why Expiry?

Suppose attacker steals token.

Without expiry

Works forever.

With expiry

Only few minutes.

 

Refresh Token

 
Login

↓

Access Token (15 min)

+

Refresh Token (7 Days)
 

 

Flow

 
Login
   │
   ▼
Access Token
Refresh Token
   │
   ▼
API Calls
   │
Access Token Expires
   │
   ▼
Send Refresh Token
   │
   ▼
Generate New Access Token
 

 

Why Two Tokens?

Access Token

  • Short life
  • Sent on every request

Refresh Token

  • Long life
  • Used only to obtain a new access token
  • Often stored securely (HTTP-only cookie or secure storage)

 

What if Access Token is Modified?

Immediately rejected.

Signature verification fails.


What if Refresh Token Expires?

User must login again.

 

Should Roles Be Stored in JWT?

Yes.

Example

 
{
   "sub":"roman",
   "roles":[
      "ADMIN",
      "USER"
   ]
}
 

Then Spring Security creates authorities.

 
.hasRole("ADMIN")
 

works without querying the database for every request (unless you intentionally re-load user data).


Role-Based Authorization

API Level

 
.requestMatchers("/admin/**")
.hasRole("ADMIN")
 

Method Level

 
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(){}
 

Both work with JWT because the roles are extracted from the validated token and placed into the SecurityContext.


Does JWT Work for Authentication and Authorization?

Yes.

Authentication

 
Who are you?
 

JWT identifies the user.

Authorization

 
What can you access?
 

Roles/authorities inside the JWT determine access.


JWT in Microservices

Service A → Service B

 
Client
   │
JWT
   ▼
Order Service
   │
JWT
   ▼
Payment Service
 

Most commonly:

  • Service A forwards the user's JWT to Service B.
  • Service B validates the JWT independently using the same public key or shared secret (depending on the signing algorithm).

Should Internal Service Calls Use JWT?

Option 1 (Most Common)

Forward user JWT.

 
Client

↓

API Gateway

↓

Order Service

↓

Inventory Service

↓

Payment Service
 

Each service validates JWT.

Good for user-context propagation and end-to-end authorization.


Option 2

Service-to-Service Token

 
Order Service

↓

Client Credentials Token

↓

Payment Service
 

No user context.

Instead,

Service authenticates itself.

Used for internal scheduled jobs, backend communication, etc.


API Gateway Flow

 
             Client
                │
      Bearer JWT
                │
                ▼
        API Gateway
                │
     Validate JWT (optional)
                │
                ▼
        Order Service
                │
      Validate JWT again
                │
                ▼
      Business Logic
 

In production, gateways often perform initial validation (authentication, rate limiting, routing), but backend services usually also validate the token rather than blindly trusting the gateway. This is called defense in depth.


If There Is No Other Microservice

Absolutely valid.

 
Client

↓

Spring Boot App

↓

JWT Authentication

↓

Controller
 

JWT is not only for microservices.

It is widely used for:

  • REST APIs
  • Mobile apps
  • React + Spring Boot
  • Angular + Spring Boot
  • Flutter apps
  • Single backend services
  • Microservices

Spring Security JWT Authentication Flow

 
Client
   │
Login
   │
   ▼
AuthenticationManager
   │
   ▼
UserDetailsService
   │
   ▼
PasswordEncoder
   │
   ▼
Generate JWT
   │
   ▼
Client Stores JWT
   │
Every Request
Authorization: Bearer JWT
   │
   ▼
JwtAuthenticationFilter
   │
Validate Signature
Check Expiry
Extract Claims
   │
   ▼
Create Authentication
   │
   ▼
SecurityContextHolder
   │
   ▼
Authorization
   │
   ▼
Controller

 

 

Real-Time JWT Authentication Project

                +----------------------+
               |      React / App     |
               +----------+-----------+
                          |
                          | POST /login
                          | username,password
                          |
                          v
+---------------------------------------------------------+
|                 Spring Boot Application                 |
|                                                         |
|  AuthenticationController                              |
|          |                                              |
|          v                                              |
|  AuthenticationManager                                  |
|          |                                              |
|          v                                              |
|  DaoAuthenticationProvider                              |
|          |                                              |
|          v                                              |
|  UserDetailsService                                     |
|          |                                              |
|          v                                              |
|      Database                                           |
|          |                                              |
|          v                                              |
| BCryptPasswordEncoder.matches()                         |
|          |                                              |
|          v                                              |
| Authentication Success                                  |
|          |                                              |
|          v                                              |
| JwtService.generateToken()                              |
|          |                                              |
|          v                                              |
| Access Token + Refresh Token                            |
+---------------------------------------------------------+
                          |
                          |
                          | Bearer Token
                          |
                          v
+---------------------------------------------------------+
| JwtAuthenticationFilter                                 |
|                                                         |
| Extract Token                                           |
| Validate Signature                                      |
| Check Expiry                                            |
| Load User                                                |
| Create Authentication                                   |
| SecurityContextHolder                                   |
+---------------------------------------------------------+
                          |
                          v
                   Controller

Real Project Folder Structure

src/main/java

├── config
│      SecurityConfig

├── controller
│      AuthenticationController
│      UserController

├── entity
│      User

├── repository
│      UserRepository

├── security
│      JwtAuthenticationFilter
│      JwtService
│      JwtAuthenticationEntryPoint

├── service
│      CustomUserDetailsService
│      AuthenticationService

├── dto
│      LoginRequest
│      LoginResponse
│      RefreshTokenRequest

└── util
      JwtUtil (optional)

 

Complete Login Flow

Imagine this request

 
POST /login

{
   "username":"roman",
   "password":"123456"
}
 

Now let's go inside Spring Security.


Step 1

Request reaches

 
AuthenticationController
 
 
@PostMapping("/login")
public LoginResponse login(LoginRequest request){

}
 

Controller should NOT verify password.

Controller only receives request.


Step 2

Controller calls

 
authenticationService.login(request);
 

Now controller's work is finished.


Step 3

AuthenticationService

This is where real authentication begins.

 
authenticationManager.authenticate(

new UsernamePasswordAuthenticationToken(
username,
password

));
 

Question:

Who checks username?

Who checks password?

Answer:

AuthenticationManager


Step 4

AuthenticationManager

Think of it as

 
Traffic Police
 

It doesn't know users.

It simply asks

 
AuthenticationProvider

Can you authenticate?
 

Step 5

AuthenticationProvider

Usually

 
DaoAuthenticationProvider
 

Now Provider asks

 
UserDetailsService

Load User
 

Step 6

CustomUserDetailsService

 
loadUserByUsername(username)
 

It queries database

 
SELECT *

FROM users

WHERE username='roman'
 

Database returns

 
id=10

username=roman

password=$2a$asdad...

roles=ADMIN
 

Step 7

Password Verification

Very important.

Developer sends

 
123456
 

Database has

 
$2a$8jd92j...
 

Now BCrypt

 
passwordEncoder.matches(

rawPassword,

encodedPassword

)
 

If matches

Authentication Success


Step 8

Authentication Object Created

Spring creates

 
Authentication authentication
 

Inside it

 
Username

Authorities

Principal

isAuthenticated=true
 

Still

NO JWT.


Step 9

Now OUR code runs

 
jwtService.generateToken(user)
 

Now JWT generation begins.

This is NOT Spring Security.

This is YOUR code.


Step 10

JWT Generation

Header

 
{
 "alg":"HS256",
 "typ":"JWT"
}
 

Payload

 
{
 "sub":"roman",
 "role":"ADMIN",
 "iat":123456,
 "exp":123999
}
 

Then

 
Base64(Header)

+

Base64(Payload)

+

SecretKey

↓

HMACSHA256

↓

Signature
 

Finally

 
xxxxx.yyyyy.zzzzz
 

Return

 
{
   "accessToken":"eyJhbGc..."
}
 

Step 11

React stores

 
Local Storage

or

HttpOnly Cookie
 

Next Request

 
GET /products

Authorization:

Bearer eyJhbGc...
 

Now login is NOT called.

Instead

JWT Filter starts.


JwtAuthenticationFilter

Every request

 
Request

↓

JwtAuthenticationFilter

↓

Controller
 

Filter executes FIRST.


Filter extracts

 
Authorization

Bearer eyJhbGc...
 

Remove

 
Bearer
 

Now only

 
eyJhbGc...
 

Validate Token

Your code

 
jwtService.isTokenValid(token)
 

Inside

Spring JWT Library

does

 
Split Token

↓

Header

↓

Payload

↓

Signature
 

Again compute

 
Header

+

Payload

+

SecretKey

↓

HMACSHA256
 

Compare

 
Generated Signature

==

Incoming Signature
 

If different

401 Unauthorized


Then

Expiry check

 
exp

>

Current Time ?
 

If expired

401


Then

Extract Username

 
sub=roman
 

Load User Again

 
loadUserByUsername("roman")
 

Why?

Because

User may be

Disabled

Deleted

Locked

Roles changed


Create Authentication

 
UsernamePasswordAuthenticationToken
 

Now store

 
SecurityContextHolder

.setAuthentication(authentication)
 

Now Spring knows

 
Current User

=

roman
 

Controller starts.


Controller

 
@GetMapping("/admin")
 

Now authorization begins.


Security checks

 
.hasRole("ADMIN")
 

JWT contains

 
ADMIN
 

Allowed.

Otherwise

403 Forbidden.


Entire Runtime Flow

 
Browser

↓

POST /login

↓

AuthenticationController

↓

AuthenticationService

↓

AuthenticationManager

↓

AuthenticationProvider

↓

UserDetailsService

↓

Database

↓

PasswordEncoder

↓

Authentication Success

↓

JwtService

↓

JWT Generated

↓

Browser Stores JWT

↓

=================================================

GET /products

↓

JwtAuthenticationFilter

↓

Extract JWT

↓

Validate Signature

↓

Check Expiry

↓

Load User

↓

Create Authentication

↓

SecurityContextHolder

↓

Authorization

↓

Controller

↓

Response
 

Real-Time Project & Spring Security Internals

Phase 1 — Build the Project

Spring Boot 3.x

Spring Security 6.x

MySQL/PostgreSQL

JWT

Refresh Token

Role Based Authentication

Method Security

API Level Security

Exception Handling

Logout

Token Revocation

Microservice Ready

 

Project Structure

 
auth-service

├── config
├── controller
├── dto
├── entity
├── repository
├── security
├── service
├── exception
├── util
└── application.yml

 

Scenario 1 — First Login (Correct Username & Password)

 
Client

↓

POST /login

↓

AuthenticationManager

↓

JWT Generated

↓

Access Token

↓

Refresh Token

↓

200 OK

 

Read Project code you will more details.

32 min read
Jul 06, 2026
By Sogdo Academy
Share