1. Introduction
When you develop a REST API, you will face one of the most important security questions:
Who is asking, and what can they access?
This is where authentication and authorization come in.
Authentication
Authentication answers:
Who are you?
For example, when a user logs in using an email and password, the backend verifies the provided credentials.
Email + Password
|
v
Authentication
|
v
User IdentityIf the credentials are valid, the user is authenticated.
Authorization
Authorization happens after authentication. It answers:
What can you access?
For example, an application can have two roles:
USER
ADMIN
An ADMIN may be allowed to create, update, and delete products, while a USER may only be allowed to view products.
The difference can be summarized as:
Authentication → Who are you?
Authorization → What can you access?Why JWT?
For REST APIs, we may want authentication to be stateless.
Instead of keeping a traditional server-side session, the server can issue a token after successful login. The client then includes that token with subsequent requests.
The overall flow is:
Login
|
v
Validate Credentials
|
v
Generate JWT
|
v
Client Receives JWT
|
v
Client Sends JWT
|
v
Server Validates JWT
|
v
Access Allowed / DeniedIn this article, we will explore the JWT authentication flow implemented with Spring Boot and Spring Security.
2. What Is JWT?
JWT stands for JSON Web Token.
It is a compact token format commonly used to pass information between a client and a server.
A JWT consists of three parts:
Header.Payload.SignatureA JWT has a structure similar to:
xxxxx.yyyyy.zzzzzHeader
The header contains information about the token, including the signing algorithm and token type.
For example:
{
"alg": "HS256",
"typ": "JWT"
}The alg property identifies the algorithm used to sign the token, while typ identifies the token type.
Payload
The payload contains claims. Claims are pieces of information about the user or token.
For example:
{
"sub": "[email protected]",
"role": "USER",
"iat": 1724500000,
"exp": 1724503600
}Common claims include:
sub: Subject or user identifieriat: Issued-at timeexp: Expiration timerole: User role
The JWT payload is encoded, not encrypted by default. Therefore, sensitive information such as passwords should not be stored inside the payload.
Signature
The signature helps ensure that the token has not been altered.
Conceptually:
Signature = HMAC(Header + "." + Payload, Secret Key)When the server receives the token, it can verify the signature. If the token has been modified, the signature verification will fail.
Stateless Authentication
Traditional session-based authentication can be represented as:
Client
|
v
Session
|
v
Server
|
v
Session DataWith JWT-based authentication:
Client
|
v
JWT
|
v
Server Validates JWTJWT can be used in distributed applications and REST APIs because the server does not need to maintain a traditional session for every client.
3. Why Spring Security?
Sending a username and password is not enough to implement authentication in a real application.
An application also needs to handle:
Password verification
Authentication
Authorization
Roles and permissions
Request filtering
Security context
Protected endpoints
Authentication failures
Spring Security provides the security infrastructure for Spring applications.
Security rules can be defined centrally instead of implementing them separately in every controller.
A simplified request flow is:
HTTP Request
|
v
Spring Security
|
v
Authentication
|
v
Authorization
|
v
ControllerIn Spring Security, authentication and authorization are separate concepts.
Authentication determines whether the user is authenticated.
Email + Password
|
v
AuthenticationManager
|
v
Credentials Valid
|
v
AuthenticatedAuthorization determines whether the authenticated user has permission to access a resource.
Authenticated User
|
v
Role
|
+----> USER
|
+----> ADMIN
|
v
Limited Access / Full AccessIn simple terms:
Authentication → Who is the user?
Authorization → What can the user access?4. JWT Authentication Flow
Let's look at what happens when a user logs in and accesses a protected API.
The overall flow is:
Login Request
|
v
AuthenticationManager
|
v
UserDetailsService
|
v
Password Validation
|
v
Generate JWT
|
v
Return Token
|
v
Client
|
v
JWT Filter
|
v
Validate JWT
|
v
SecurityContext
|
v
Authorization
|
v
Protected APIStep 1: Login Request
The user provides credentials to the login endpoint.
POST /api/auth/loginFor example:
{
"email": "[email protected]",
"password": "password123"
}These credentials need to be verified by the backend.
Step 2: AuthenticationManager
Spring Security's AuthenticationManager handles the authentication request.
Login Request
|
v
AuthenticationManagerIt attempts to authenticate the user using the configured authentication mechanism.
If the credentials are incorrect, authentication fails.
Step 3: UserDetailsService
Spring Security needs to retrieve the user's information from the database.
This is typically handled using UserDetailsService.
AuthenticationManager
|
v
UserDetailsService
|
v
Database
|
v
UserThe user information can include:
Email
Password
Role
The database should not store passwords as plain text. Passwords should be stored using a secure password-hashing mechanism, such as BCrypt.
Step 4: Generate JWT
After successful authentication, a JWT is generated with relevant claims such as the username, role, and expiration time.
Authenticated User
|
v
JWT Generator
|
v
Signed JWTThe token is then returned to the client.
Step 5: Client Sends the JWT
For subsequent requests, the client includes the JWT in the Authorization header.
For example:
GET /api/products
Authorization: Bearer <JWT>The Bearer prefix indicates that the following value is a bearer token.
Step 6: JWT Filter
Before the request reaches the controller, the JWT authentication filter can inspect the request.
HTTP Request
|
v
JWT Filter
|
v
Authorization Header
|
v
Extract JWTThe filter extracts the token and checks whether it can be used for authentication.
Step 7: Validate JWT
The application validates the token, including its signature and expiration.
JWT
|
+-- Signature Validation
|
+-- Expiration Check
|
+-- Claims ExtractionIf the token is invalid or expired, the request should not be considered authenticated.
Step 8: SecurityContext
If the JWT is valid, Spring Security can create an Authentication object and place it in the SecurityContext.
Valid JWT
|
v
Authentication Object
|
v
SecurityContextSpring Security can now determine which user the request is associated with.
Step 9: Authorization
Finally, Spring Security verifies whether the authenticated user has permission to access the requested endpoint.
For example:
GET /api/products
|
v
Authenticated?
|
YES
|
v
Required Role?
|
v
Access GrantedFor an endpoint that requires administrator permissions:
DELETE /api/products/{id}
|
v
Authenticated?
|
v
ADMIN Role?
/ \
YES NO
| |
v v
Allow DenyThis completes the JWT authentication and authorization flow.
Key Takeaways
JWT authentication and Spring Security work together to provide a structured security flow for REST APIs.
The main concepts to remember are:
Authentication determines who the user is.
Authorization determines what the user can access.
JWT provides a token-based mechanism that can be used for stateless authentication.
AuthenticationManager handles the authentication process.
UserDetailsService retrieves user information.
The JWT filter extracts and validates the token from incoming requests.
The SecurityContext holds the authenticated user's security information for the current request.
Roles and permissions are used to control access to protected resources.
The overall lifecycle can be summarized as:
Login
|
v
Validate Credentials
|
v
Generate JWT
|
v
Client Stores Token
|
v
Client Sends JWT
|
v
JWT Filter
|
v
Validate Token
|
v
SecurityContext
|
v
Authorization
|
v
Protected APIUnderstanding this lifecycle makes it easier to work with JWT authentication and Spring Security when building Spring Boot REST APIs.
Join the conversation! Your thoughts help the community grow.