5.0 KiB
5.0 KiB
Authentication & Token Flow (iYHCT360)
This document describes in detail the Authentication and Token (Access Token / Refresh Token) processing flow based on the project's actual source code. This is the core security framework designed to be reusable (base) across other projects.
1. Technology Overview & Design Patterns
- JWT (JSON Web Token): Short-lived Access Token containing the user's basic Claims.
- Refresh Token Storage: Securely stored in the Database (saving only hashed strings to prevent database leak vulnerabilities).
- Refresh Token Rotation: Upon performing a token refresh, the old Refresh Token is revoked, and a completely new Refresh Token is issued (minimizing the risk of theft).
- Single Active Session: Each login will revoke all currently Active Refresh Tokens of that User to ensure there is only 1 active session at a time.
1.1. JWT Configuration (appsettings.json)
System default lifecycles:
- Access Token: Lives for 15 minutes.
- Refresh Token: Lives for 7 days.
2. Detailed Processing Flows
2.1. Login Flow
Endpoint: POST /api/auth/login
Processing Steps:
- Client sends a
LoginRequestcontaining:EmailandPassword. - The system searches for the User by Email (only
IsActiveusers). - Verifies the password (hashing verification via
IPasswordHasher). - The system retrieves the User's corresponding Roles from the database.
- Generates an Access Token containing information (
id,roles, etc.). - Generates a random Refresh Token string.
- Ensures Single Active Session: The system queries the db to find and mark all previous active Refresh Tokens of the user (
RevokedAt = nulland not Expired) as revoked (RevokedAt = DateTimeOffset.UtcNow). - Hashing the token: The random Refresh Token string (which is sent to the client only once) is hashed using an algorithm (e.g.,
TokenHasher.ComputeHash()) and ONLY this hash value is saved in the Database along with the IP + UserAgent. - Updates the user's
LastLoginAtand returns the information (Access Token, Refresh Token, Roles, UserType) to the Client.
2.2. Token Refresh Flow (Token Rotation)
Endpoint: POST /api/auth/refresh-token
Processing Steps:
- Client sends both the
AccessToken(which might be expired) and theRefreshToken. - The system looks up the Refresh Token in the Database (stored as the hash of the original Refresh Token string) => Verifies existence, check it's not revoked (
RevokedAt == null), and check it's not expired. - Decodes the
AccessTokenusing the Extract Claims function to get theuserId. TheuserIdretrieved from the token MUST match theUserIdowning the Refresh Token. - Checks if the User is still
IsActive. - Reloads the user's roles from the Database (if roles have changed while the old token was still valid, the refresh action will incorporate the new
rolesinto the next Access Token). - Issues a new
AccessTokenand a completely newRefreshToken. - Manually marks the current Refresh Token as revoked (
RevokedAt = DateTimeOffset.UtcNow). - Saves the hash value of the new RefreshToken into the DB with a 7-day expiration.
- Returns the data to the Client.
2.3. Logout Flow
Endpoint: POST /api/auth/logout
Processing Steps:
- Client sends the
RefreshTokento the system. - The system hashes the incoming token and finds the corresponding record in the DB.
- Marks that Token as revoked (
RevokedAt = DateTimeOffset.UtcNow). - (Optional: The Client deletes the AccessToken/RefreshToken stored locally on its device).
2.4. Password Reset (Forgot password & Reset)
- Forgot Password (
POST /api/auth/forgot-password):- Generates a Raw Token (a
Guid.NewGuid()string). - Hashes that Raw Token and saves it into the User's
SecurityStampfield. - Concatenates
${user.Id}:{rawToken}, then appliesBase64 Encodeand returns it (or sends it via Email) to act as the ResetToken.
- Generates a Raw Token (a
- Reset Password (
POST /api/auth/reset-password):Base64decodes the token above to extract theuserIdandrawToken.- Finds the User in the db, compares the hash of
rawTokenwith theSecurityStamp. - If valid, Hashes the
NewPasswordinto the DB. SetsSecurityStamp = null(can only be used to change the password once). - Security: Immediately revokes all active Refresh Tokens for this User to forcefully log them out across all devices.
3. Best Practices Summary Applied in the Backend
- Fully leverage the
TokenHasherconcept: Never store Refresh Tokens, OTP tokens, or Forgot password tokens in direct raw text. If the Database leaks, attackers still cannot use those tokens (similar to hashed passwords). - Always cross-check: Ensure the Refresh Token genuinely belongs to the
userIdpresent in the Access Token to prevent cross-token forgery. - Synchronization: When an Admin changes a User's Password/Roles or a User changes their own password (Reset/Change) -> The system must automatically revoke all Refresh Tokens to force a fresh log-in.