A comprehensive Spring Boot application demonstrating JWT-based authentication and role-based authorization with refresh token support. This project showcases modern security practices using Spring Security 7 and Spring Boot 4.
- π JWT Authentication - Secure token-based authentication
- π Refresh Token Support - Long-lived refresh tokens stored in database
- π₯ User Registration & Login - Complete authentication flow
- π‘οΈ Role-Based Access Control (RBAC) - Fine-grained authorization with roles and privileges
- πͺ HTTP-Only Cookies - Secure token storage in cookies
- π OpenAPI/Swagger Documentation - Interactive API documentation
- β Password Validation - Strong password requirements
- π« Custom Error Handling - Customized access denied and unauthorized handlers
- π Spring Security Integration - Full Spring Security configuration
- Java 17
- Spring Boot 4.0.1
- Spring Security 7
- Spring Data JPA
- PostgreSQL - Database
- JWT (jjwt 0.11.5) - JSON Web Token implementation
- Maven - Build tool
- Lombok - Boilerplate reduction
- OpenAPI/SpringDoc - API documentation
- Bean Validation - Request validation
Before you begin, ensure you have the following installed:
- JDK 17 or higher
- Maven 3.6+
- PostgreSQL 12+
- Git (for cloning the repository)
git clone https://github.com/yourusername/security.git
cd securityCreate a PostgreSQL database:
CREATE DATABASE db_security;Update the application.yml file with your database credentials:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/db_security
username: postgres
password: ${POSTGRES_PASSWORD} # Set this environment variableImportant: Set the POSTGRES_PASSWORD environment variable with your PostgreSQL password:
Windows (PowerShell):
$env:POSTGRES_PASSWORD="your_password"Windows (CMD):
set POSTGRES_PASSWORD=your_passwordLinux/Mac:
export POSTGRES_PASSWORD=your_passwordmvn clean installmvn spring-boot:runOr using the Maven wrapper:
./mvnw spring-boot:runThe application will start on http://localhost:8086
Once the application is running, access the Swagger UI for interactive API documentation:
http://localhost:8086/swagger-ui.html
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/v1/auth/register |
Register a new user | β |
POST |
/api/v1/auth/authenticate |
Login and get JWT tokens | β |
POST |
/api/v1/auth/refresh-token |
Refresh access token | β |
POST |
/api/v1/auth/refresh-token-cookie |
Refresh token via cookie | β |
POST |
/api/v1/auth/logout |
Logout and invalidate tokens | β |
GET |
/api/v1/auth/info |
Get authentication info | β |
| Method | Endpoint | Description | Required Role | Required Privilege |
|---|---|---|---|---|
GET |
/api/v1/admin/resource |
Admin read resource | ADMIN |
READ_PRIVILEGE |
DELETE |
/api/v1/admin/resource |
Admin delete resource | ADMIN |
DELETE_PRIVILEGE |
POST |
/api/v1/user/resource |
User create resource | ADMIN or USER |
WRITE_PRIVILEGE |
PUT |
/api/v1/user/resource |
User update resource | ADMIN or USER |
UPDATE_PRIVILEGE |
curl -X POST http://localhost:8086/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"firstname": "John",
"lastname": "Doe",
"email": "john.doe@example.com",
"password": "SecurePass123!"
}'curl -X POST http://localhost:8086/api/v1/auth/authenticate \
-H "Content-Type: application/json" \
-d '{
"email": "john.doe@example.com",
"password": "SecurePass123!"
}'Response:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer"
}Tokens are also set as HTTP-only cookies automatically.
curl -X GET http://localhost:8086/api/v1/admin/resource \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Or if using cookies (set automatically during login):
curl -X GET http://localhost:8086/api/v1/admin/resource \
--cookie "jwt-cookie=YOUR_JWT_TOKEN"curl -X POST http://localhost:8086/api/v1/auth/refresh-token \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "YOUR_REFRESH_TOKEN"
}'src/
βββ main/
β βββ java/fr/mossaab/security/
β β βββ config/ # Security configuration classes
β β β βββ SecurityConfiguration.java
β β β βββ ApplicationSecurityConfig.java
β β β βββ JwtAuthenticationFilter.java
β β β βββ CustomAccessDeniedHandler.java
β β β βββ Http401UnauthorizedEntryPoint.java
β β βββ controller/ # REST controllers
β β β βββ AuthenticationController.java
β β β βββ AuthorizationController.java
β β βββ entities/ # JPA entities
β β β βββ User.java
β β β βββ RefreshToken.java
β β βββ enums/ # Enumerations
β β β βββ Role.java
β β β βββ Privilege.java
β β β βββ TokenType.java
β β βββ service/ # Business logic
β β β βββ AuthenticationService.java
β β β βββ JwtService.java
β β β βββ RefreshTokenService.java
β β β βββ impl/ # Service implementations
β β βββ repository/ # Data access layer
β β β βββ UserRepository.java
β β β βββ RefreshTokenRepository.java
β β βββ payload/ # DTOs
β β β βββ request/
β β β βββ response/
β β βββ validation/ # Custom validators
β β βββ exception/ # Custom exceptions
β β βββ handlers/ # Exception handlers
β βββ resources/
β βββ application.yml # Application configuration
βββ test/ # Test files
The application implements a role-based access control system:
Roles:
ADMIN- Full access with all privilegesUSER- Limited access with read and write privileges
Privileges:
READ_PRIVILEGE- Read accessWRITE_PRIVILEGE- Create accessUPDATE_PRIVILEGE- Update accessDELETE_PRIVILEGE- Delete access
- Access Token Expiration: 15 minutes (900,000 ms)
- Refresh Token Expiration: 15 days (1,296,000,000 ms)
- Token Storage: HTTP-only cookies for enhanced security
The application enforces strong password validation. Ensure your password meets the requirements defined in the StrongPassword validator.
Configure JWT settings in application.yml:
application:
security:
jwt:
secret-key: YOUR_SECRET_KEY # Change this in production!
expiration: 900000 # 15 minutes
cookie-name: jwt-cookie
refresh-token:
expiration: 1296000000 # 15 days
cookie-name: refresh-jwt-cookiesecret-key in production environments!
Run the test suite:
mvn testThis project is open source and available under the MIT License.
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
β If you find this project helpful, please consider giving it a star!