Authentication and Authorization Flow
Relevant source files
The following files were used as context for generating this wiki page:
- src/main/java/com/ncs/zalopay/controller/AuthController.java
- src/main/java/com/ncs/zalopay/security/WebSecurityConfig.java
- src/main/java/com/ncs/zalopay/security/jwt/JwtUtils.java
- src/main/java/com/ncs/zalopay/security/jwt/AuthTokenFilter.java
- src/main/java/com/ncs/zalopay/security/services/UserDetailsServiceImpl.java
- src/main/java/com/ncs/zalopay/models/User.java
- src/main/java/com/ncs/zalopay/models/Role.java
- src/main/java/com/ncs/zalopay/payload/request/SignupRequest.java
- src/main/java/com/ncs/zalopay/payload/request/LoginRequest.java
- src/main/java/com/ncs/zalopay/payload/response/JwtResponse.java
- src/main/resources/application.properties
Introduction
The authentication and authorization system in this project is built using Spring Security and JSON Web Tokens (JWT). It provides a RESTful API for user registration and login. Once a user is authenticated, a JWT is issued, which must be included in the header of subsequent requests to access protected resources.
The flow is managed by a combination of controllers, security configuration, custom filters, and service classes. WebSecurityConfig defines the security rules, AuthController handles signup and signin requests, JwtUtils is responsible for JWT creation and validation, and AuthTokenFilter intercepts incoming requests to process the JWT and establish the user's identity within the security context.
Core Security Configuration
The primary security setup is defined in WebSecurityConfig.java. This class configures CORS, CSRF, session management, and authorization rules for API endpoints.
- Session Management: The session creation policy is set to
STATELESS, which is appropriate for a REST API using token-based authentication. - Password Encoding: A
BCryptPasswordEncoderis used to securely hash and verify user passwords. - Authentication Filter: The custom
AuthTokenFilteris registered to be executed before the standardUsernamePasswordAuthenticationFilter.
Sources: src/main/java/com/ncs/zalopay/security/WebSecurityConfig.java:43-80
Endpoint Authorization Rules
The following table outlines the access rules for different API paths as configured in the configure(HttpSecurity http) method.
| Path Pattern | Access Rule |
|---|---|
/api/auth/** | Permit All (Public) |
/api/test/all | Permit All (Public) |
/api/test/user | Requires USER, MODERATOR, or ADMIN role |
/api/test/mod | Requires MODERATOR role |
/api/test/admin | Requires ADMIN role |
| Any other request | Must be authenticated |
Sources: src/main/java/com/ncs/zalopay/security/WebSecurityConfig.java:62-70
User Registration (Signup)
New users are registered via a POST request to the /api/auth/signup endpoint. The controller validates the request to ensure the username and email are not already in use, encodes the password, assigns roles, and saves the new user to the database.
Sources: src/main/java/com/ncs/zalopay/controller/AuthController.java:67-123
Signup Flow
The diagram below illustrates the sequence of operations during user registration.
Signup Request Payload
The request body must conform to the SignupRequest class structure.
| Field | Type | Validation | Description |
|---|---|---|---|
username | String | @NotBlank, @Size(min=3, max=20) | The desired username. |
email | String | @NotBlank, @Size(max=50), @Email | The user's email address. |
role | Set<String> | A set of role names (e.g., "admin", "mod", "user"). | |
password | String | @NotBlank, @Size(min=6, max=40) | The user's password. |
Sources: src/main/java/com/ncs/zalopay/payload/request/SignupRequest.java
User Authentication (Signin)
Authenticated users obtain a JWT by sending a POST request with their credentials to the /api/auth/signin endpoint. The system uses Spring Security's AuthenticationManager to validate the credentials. Upon success, a JWT is generated and returned to the client.
Sources: src/main/java/com/ncs/zalopay/controller/AuthController.java:42-64
Signin Flow
This diagram shows the process of authenticating a user and issuing a JWT.
Login Payloads
Login Request
The request body for the signin endpoint.
| Field | Type | Validation | Description |
|---|---|---|---|
username | String | @NotBlank | The user's username. |
password | String | @NotBlank | The user's password. |
Sources: src/main/java/com/ncs/zalopay/payload/request/LoginRequest.java
JWT Response
The successful response body containing the token and user information.
| Field | Type | Description |
|---|---|---|
token | String | The JWT access token. |
id | Long | The user's unique ID. |
username | String | The user's username. |
email | String | The user's email. |
roles | List<String> | A list of roles assigned to the user. |
Sources: src/main/java/com/ncs/zalopay/payload/response/JwtResponse.java
JWT Generation and Validation
The JwtUtils class centralizes all JWT-related operations. It uses a secret key and expiration time defined in application.properties to sign and create tokens.
Sources: src/main/java/com/ncs/zalopay/security/jwt/JwtUtils.java, src/main/resources/application.properties:10-11
JWT Generation
The generateJwtToken method creates a token using the authenticated user's username as the subject.
// src/main/java/com/ncs/zalopay/security/jwt/JwtUtils.java:29-38
public String generateJwtToken(Authentication authentication) {
UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
return Jwts.builder()
.setSubject((userPrincipal.getUsername()))
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
JWT Validation
The validateJwtToken method parses an incoming token string and verifies its signature and expiration. It catches various exceptions to handle invalid tokens gracefully.
Sources: src/main/java/com/ncs/zalopay/security/jwt/JwtUtils.java:51-68
Request Authorization and Filtering
The AuthTokenFilter is a crucial component that intercepts every incoming HTTP request to check for a JWT and authenticate the user for that request.
Sources: src/main/java/com/ncs/zalopay/security/jwt/AuthTokenFilter.java
Filter Logic Flow
This flowchart shows the decision-making process within the AuthTokenFilter.
The filter first calls parseJwt to extract the token from the Authorization: Bearer <token> header. If a valid token is found, it retrieves the username, loads the UserDetails from the database via UserDetailsServiceImpl, and creates a UsernamePasswordAuthenticationToken. This token is then set in the SecurityContextHolder, making the user's identity available for the duration of the request.
Sources: src/main/java/com/ncs/zalopay/security/jwt/AuthTokenFilter.java:32-54, src/main/java/com/ncs/zalopay/security/services/UserDetailsServiceImpl.java
Data Models
The authentication system relies on User and Role entities, which are mapped to database tables.
Entity Relationship Diagram
The diagram shows a many-to-many relationship between users and roles.
User Entity
| Field | Type | Constraints |
|---|---|---|
id | Long | @Id, @GeneratedValue |
username | String | @NotBlank, @Size(max = 20) |
email | String | @NotBlank, @Size(max = 50), @Email |
password | String | @NotBlank, @Size(max = 120) |
roles | Set<Role> | @ManyToMany, FetchType.LAZY |
Sources: src/main/java/com/ncs/zalopay/models/User.java
Role Entity
| Field | Type | Constraints |
|---|---|---|
id | Integer | @Id, @GeneratedValue |
name | ERole | @Enumerated(EnumType.STRING), @Column(length = 20) |
Sources: src/main/java/com/ncs/zalopay/models/Role.java
Summary
The project implements a robust, token-based authentication and authorization flow using Spring Security and JWT. Users register and sign in through the AuthController to receive a JWT. This token is then passed with each subsequent API request in the Authorization header. The AuthTokenFilter validates this token, and WebSecurityConfig enforces role-based access control on protected endpoints. This stateless approach is well-suited for modern RESTful applications and microservices architectures.