Version: 1.0.0
A full-stack authentication and user profile management solution built with Spring Boot (backend) and React (frontend). This service provides comprehensive user authentication, authorization, security features, and administrative tools.
This project implements a production-ready authentication service with features including JWT-based authentication, OAuth2 (Google) integration, role-based access control, whitelist/blacklist management, masked login functionality, and comprehensive security measures.
- User Registration: Email-based registration with email verification
- Login/Logout: JWT-based authentication with access tokens (15 minutes) and refresh tokens (7 days, stored in httpOnly cookies and rotated on refresh)
- Email Verification: Token-based verification with resend functionality
- Password Reset: Secure password reset flow with 1-hour token expiration and cooldown between requests
- OAuth2 Google Authentication: Social login via Google OAuth2 with access token returned via URL fragment
- Token Refresh: Automatic access token refresh via httpOnly refresh cookie with refresh token rotation and re-use detection
- Role-Based Access Control (RBAC): USER and ADMIN roles with protected endpoints
- Resource Access Control: Endpoint-level access checks for admin panel and user management
- Whitelist/Blacklist Access Control:
- Configurable access mode (WHITELIST/BLACKLIST) via
ACCESS_MODE_DEFAULT - Admin can switch modes with OTP + password verification
- Admin can manage whitelist and blacklist entries
- Blacklist always blocks login regardless of credentials
- Configurable access mode (WHITELIST/BLACKLIST) via
- Account Protection:
- 5 failed login attempts โ 5-minute temporary lock with email notification
- 10 failed attempts โ permanent account block with email notification
- Rate Limiting: Bucket4j per-IP rate limiting
- Authentication endpoints: 120 requests/minute (2 requests/second)
- Admin endpoints: 120 requests/minute (2 requests/second)
- Resend endpoints: 1 request/minute per email
- Responses include
Retry-Afterheader andretryAfterSecondsfield to inform clients when to retry
- Password Validation: Strong password requirements with regex validation
- Secure Password Storage: BCrypt password hashing
- JWT Security: Refresh token stored in httpOnly cookie with rotation and re-use detection; access token kept in memory with configurable expiration
- CSRF Protection: Enabled for cookie-based refresh/logout flows
- Content Security Policy (CSP): Default CSP headers to reduce XSS risk
- Security Event Logging: Comprehensive logging of rate limiting and authentication failures
- Profile Management: View and update user profile data
- User Management: Admin can view user details, create new users, update name/email/block status, update roles via dedicated endpoint, and delete users
- User Search & Pagination: Search users with pagination support
- Role Management: Admin can assign and update user roles
- User Management Interface: Admin interface for managing users (view, create, update, delete)
- Access List Management: Manage whitelist and blacklist entries
- Access Mode Control: Switch between WHITELIST and BLACKLIST modes (requires OTP + password)
- Admin Initialization: Automatic admin account creation on startup (when
ADMIN_ENABLED=true)- Admin receives setup password link via email
- Masked Login Settings: Configure masked login functionality (enable/disable, select template)
- Audit Trail: Separate log file for all admin actions
Masked Login is a security feature that displays a fake page (template) to unauthenticated users instead of the real login page. This helps protect the actual login endpoint from automated attacks and reconnaissance.
- 10 Pre-built Templates:
- 404 Not Found
- Site Maintenance
- Cooking Recipe
- Terms of Service
- About Us
- Cat Facts
- Lorem Ipsum
- Weather
- Coming Soon
- Database Error
- Admin Configuration: Enable/disable masked login and select template via admin panel (requires password confirmation)
- Public Settings Endpoint: Frontend can check if masked login is enabled without authentication
- Secret Access: Authenticated users and users with
?secret=trueparameter can access the real login page
- Multi-language Support: Full localization for 4 languages (EN, DE, RU, UA), including validation errors
- Asynchronous Email Notifications: Lock/block notifications sent asynchronously
- Resend Cooldown: Backend enforces 1 request/minute per email with HTTP 429; frontend shows countdown timer
- Comprehensive Logging:
- Request correlation with trace IDs across all logs
- Performance metrics for critical operations
- Structured logging support (JSON format when
LOG_JSON_ENABLED=true) - Time-based log rotation with size limits
- Separate log files for application, errors, and admin actions
- Java 25
- Spring Boot 4.0.2 (Spring Framework 7.0.3)
- Spring Security - Authentication and authorization
- Spring Data JPA / Hibernate - Database persistence
- PostgreSQL 17.5 - Database
- JWT (jjwt 0.12.6) - Token-based authentication
- OAuth2 Client - Google OAuth2 integration
- Bucket4j 8.10.1 - Rate limiting
- SMTP Mail - Email notifications
- Lombok - Boilerplate reduction
- SLF4J + Logback - Logging with structured logging support
- Testcontainers 2.0.2 - Integration testing with Docker containers
- JUnit 5 - Unit and integration testing
- Mockito - Mocking framework
- React 18
- TypeScript 5.2
- Vite 5 - Build tool and dev server
- Material-UI (MUI) 5 - UI component library
- React Router 6 - Client-side routing
- Context API - State management
- Axios - HTTP client
- i18next - Internationalization (EN, DE, RU, UA)
- Vitest - Unit testing
- Testing Library - React component testing
- Java 25 and Maven for the backend
- Node.js 18+ and npm for the frontend
- Docker (optional) for containerized workflow and Testcontainers
- PostgreSQL database (or use Docker)
-
Build and test backend:
./build-and-test.sh
-
Deploy with Docker Compose:
# For local development (with exposed ports) ./deploy.sh local # For server deployment (no exposed ports, uses networks) ./deploy.sh server
-
Backend:
cd backend mvn clean install mvn spring-boot:run -
Frontend:
cd frontend npm install npm run dev -- --host --port 5173
Create a .env file based on env.example. Required variables:
DB_URL- Database connection URLDB_USERNAME- Database usernameDB_PASSWORD- Database passwordJWT_ACCESS_SECRET- Secret key for access tokensJWT_REFRESH_SECRET- Secret key for refresh tokensGOOGLE_CLIENT_ID- Google OAuth2 client IDGOOGLE_CLIENT_SECRET- Google OAuth2 client secretMAIL_HOST- SMTP server hostMAIL_USERNAME- SMTP usernameMAIL_PASSWORD- SMTP passwordFRONTEND_URL- Frontend application URLADMIN_ENABLED- Enable admin initialization (true/false)ADMIN_EMAIL- Admin email addressADMIN_USERNAME- Admin username
See env.example for all available configuration options.
Use this service as a central auth provider while keeping other apps separate.
Route the following paths to different services (via nginx/traefik/reverse proxy):
- Auth frontend pages (e.g.
/login,/register,/forgot-password,/reset-password,/verify,/oauth2/success,/profile,/admin) โ auth-service frontend /api/auth/*โ auth-service backend/superappโ other app frontend/superapi/*โ other app backend
Use path-based routing on a single domain. This example routes /superapp and /superapi first, then defaults to the auth frontend for all other pages.
server {
listen 80;
server_name my-app.com;
# Auth API
location /api/auth/ {
proxy_pass http://auth-backend;
}
# Other app API
location /superapi/ {
proxy_pass http://superapp-backend;
}
# Other app frontend
location /superapp/ {
proxy_pass http://superapp-frontend;
}
# Auth frontend (login/profile/admin/register/etc.)
location / {
proxy_pass http://auth-frontend;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}Send users to: /login?redirect=/superapp
Only relative paths are accepted (e.g. /superapp, /superapp/page).
On app start:
await fetch('/api/auth/refresh', { method: 'POST', credentials: 'include' });
// 200 -> save accessToken in memory and continue
// 401 -> window.location.replace('/login?redirect=/superapp')Attach Authorization: Bearer <accessToken> for API calls. If you receive 401, refresh and retry.
Validate access tokens with the same JWT_ACCESS_SECRET used by this service.
Refresh tokens are httpOnly cookies and are not available to your backend.
Access token claims:
sub- user emailroles- list of role namesuserId- numeric user id
- Refresh cookie is
Secure=trueby default. For HTTP local dev set:SECURITY_REFRESH_COOKIE_SECURE=false
- Refresh cookie uses
SameSite=StrictandPath=/api/auth. POST /api/auth/refreshandPOST /api/auth/logoutrequireX-XSRF-TOKEN. CallGET /api/auth/csrfonce per session to set the CSRF cookie if your client doesn't already send it.
Settings are managed via application.yml. Sensitive data (database credentials, JWT secrets, mail settings, OAuth) must be provided via environment variables.
- Configuration file:
logback-spring.xml - Log files:
logs/app.log- General application logslogs/error.log- Errors and warnings onlylogs/admin.log- Admin action audit trail
- Environment variables:
LOG_LEVEL- Root log levelLOG_FILE_ENABLED- Enable file logging (default: true)LOG_JSON_ENABLED- Enable JSON structured logging (default: false)LOG_MAX_HISTORY- Number of days to keep logs (default: 30)LOG_MAX_SIZE- Maximum log file size (default: 10MB)LOG_TOTAL_SIZE_CAP- Total size cap for all logs (default: 1GB)SLOW_REQUEST_THRESHOLD_MS- Threshold for slow request warnings (default: 1000ms)
Note: Mount logs/ as a Docker volume for log persistence.
POST /register- User registrationPOST /login- User loginPOST /refresh- Refresh access tokenPOST /logout- Logout and clear refresh cookiePOST /verify- Verify email addressPOST /resend-verification- Resend verification emailPOST /forgot-password- Initiate password resetPOST /reset-password- Reset password with tokenGET /csrf- Issue CSRF cookie for XSRF protectionGET /check-access/{resource}- Check user access to resourceGET /oauth2/success- OAuth2 callback endpoint
Notes:
POST /loginandPOST /refreshset the refresh token httpOnly cookie and returnaccessTokenin JSON.POST /refreshandPOST /logoutrequire theX-XSRF-TOKENheader (callGET /csrfto prime it).
GET /profile- Get user profile (authenticated)POST /profile- Update user profile (authenticated)GET /check- Check authentication status
GET /users- Get all users (paginated, with search)POST /users- Create new userGET /users/{id}- Get user by IDPUT /users/{id}- Update userDELETE /users/{id}- Delete userPUT /users/{id}/roles- Update user rolesGET /roles- Get all rolesGET /whitelist- Get whitelist entriesPOST /whitelist/add- Add email to whitelistDELETE /whitelist/remove- Remove email from whitelistGET /blacklist- Get blacklist entriesPOST /blacklist/add- Add email to blacklistDELETE /blacklist/remove- Remove email from blacklistGET /access-mode- Get current access mode settingsPOST /access-mode/request-otp- Request OTP for mode changePOST /access-mode/change- Change access mode (requires OTP + password)POST /verify-admin- Verify admin passwordGET /masked-login/settings- Get masked login settingsPUT /masked-login/settings- Update masked login settings (requires password)
GET /settings- Get masked login public settings (enabled/disabled, template ID)GET /template/{templateId}- Get masked login template HTML (template ID: 1-10)
Authentication-service/
โโโ backend/ # Spring Boot backend
โ โโโ src/
โ โ โโโ main/
โ โ โ โโโ java/ # Java source code
โ โ โ โโโ resources/ # Configuration files
โ โ โโโ test/ # Test code
โ โโโ pom.xml # Maven dependencies
โโโ frontend/ # React frontend
โ โโโ src/
โ โ โโโ components/ # React components
โ โ โโโ pages/ # Page components
โ โ โโโ services/ # API services
โ โ โโโ assets/ # Static assets
โ โโโ package.json # npm dependencies
โโโ docker-compose.yml # Docker Compose configuration
โโโ README.md # This file
The following improvements are planned for future versions:
Rate Limiting Service: Currently uses in-memory storage (ConcurrentHashMap) for rate limiting buckets. This works well for single-instance deployments, but has limitations:
- Rate limits are not shared across multiple instances
- When scaling horizontally (multiple instances behind a load balancer), each instance maintains its own rate limit counters
- This means the effective rate limit becomes:
configured_limit ร number_of_instances
Improvement (only needed for horizontal scaling): Migrate to Redis-backed rate limiting using Bucket4j's Redis integration. This ensures rate limits are shared across all instances and work correctly in clustered deployments.
Note: For single-instance deployments, the current in-memory implementation is perfectly adequate and performant.
Service runs on Java 25 LTS with virtual threads enabled for request handling to improve throughput under high concurrent load. To disable, set spring.threads.virtual.enabled=false.
To use this authentication service in a microservices architecture, the following components need to be implemented:
-
JWT Validation Endpoint: Add a public endpoint (e.g.,
/api/auth/validateor/api/auth/user-info) that accepts JWT tokens and returns user information (email, roles). This allows other services to validate tokens and get user context without direct database access. -
Client Library/Module: Create a reusable authentication client library (Maven/Gradle module) that other services can integrate to:
- Validate JWT tokens locally (using shared secret/public key)
- Extract user information and roles from tokens
- Handle token expiration and refresh scenarios
- Provide consistent authentication handling across services
Current State: Service is designed as a standalone authentication service but requires additional endpoints and client libraries for microservice integration.
- Monitoring & Metrics: Add Spring Boot Actuator or Micrometer + Prometheus integration
- API Documentation: Add OpenAPI/Swagger documentation
- Caching: Implement caching for frequently accessed data (roles, settings)
- Health Checks: Enhanced health check endpoints for Kubernetes/Docker orchestration
Complete step-by-step authentication flow demonstration:
|
|
|
|
|
|
|
|
Standard login form with email and password fields. Also includes Google OAuth2 authentication option.
User registration form for creating new accounts.
Email verification page for confirming account registration.
User profile page displaying account information and status. For admin users, includes a link to the admin panel.
Profile editing interface for updating user information.
Admin panel - Users management tab with pagination.
Form for creating new users. Allows immediate admin role assignment and account blocking during creation.
Admin panel - Whitelist and blacklist management for access control.
Admin panel - Access mode control for switching between WHITELIST and BLACKLIST modes for the entire application.
Admin panel - Masked login settings with template preview.
- Dmytro Shubchynskyi
For any questions or further information, please contact d.shubchynskyi@gmail.com



















