feat(auth): add login with JWT access and refresh tokens#282
Conversation
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR implements a complete JWT-based authentication system with HTTP-only cookie storage, session management, and password reset flows. It adds type contracts, validation DTOs, two Passport strategies for access/refresh tokens, core auth service methods with token signing and session persistence, module wiring, and controller integration. ChangesJWT Authentication with Cookie Sessions
Sequence Diagram(s)sequenceDiagram
participant Client
participant AuthController
participant JwtAccessStrategy
participant JwtRefreshStrategy
participant AuthService
participant Prisma
Client->>AuthController: POST /auth/login { email, password }
AuthController->>AuthService: login(dto, sessionMetadata)
AuthService->>Prisma: user.findFirst by email
AuthService->>AuthService: verify password
AuthService->>AuthService: signTokenPair()
AuthService->>Prisma: createSession with refresh hash
AuthService-->>AuthController: { accessToken, refreshToken, redirectTo }
AuthController->>AuthController: setAuthCookies(tokens)
AuthController-->>Client: Set-Cookie: accessToken, refreshToken
Client->>AuthController: GET /auth/refresh
AuthController->>JwtRefreshStrategy: guard validates refresh cookie
JwtRefreshStrategy->>Prisma: findFirst session by hash
JwtRefreshStrategy-->>AuthController: RefreshRequestUser
AuthController->>AuthService: refresh(refreshUser, sessionMetadata)
AuthService->>AuthService: signTokenPair()
AuthService->>Prisma: update session hash/expiry
AuthService-->>AuthController: { accessToken, refreshToken }
AuthController->>AuthController: setAuthCookies(tokens)
AuthController-->>Client: Set-Cookie: accessToken, refreshToken
Client->>AuthController: protected route
AuthController->>JwtAccessStrategy: guard validates access cookie
JwtAccessStrategy->>Prisma: user.findFirst by sub
JwtAccessStrategy-->>AuthController: AuthenticatedRequestUser
AuthController-->>Client: protected resource
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
apps/backend/src/domains/users/auth/strategies/jwt-refresh.strategy.ts (1)
16-18: 💤 Low valueConsider extracting shared type to a common location.
RequestWithCookiesis duplicated betweenjwt.strategy.tsandjwt-refresh.strategy.ts. Could be extracted toauth.types.tsfor DRY compliance.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/backend/src/domains/users/auth/strategies/jwt-refresh.strategy.ts` around lines 16 - 18, RequestWithCookies is duplicated in jwt.strategy and jwt-refresh.strategy; extract it into a shared auth.types module and import it from both strategies. Create an auth.types.ts that exports the RequestWithCookies type, remove the local duplicate declarations from jwt.strategy.ts and jwt-refresh.strategy.ts, and update their imports to use the new auth.types export so both strategies reference the single shared type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/backend/src/domains/users/auth/auth.controller.ts`:
- Around line 115-126: The logout endpoint currently returns a plain object from
authService.logout; wrap the response into the project's envelope shape before
returning. In the logout method (auth.controller.logout) call const result =
await this.authService.logout(refreshToken) as needed, then return an envelope
such as { success: true, data: result } (or { success: true, data: { loggedOut:
true } } if you want to be explicit); keep the existing
clearAuthCookies(response) call and HTTP status. Ensure any error paths also
return the envelope shape (success: false with message/code) if applicable.
- Around line 128-145: The refresh controller currently returns a raw object;
change the response to the required envelope format. In the refresh method
(auth.controller.refresh) after setAuthCookies(response, tokens) return an
envelope like { success: true, data: { refreshed: true } } (or include any
message/code as needed) instead of { refreshed: true }; ensure no other callers
rely on the old shape and keep authService.refresh and getSessionMetadata usage
unchanged.
- Around line 97-113: The login endpoint currently returns a raw object; change
it to return the required envelope shape. In the login method, after calling
this.authService.login(...) and this.setAuthCookies(...), return an envelope
object like { success: true, data: { redirectTo: result.redirectTo } }
(optionally include message/code if relevant) so the login controller (method:
login) conforms to the app-wide response format; keep the calls to
this.getSessionMetadata(request) and this.setAuthCookies(response, result)
unchanged.
- Around line 153-165: Update the controller methods forgotPassword and
resetPassword to return responses in the required envelope shape instead of
returning service results directly: call this.authService.forgotPassword(dto)
and this.authService.resetPassword(dto) as before, but wrap their successful
output into { success: true, data: <serviceResult>, message?: <optionalMessage>,
code?: <optionalCode> } (or use a shared helper like createEnvelope(result,
message) if available) so both endpoints always emit { success, data, message,
code } envelope objects; keep error handling unchanged (errors should still
propagate to the global exception filter which can emit { success: false,
message, code }).
In `@apps/backend/src/domains/users/auth/auth.types.ts`:
- Around line 21-22: Rename the boolean fields emailVerified and phoneVerified
to isEmailVerified and isPhoneVerified in the auth types (e.g., the
interface/type where emailVerified and phoneVerified are defined) to meet the
boolean-naming convention; update all references/usages (serializers, DB
mappings, DTOs, tests, and any code that reads/writes these properties) to the
new names and adjust any type imports/exports that reference the old symbols so
compilation and runtime mapping remain consistent.
---
Nitpick comments:
In `@apps/backend/src/domains/users/auth/strategies/jwt-refresh.strategy.ts`:
- Around line 16-18: RequestWithCookies is duplicated in jwt.strategy and
jwt-refresh.strategy; extract it into a shared auth.types module and import it
from both strategies. Create an auth.types.ts that exports the
RequestWithCookies type, remove the local duplicate declarations from
jwt.strategy.ts and jwt-refresh.strategy.ts, and update their imports to use the
new auth.types export so both strategies reference the single shared type.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0d18028f-628e-4880-890e-b8ba32a030ed
📒 Files selected for processing (11)
apps/backend/src/domains/users/auth/auth.constants.tsapps/backend/src/domains/users/auth/auth.controller.tsapps/backend/src/domains/users/auth/auth.module.tsapps/backend/src/domains/users/auth/auth.service.tsapps/backend/src/domains/users/auth/auth.types.tsapps/backend/src/domains/users/auth/dto/login.dto.tsapps/backend/src/domains/users/auth/dto/password-reset.dto.tsapps/backend/src/domains/users/auth/strategies/jwt-refresh.strategy.tsapps/backend/src/domains/users/auth/strategies/jwt.strategy.tsapps/backend/src/domains/users/auth/strategies/local.strategy.tsapps/backend/src/modules/auth/auth.module.ts
What does this PR do?
This PR implements B-05: Auth Login + JWT + Sessions.
It adds authenticated session handling for Twizrr users after registration. Login now validates user credentials, creates a session record, stores JWT access and refresh tokens in HttpOnly cookies, and returns frontend redirect information based on whether the user owns a store.
Added endpoints:
POST /auth/loginPOST /auth/logoutPOST /auth/refreshPOST /auth/forgot-passwordPOST /auth/reset-passwordSession handling:
Sessionrow.revokedAt.Cookie names:
twizrr_access_tokentwizrr_refresh_tokenType of change
How to test this
Checkout the branch:
Run Backend test:
cd apps/backend
pnpm run lint
npx tsc --noEmit
pnpm run build
Start the backend and test auth endpoints:
POST /auth/login
POST /auth/refresh
POST /auth/logout
POST /auth/forgot-password
POST /auth/reset-password
Expected result:
Login returns auth cookies, not tokens in the JSON response body.
Login response includes redirectTo.
Refresh works only with a valid, active, unexpired session.
Logout revokes the active session and clears cookies.
Forgot-password does not reveal whether an email exists.
Reset-password updates the password and revokes active se
Area affected
Pre-commit checklist
console.logleft in production code.envfiles committedanytypes addeddb pushScreenshots
Notes for reviewer