|
| 1 | +# Sparkly Server – Users & Authentication |
| 2 | + |
| 3 | +This document is the slightly chaotic but fully functional guide to how Sparkly Server handles Users and Authentication. If Sparkly were a nightclub, this module would manage the guest list, check IDs, validate wristbands, and occasionally throw someone out when their token expires. |
| 4 | + |
| 5 | +## What a User Is in Sparkly |
| 6 | + |
| 7 | +A User is a simple creature. The domain model represents only what matters: |
| 8 | + |
| 9 | +• Id – primary key, a GUID with attitude. |
| 10 | + |
| 11 | +• Email – unique, required, cannot be nonsense. |
| 12 | + |
| 13 | +• UserName – the name that appears publicly. |
| 14 | + |
| 15 | +• PasswordHash – the encrypted version of whatever password the user typed. |
| 16 | + |
| 17 | +• Projects – navigation to the projects the user owns. |
| 18 | + |
| 19 | +>The entity carries no business logic. It is deliberately boring. That is good. |
| 20 | +
|
| 21 | +## Persistence: EF Core Mapping |
| 22 | + |
| 23 | +Users are mapped inside `AppDbContext` to a clean `users` table. The key details: |
| 24 | + |
| 25 | +• Email has a unique index. |
| 26 | + |
| 27 | +• All required fields are enforced. |
| 28 | + |
| 29 | +• Relationship between User → Projects is defined, so ownership is always clear. |
| 30 | + |
| 31 | +>EF Core takes care of the SQL, so you never have to think about migrations while half‑asleep. |
| 32 | +
|
| 33 | +## User Repository – Access Without Drama |
| 34 | + |
| 35 | +The repository provides controlled access to the database. It typically allows: |
| 36 | + |
| 37 | +• Finding users by Id. |
| 38 | + |
| 39 | +• Finding users by Email. |
| 40 | + |
| 41 | +• Creating new users. |
| 42 | + |
| 43 | +• Checking email uniqueness. |
| 44 | + |
| 45 | +>The repository keeps the rest of the app blissfully unaware of how the database works. |
| 46 | +
|
| 47 | +## Authentication: The Sparkly Way |
| 48 | + |
| 49 | +Sparkly uses JWTs. Nothing exotic. Just clean, industry‑standard authentication. |
| 50 | + |
| 51 | +The flow is straightforward: |
| 52 | + |
| 53 | +1. A user sends credentials. |
| 54 | +2. The service checks email and password. |
| 55 | +3. If valid, Sparkly issues two tokens: |
| 56 | + |
| 57 | + • Access Token – short lived, used for API calls. |
| 58 | + |
| 59 | + • Refresh Token – long lived, used to renew sessions. |
| 60 | +4. The refresh token is tied to the user, stored in the database, and rotated on use. |
| 61 | + |
| 62 | +>If you lose the refresh token, the session dies. That is life. |
| 63 | +
|
| 64 | +## Password Handling |
| 65 | + |
| 66 | +Passwords are hashed using a proper hashing algorithm (no Base64 nonsense). Only hashes are stored. The service handles hashing and verification. |
| 67 | + |
| 68 | +Your password never leaves the service in plain text. The system could not leak it even if it tried. |
| 69 | + |
| 70 | +## UserService – The Traffic Director |
| 71 | + |
| 72 | +This layer does the actual work: |
| 73 | + |
| 74 | +• Registering users. |
| 75 | + |
| 76 | +• Validating credentials. |
| 77 | + |
| 78 | +• Managing tokens. |
| 79 | + |
| 80 | +• Ensuring business rules are respected. |
| 81 | + |
| 82 | +>If something feels too smart for the controller or too specific for the repository, it belongs here. |
| 83 | +
|
| 84 | +## DTOs (Data Transfer Objects) |
| 85 | + |
| 86 | +DTOs protect the system from leaking internal structures into the API. |
| 87 | + |
| 88 | +Typical ones: |
| 89 | + |
| 90 | +• UserRegisterDto |
| 91 | + |
| 92 | +• UserLoginDto |
| 93 | + |
| 94 | +• UserDto for returning minimal identity information. |
| 95 | + |
| 96 | +>They shape the data for the outside world so the domain remains clean. |
| 97 | +
|
| 98 | +## UsersController – The Doorway |
| 99 | + |
| 100 | +Endpoints typically include: |
| 101 | + |
| 102 | +• POST /users/register – Create a new account. |
| 103 | + |
| 104 | +• POST /users/login – Authenticate and receive tokens. |
| 105 | + |
| 106 | +• POST /users/refresh – Renew access token. |
| 107 | + |
| 108 | +• GET /users/me – Return info about the current user. |
| 109 | + |
| 110 | +>Controllers stay thin. They pass data to services and return results without thinking too much. |
| 111 | +
|
| 112 | +## Authorization |
| 113 | + |
| 114 | +Once a user is authenticated, requests carry the Access Token in the Authorization header. |
| 115 | + |
| 116 | +Rules are simple: |
| 117 | + |
| 118 | +• No token → No entry. |
| 119 | + |
| 120 | +• Invalid token → No entry. |
| 121 | + |
| 122 | +• Expired token → Renew using refresh. |
| 123 | + |
| 124 | +>Most protected endpoints have the `[Authorize]` attribute to ensure that only logged‑in users can reach them. |
| 125 | +
|
| 126 | +## Error Handling |
| 127 | + |
| 128 | +Authentication failure cases include: |
| 129 | + |
| 130 | +• Wrong email or password. |
| 131 | + |
| 132 | +• Email already registered. |
| 133 | + |
| 134 | +• Expired or missing token. |
| 135 | + |
| 136 | +• Refresh token not found or invalid. |
| 137 | + |
| 138 | +>The API returns appropriate error responses. Clear, predictable, and not misleading. |
| 139 | +
|
| 140 | +## Refresh Token Lifecycle |
| 141 | + |
| 142 | +Refresh tokens in Sparkly are treated like long-lived session keys. They live in the database and have a clear lifecycle so they do not turn into immortal zombies. |
| 143 | + |
| 144 | +### Storage |
| 145 | + |
| 146 | +Each refresh token is typically associated with: |
| 147 | + |
| 148 | +• User Id – who owns it. |
| 149 | + |
| 150 | +• Token value – secure random string. |
| 151 | + |
| 152 | +• Expiration date – when it stops being valid. |
| 153 | + |
| 154 | +• Creation time – when it was issued. |
| 155 | + |
| 156 | +• Revocation data (optional) – when and why it was invalidated. |
| 157 | + |
| 158 | +>This allows you to answer questions like: "Is this token still valid?" and "Did we revoke it already?". |
| 159 | +
|
| 160 | +### Rotation on Use |
| 161 | + |
| 162 | +Sparkly should use **rotation** when a refresh token is used: |
| 163 | + |
| 164 | +1. Client sends the current refresh token. |
| 165 | +2. Server validates it: |
| 166 | + |
| 167 | + • belongs to an existing user, |
| 168 | + |
| 169 | + • not expired, |
| 170 | + |
| 171 | + • not revoked. |
| 172 | +3. If valid: |
| 173 | + • issue a new access token, |
| 174 | + • issue a brand new refresh token, |
| 175 | + • revoke (or mark as used) the old refresh token. |
| 176 | + |
| 177 | +>This rotation means that every refresh token is single-use. Once it is exchanged, it should not work again. This greatly limits the damage if one token gets stolen. |
| 178 | +
|
| 179 | +### Invalidation Rules |
| 180 | + |
| 181 | +A refresh token can be invalidated when: |
| 182 | + |
| 183 | +• User logs out. |
| 184 | + |
| 185 | +• User changes password. |
| 186 | + |
| 187 | +• Admin forces logout / security reset. |
| 188 | + |
| 189 | +• Token is used and rotated. |
| 190 | + |
| 191 | +>>Invalidation usually means either deleting the token row from the database or marking a `RevokedAt` / `IsRevoked` field. |
| 192 | +> |
| 193 | +>For extra security, on critical events (like password change) you can invalidate **all** refresh tokens for the user. |
| 194 | +
|
| 195 | +### Compromised Token Scenario |
| 196 | + |
| 197 | +If an attacker steals a refresh token, rotation rules help: |
| 198 | + |
| 199 | +• If the legitimate client uses the token first → attacker’s token becomes useless after rotation. |
| 200 | + |
| 201 | +• If the attacker uses it first → legitimate user’s refresh token stops working, which is a strong signal that something is wrong. |
| 202 | + |
| 203 | +You can then: |
| 204 | + |
| 205 | +• invalidate all tokens for that user, |
| 206 | + |
| 207 | +• force re-login, |
| 208 | + |
| 209 | +• optionally log suspicious activity. |
| 210 | + |
| 211 | +### Expiration Strategy |
| 212 | + |
| 213 | +Typical strategy: |
| 214 | + |
| 215 | +• Access token – short lifetime (minutes). |
| 216 | + |
| 217 | +• Refresh token – longer lifetime (days/weeks). |
| 218 | + |
| 219 | +>This gives a good balance between usability and security. Access tokens are cheap, short-lived, and stateless. Refresh tokens are stateful and more powerful, so they are carefully tracked. |
| 220 | +
|
| 221 | +## Summary |
| 222 | + |
| 223 | +Users and Authentication in Sparkly are built to be solid, understandable, and easy to maintain. The architecture enforces separation: |
| 224 | + |
| 225 | +• Domain defines what a User is. |
| 226 | + |
| 227 | +• Repository retrieves data. |
| 228 | + |
| 229 | +• Services execute business logic. |
| 230 | + |
| 231 | +• Controllers expose it cleanly. |
| 232 | + |
| 233 | +• JWTs handle authentication. |
| 234 | + |
| 235 | +>The result is a system where you always know where to look. No magic, just structure. |
0 commit comments