This project was built to understand how real backend systems handle authentication, authorization, and stateless security.
Instead of relying only on Spring Boot auto-configuration, I implemented the core security flow myself using Spring Security and JWTs.
The goal was to learn how login systems actually work under the hood and how APIs protect routes using tokens rather than server sessions.
- User registration with BCrypt password hashing
- User login with JWT token generation
- Stateless authentication (no server-side sessions)
- Role-based access control (e.g. USER vs ADMIN)
- Custom JWT authentication filter integrated into Spring Security
- Protected API routes that require a valid token
- Clean layered backend structure (Controller → Service → Security → Repository)
- Docker support for running the service in a container
| Area | Technology |
|---|---|
| Language | Java |
| Framework | Spring Boot |
| Security | Spring Security + JWT |
| Database | H2 (development) |
| Build Tool | Maven |
| Containerization | Docker |
src/main/java/com/charlie/auth
│
├── config # Security configuration & filter chain
├── controller # REST endpoints (login, register, user info)
├── domain # JPA entities (User, Role)
├── dto # Request and response models
├── repository # Database access using Spring Data JPA
├── security # JWT service, filter, and UserDetails implementation
└── service # Authentication and registration logic
- A user registers with email and password
- The password is hashed using BCrypt before being stored
- The user logs in with their credentials
- If valid, the server generates a signed JWT
- The client sends this token in future requests
- A custom JWT filter validates the token on every protected request
- Spring Security authorizes access based on the user’s role
- Used JWT-based stateless authentication to mirror how modern APIs and microservices handle security
- Implemented a custom JWT filter to better understand Spring Security’s filter chain
- Kept the architecture layered to reflect how production backend services are structured
- Used H2 for simplicity in development, with the option to swap to PostgreSQL later
JWT settings are stored in:
application.properties
Example:
jwt.secret=your-secret-key-here
jwt.expiration-minutes=60./mvnw spring-boot:runServer runs at:
http://localhost:8080
Build the image:
docker build -t jwt-auth-service .Run the container:
docker run -p 8080:8080 jwt-auth-serviceRegister
POST /api/auth/register
{
"email": "user@example.com",
"password": "password123"
}Login
POST /api/auth/login
{
"email": "user@example.com",
"password": "password123"
}Returns:
{
"token": "JWT_TOKEN_HERE"
}Get current user info
GET /api/auth/me
Header required:
Authorization: Bearer JWT_TOKEN_HERE
- Passwords are never stored in plain text
- JWTs are signed and validated using a secret key
- The service is fully stateless — no HTTP sessions are stored
- Role-based authorization is enforced by Spring Security
- How Spring Security handles authentication internally
- How JWTs are generated, signed, and verified
- The difference between authentication and authorization
- How stateless APIs scale better in distributed systems
- How security filters integrate into the request lifecycle