fix: magic link login#133
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR enhances the magic link authentication flow by adding a Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Email as Email Service
participant Browser as Frontend<br/>(Next.js)
participant Backend as Backend<br/>(Fastify)
User->>Backend: POST /auth/magiclink/request
Backend->>Backend: Generate verificationId, code
Backend->>Email: Send email with<br/>link + code
Email->>User: Email with magic link<br/>(?verificationId=...&token=...)
alt Auto-verify (token present)
User->>Browser: Click magic link
Browser->>Backend: GET /auth/callback/magiclink<br/>(verificationId, token)
Backend->>Backend: Verify credentials
Backend-->>Browser: Auth tokens
Browser->>Browser: Set cookies<br/>Redirect to callback URL
else Manual entry (no token)
User->>Browser: Visit callback URL<br/>(verificationId only)
Browser->>Browser: Render code-entry form
User->>Browser: Fill code & submit
Browser->>Backend: POST /auth/callback/magiclink<br/>(verificationId, code)
Backend->>Backend: Verify credentials
Backend-->>Browser: Auth tokens
Browser->>Browser: Set cookies<br/>Redirect to callback URL
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/docu/content/docs/architecture/authentication.mdx (1)
90-95:⚠️ Potential issue | 🟡 MinorDocument manual verification as
{ email, token }.
apps/fastify/src/routes/auth/magiclink/verify.tsrejects requests that omit bothverificationIdand**/*.mdx: Verify MDX content follows documentation standards.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/docu/content/docs/architecture/authentication.mdx` around lines 90 - 95, The docs' "Option A (manual)" step is misleading: the verify endpoint (apps/fastify/src/routes/auth/magiclink/verify.ts) requires either verificationId or email, so update the MDX to document manual verification payload as { email, token } (not just { token }) and show the correct POST to /auth/magiclink/verify with that body; ensure the example matches the verify.ts expectation and mention that verificationId may be used as an alternative.apps/next/app/auth/callback/magiclink/route.ts (1)
25-52:⚠️ Potential issue | 🟡 MinorSurface
INVALID_CODEin the fallback form.The POST path already redirects back with
message=INVALID_CODE, but this GET path never reads it andrenderCodeEntryForm()always renders a blank form. Users get no feedback after a bad submission.💡 Suggested fix
-function renderCodeEntryForm(verificationId: string, callbackURL: string): NextResponse { +function renderCodeEntryForm( + verificationId: string, + callbackURL: string, + message?: string, +): NextResponse { + const errorMessage = + message === 'INVALID_CODE' ? 'Enter a valid 6-digit code.' : undefined const html = `<!DOCTYPE html> <html lang="en"> ... <body> <h1>Enter your code</h1> <p>Enter the 6-digit code from your email to sign in.</p> <form method="POST" action="/auth/callback/magiclink"> <input type="hidden" name="verificationId" value="${verificationId.replace(/"/g, '"')}"/> <input type="hidden" name="callbackURL" value="${callbackURL.replace(/"/g, '"')}"/> <label for="token">Code</label> <input id="token" name="token" type="text" inputmode="numeric" pattern="\\d*" maxlength="6" autocomplete="one-time-code" placeholder="000000" required/> + ${errorMessage ? `<p class="error">${errorMessage}</p>` : ''} <button type="submit">Verify</button> </form> ... </html>`export async function GET(request: Request) { const { searchParams } = new URL(request.url) const verificationId = searchParams.get('verificationId') const token = searchParams.get('token') const rawCallback = searchParams.get('callbackURL') + const message = searchParams.get('message') const callbackURL = isSafeCallbackUrl(rawCallback, request.url) ... if (hasValidVerificationId && verificationId) - return renderCodeEntryForm(verificationId, callbackURL) + return renderCodeEntryForm(verificationId, callbackURL, message ?? undefined)Also applies to: 55-59, 92-93
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/app/auth/callback/magiclink/route.ts` around lines 25 - 52, The form never shows feedback for message=INVALID_CODE; update the GET handler to read the request query param "message" and pass it into renderCodeEntryForm as an optional errorMessage (or change renderCodeEntryForm signature to accept an errorMessage string), then inside renderCodeEntryForm render a visible error element (e.g., <p class="error">Invalid code — please try again</p>) when errorMessage === "INVALID_CODE" (ensure you still escape verificationId and callbackURL and place the error element near the token input so users see it); apply the same change to the other call sites that render this form (the other places referenced) so the INVALID_CODE message surfaces consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/next/app/auth/callback/magiclink/route.ts`:
- Around line 54-74: The GET handler currently performs a state-changing
magiclink exchange (calls client.auth.magiclink.verify, extracts tokens, sets
cookies via setAuthCookiesOnResponse and redirects) which must be removed: make
GET side-effect free by stopping any call to client.auth.magiclink.verify and
instead return a safe non-mutating response (e.g., a static confirmation page or
200 with instructions) and retain validation of verificationId, token and
callbackURL with isSafeCallbackUrl; then implement a POST handler (or an
explicit user action endpoint) that accepts verificationId and token from the
client, performs client.auth.magiclink.verify, calls extractTokens, sets auth
cookies with setAuthCookiesOnResponse and issues the redirect with
NextResponse.redirect, while preserving existing validation logic (uuidLike,
sixDigitCode) and error redirects (FAILED_VERIFY).
---
Outside diff comments:
In `@apps/docu/content/docs/architecture/authentication.mdx`:
- Around line 90-95: The docs' "Option A (manual)" step is misleading: the
verify endpoint (apps/fastify/src/routes/auth/magiclink/verify.ts) requires
either verificationId or email, so update the MDX to document manual
verification payload as { email, token } (not just { token }) and show the
correct POST to /auth/magiclink/verify with that body; ensure the example
matches the verify.ts expectation and mention that verificationId may be used as
an alternative.
In `@apps/next/app/auth/callback/magiclink/route.ts`:
- Around line 25-52: The form never shows feedback for message=INVALID_CODE;
update the GET handler to read the request query param "message" and pass it
into renderCodeEntryForm as an optional errorMessage (or change
renderCodeEntryForm signature to accept an errorMessage string), then inside
renderCodeEntryForm render a visible error element (e.g., <p
class="error">Invalid code — please try again</p>) when errorMessage ===
"INVALID_CODE" (ensure you still escape verificationId and callbackURL and place
the error element near the token input so users see it); apply the same change
to the other call sites that render this form (the other places referenced) so
the INVALID_CODE message surfaces consistently.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 40eb9cca-74e0-4789-a42d-8d1cae2e6ddf
📒 Files selected for processing (5)
apps/docu/content/docs/architecture/authentication.mdxapps/fastify/src/routes/auth/magiclink/request.test.tsapps/fastify/src/routes/auth/magiclink/request.tsapps/next/app/auth/callback/magiclink/route.tsapps/next/e2e/auth-helpers.ts
Summary by CodeRabbit
New Features
Documentation
Tests