You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This document provides a focused deep dive into how **Authentication & Identity Management** is handled in the SpringQueuePro system. It will touch on how user identity is represented and persisted, how authentication is performed in a **stateless manner using JWTs**, and how session trust is maintained through **access tokens**, **refresh tokens**, and **Redis-backed refresh token rotation**.
5
+
This document provides a focused deep dive into how **Authentication & Identity Management** is implemented in the SpringQueuePro system. It explains how user identity is represented and persisted, how authentication is performed using **stateless JWT access tokens**, and how session trust is maintained through **Redis-backed refresh token persistence and rotation**.
6
6
7
-
- The goal of this section is to explain who a `User` is, how they prove their identity to the system, and how that trust is safely maintained over time, even in a distributed, horizontally scalable environment. (*It will also touch on the **deliberate architectural choices made to mimic real-world system design practices***).
7
+
The goal of this section is to clearly articulate:
8
+
- Who a `User` is in the context of SpringQueuePro
9
+
- How users prove their identity to the system
10
+
- How that trust is safely maintained over time in a distributed, horizontally scalable environment
8
11
9
-
**NOTE**: This document will **not** cover authorization concerns relating to role-based access control (RBAC), endpoint protection, nor method-level security annotations. (Those topics are addressed separately in the Security Configuration & RBAC "deep dive" documentation).
12
+
Special emphasis is placed on the **deliberate architectural decisions made to mirror real-world production systems**, rather than relying on simplified or purely academic authentication patterns.
13
+
14
+
> **NOTE**: This document focuses strictly on authentication and identity management.
15
+
> Authorization concerns such as RBAC, endpoint protection rules, and method-level security annotations are covered separately in the *Security Configuration & RBAC* deep dive.
10
16
11
17
---
12
18
@@ -16,129 +22,176 @@ This document provides a focused deep dive into how **Authentication & Identity
-[Steps Taken to Mimic Production Quality](#steps-taken-to-mimic-production-quality)
18
24
25
+
---
26
+
19
27
## Why a `User` Exists in My Task/Job Queue System
20
28
21
-
SpringQueuePro is a distributed task/job processing engine, and in its most minimal form (*see SpringQueue*) can operate without any notion of `User`(s) at all. (*That is, tasks could be submitted and processed globally*). However, SpringQueuePro is intentionally designed to resemble real-world task queue services, where a queue is **not a single global resource but a multi-tenant platform consumed by multiple independent clients**.
29
+
At its core, SpringQueuePro is a distributed task/job processing engine. In its most minimal form (as demonstrated in *SpringQueue*), such a system can operate without any notion of `User`s at all — tasks could be submitted and processed globally without ownership or isolation.
30
+
31
+
SpringQueuePro intentionally moves beyond this model to resemble **real-world queue platforms**, where a queue is not a single global resource but a **multi-tenant service consumed by multiple independent clients**.
22
32
23
-
Having the concept of a `User` allows the system to model ownership, isolation, and accountability in the realm of task execution. **Each authenticated user represents a distinct consumer of the queue service**, with their own logical task-processing domain. Tasks are created on behalf of a user, persisted with ownership metadata, and later queried, managed, and observed within the same user boundary.
33
+
Introducing the concept of a `User` enables the system to model:
34
+
- Ownership
35
+
- Isolation
36
+
- Accountability
37
+
38
+
Each authenticated user represents a **distinct consumer of the queue service**, operating within their own logical boundary. Tasks are created on behalf of a user, persisted with ownership metadata, and later queried, managed, and observed within that same boundary.
24
39
25
40
### This guarantees:
26
41
1. Tasks are scoped to an owning user, preventing accidental or unauthorized cross-visibility.
27
-
2. The system can safely support multiple concurrent users submitting and inspecting tasks simultaneously.
28
-
3. The queue behaves like a shared infrastructure service rather than a single-purpose job runner.
42
+
2. The system can safely support multiple concurrent users submitting and inspecting tasks.
43
+
3. The queue behaves like shared infrastructure rather than a single-purpose job runner.
44
+
45
+
Importantly, **user identity is orthogonal to task execution mechanics**. Workers, retries, locking, and persistence behave identically regardless of task ownership. Identity exists to define *who may submit, view, and manage tasks*, not *how tasks are processed*.
29
46
30
-
While SpringQueuePro is not a hosted production service (*for commercial use*), this multi-user model mirrors how real-world systems (such as Celery-backed platforms, managed queues, or internal job orchestration services) separate concerns between infrastructure and clients. The queue engine itself remains generic and reusable, while users provide the contextual boundary that makes the system realistic, secure, and extensible.
47
+
This separation keeps the core queue engine clean while allowing SpringQueuePro to function as a realistic, secure, multi-tenant system rather than a single-user demonstration.
31
48
32
-
The introduction of the `User` entity is orthogonal to task execution mechanics: workers, retries, locking, and persistence behave identically regardless of who owns a task. User identity exists to define who may submit, view, and manage tasks, not how tasks are processed. **This separation keeps the core queue engine clean while enabling SpringQueuePro to function as a true multi-tenant service rather than a single-user demonstration**.
49
+
---
33
50
34
51
## Authentication Model
35
52
36
-
SpringQueuePro uses a **dual-token authentication model** inspired by OAuth-style systems:
37
-
-**Access Tokens**
38
-
- Short-lived JWTs
39
-
- Used to authenticate API requests
40
-
- Never stored server-side
41
-
- Expire quickly to reduce "blast radius" if compromised
42
-
-**Refresh Tokens**
43
-
- Longer-lived JWTs
44
-
- Stored server-side in Redis
45
-
- Used only to obtain new access tokens
46
-
- Rotated on every refresh to prevent replay attacks
53
+
SpringQueuePro uses a **hybrid authentication model** inspired by OAuth-style systems, combining stateless and stateful components:
47
54
48
-
This separation allows the system to **balance security and usability in a way that mirrors real production systems**.
55
+
### Access Tokens
56
+
- Short-lived JWTs
57
+
- Used to authenticate API requests
58
+
- Never stored server-side
59
+
- Cryptographically validated on every request
60
+
- Explicitly typed (`type=access`) to prevent misuse
61
+
62
+
### Refresh Tokens
63
+
- Longer-lived JWTs
64
+
-**Persisted server-side in Redis**
65
+
- Used only to obtain new access tokens
66
+
- Rotated on every refresh
67
+
- Explicitly revocable (logout, expiry, rotation)
68
+
69
+
This separation allows the system to balance **scalability, security, and usability**, mirroring how production-grade APIs and cloud platforms handle authentication.
70
+
71
+
---
49
72
50
73
## Relevant Project Files
51
-
`security/`:
52
-
-`JwtAuthenticationFilter`
53
74
54
-
-**Enforces stateless authentication** by validating access tokens on every request
55
-
56
-
- Establishes the authenticated user in Spring Security's `SecurityContext`.
75
+
### `security/`
76
+
77
+
#### `JwtAuthenticationFilter`
78
+
- Enforces stateless authentication by validating access tokens on every protected request.
79
+
- Extracts identity from JWTs and populates Spring Security’s `SecurityContext`.
80
+
- Explicitly rejects refresh tokens at the filter layer to prevent misuse as API credentials.
81
+
- Ensures only short-lived access tokens may authenticate API requests.
- Explicitly distinguishes expired tokens from malformed or tampered tokens.
87
+
88
+
#### `CustomUserDetailsService`
89
+
- Bridges persisted user identity (`UserEntity`) into Spring Security’s authentication model.
90
+
- Loads users from PostgreSQL and resolves roles/authorities dynamically at request time.
91
+
- Allows authorization decisions to remain data-driven even with stateless JWTs.
57
92
58
-
- Explicitly rejects refresh tokens at the filter layer to prevent misuse as API credentials.
93
+
#### `dto/*`
94
+
- Simple request/response DTOs used by authentication endpoints for clarity and boundary enforcement.
95
+
- e.g. `LoginRequest`, `RegisterRequest`, `RefreshRequest`, `AuthResponse`
59
96
60
-
- Ensures that *only* short-lived tokens (access tokens) can authenticate requests.
97
+
---
61
98
62
-
-`JwtUtil`
63
-
-**Centralizes JWT creation and validation logic**, ensuring consistent token structure, cryptographic verification, expiration enforcement, and explicit token typing across the system.
99
+
### `controller/auth/AuthenticationController`
64
100
65
-
-`RefreshTokenService`
66
-
-**Provides Redis-backed storage** for refresh tokens, enabling rotation, revocation, and replay protection at the authentication flow level.
101
+
- Defines the authentication lifecycle endpoints:
102
+
-`POST /auth/register`
103
+
-`POST /auth/login`
104
+
-`POST /auth/refresh`
105
+
-`POST /auth/logout`
106
+
-`GET /auth/refresh-status`
107
+
- Orchestrates token issuance, rotation, and revocation.
108
+
- Intentionally isolated from task-related controllers to preserve separation of concerns.
67
109
68
-
-`CustomUserDetailsService`
69
-
-**Bridges persisted user identity (UserEntity) into Spring Security’s authentication model**, allowing JWT-authenticated requests to resolve a fully populated security principal.
110
+
---
70
111
71
-
-`dto/*`
72
-
- Just a collection of data transfer objects for readability, for example:<br>
73
-
`public record LoginRequest(String email, String password) { }`
112
+
### `redis/RedisTokenStore`
74
113
75
-
`controller/auth/AuthenticationController`
76
-
-**Defines the authentication lifecycle endpoints** (register, login, refresh, logout) and orchestrates token issuance, rotation, and revocation.
114
+
- Acts as the **source of truth for refresh token lifecycle**.
115
+
- Persists issued refresh tokens with TTL.
116
+
- Resolves refresh tokens to owning users.
117
+
- Enables:
118
+
- Token rotation
119
+
- Explicit logout
120
+
- Session invalidation
121
+
- Replay protection
122
+
- Cluster-wide session coordination
77
123
78
-
- This controller is intentionally separate from the task-related controllers and APIs (clean separation of concerns).
124
+
> **NOTE**: Earlier iterations of the project included a `RefreshTokenService`.
125
+
> The current architecture standardizes refresh token persistence exclusively through `RedisTokenStore`, which supersedes and effectively deprecates that older abstraction.
79
126
80
-
`redis/RedisTokenStore`
81
-
-**Provides Redis-backed persistence** for issued refresh tokens, enabling rotation, revocation, and replay prevention across the cluster.
127
+
---
82
128
83
-
`domain/entity/UserEntity`
84
-
-`UserEntity` is the persistent user identity role metadata. It represents a user's account information—which, for the sake of this project, is just an email and password hash.
129
+
### `domain/entity/UserEntity`
85
130
86
-
- PostgreSQL remains the system of record for identity, independent of authentication tokens or session state. (*This data is stored in the database and doesn't depend on either tokens or if the user is currently logged in*).
131
+
- Persistent representation of a user account.
132
+
- Stores:
133
+
- Email (primary key)
134
+
- BCrypt-hashed password
135
+
- Role metadata
136
+
- PostgreSQL serves as the **system of record for identity**, independent of session state or token lifetime.
137
+
138
+
---
87
139
88
140
## Steps Taken to Mimic Production Quality
89
141
90
-
I like to consider my SpringQueuePro project production-grade (or at the very least production-adjacent) because I designed the system around **operational realities**, and so this section here is dedicated to the design choices—relating to SQP's authentication system—that reflect this decision.
142
+
SpringQueuePro’s authentication system was designed around **operational realities**, not just theoretical correctness. The following characteristics reflect that intent:
91
143
92
-
Here are some key characteristics that stand out about SQP's authentication setup:
144
+
---
93
145
94
146
### 1. Stateless Runtime Authentication
95
147
96
-
Every request is authenticated independently using an access token. There are:
148
+
Every protected request is authenticated independently using an access token.
97
149
98
150
- No HTTP sessions
99
151
- No server-side authentication state
100
-
- No reliance on sticky sessions
152
+
- No sticky sessions
101
153
102
-
This allows the system to scale horizontally and survive restarts without breaking authentication.
154
+
This allows the system to scale horizontally and tolerate restarts without breaking authentication.
103
155
104
156
---
105
157
106
-
### 2. Short-Lived Access Tokens for Safety
158
+
### 2. Short-Lived Access Tokens
107
159
108
-
Access tokens are intentionally short-lived. If an access token is compromised, its usefulness is limited in time, reducing the impact of credential leakage.
160
+
Access tokens are intentionally short-lived to reduce the blast radius of credential leakage.
109
161
110
-
This reflects real-world security practices used in OAuth2, cloud APIs, and large-scale distributed systems.
162
+
This mirrors best practices used in OAuth2, cloud APIs, and large-scale distributed systems.
111
163
112
164
---
113
165
114
166
### 3. Refresh Tokens for Session Continuity
115
167
116
-
Rather than extending access token lifetimes indefinitely, SpringQueuePro uses refresh tokens to maintain session continuity. This allows:
168
+
Session continuity is maintained via refresh tokens rather than long-lived access tokens.
169
+
170
+
This enables:
117
171
- Frequent access token rotation
118
-
- Reduced exposure window
172
+
- Reduced exposure windows
119
173
- Better control over long-lived sessions
120
174
121
-
This mirrors how real systems balance usability with security.
122
-
123
175
---
124
176
125
-
### 4. Server-Side Refresh Token Storage (Redis)
177
+
### 4. Server-Side Refresh Token Tracking (Redis)
126
178
127
-
Although JWTs are stateless, refresh tokens are **intentionally tracked server-side**. This enables capabilities that purely stateless JWT systems cannot provide:
179
+
Although access tokens are stateless, refresh tokens are **intentionally tracked server-side**.
128
180
181
+
This enables capabilities that purely stateless JWT systems cannot provide:
129
182
- Explicit logout
130
183
- Forced session invalidation
131
184
- Replay attack prevention
132
-
-Cluster-wide session control
185
+
-Concurrency-safe rotation
133
186
134
-
Redis serves as a lightweight, fast coordination layer that supports these guarantees without reintroducing heavyweight session management.
187
+
Redis serves as a lightweightcoordination layer without reintroducing heavyweight session management.
135
188
136
189
---
137
190
138
191
### 5. Clear Separation of Concerns
139
192
140
-
Authentication logic is cleanly separated into:
141
-
- Identity persistence (`UserEntity`)
193
+
Authentication responsibilities are cleanly separated into:
This makes the system both realistic and extensible, without compromising clarity or correctness.
226
+
227
+
---
228
+
229
+
## SUMMARY
230
+
231
+
SpringQueuePro uses short-lived JWT access tokens for stateless authentication and Redis-backed refresh tokens for server-side session control. Access tokens cryptographically assert identity and are validated per request, while refresh tokens are persisted, rotated, and revoked centrally. Spring Security enforces endpoint and method-level authorization, resolving authenticated users and roles dynamically via a PostgreSQL-backed `UserDetailsService`. This hybrid design balances scalability, security, and revocability while keeping authorization decisions consistent and extensible.
0 commit comments