Skip to content

Commit 63924db

Browse files
authored
fix(auth): pass callbackPath through magic link sign-in flow (#1318)
## Summary - Fix `callbackPath` being dropped when users sign in via the magic link method. OAuth flows (Google, GitHub, WorkOS, etc.) correctly threaded `callbackPath` through `getSignInCallbackUrl(params)`, but `handleSendMagicLink` only sent the email address — ignoring `params` entirely. - The backend already fully supported `callbackUrl` end-to-end (API route zod schema, email builder, magic link URL generator, verify-magic-link page). The only gap was the frontend never sending the value. This two-file change closes that gap. ## Verification - [x] `pnpm typecheck` — passed - [x] `pnpm lint` (via pre-commit hook) — passed - [x] `pnpm format:check` (via pre-commit hook) — passed - [x] Manual browser test: navigated to `/users/sign_in?callbackPath=/organizations/new`, clicked "Continue with Email", confirmed flow reaches Turnstile with callbackPath still in the URL context (Turnstile challenge blocked full end-to-end automated test) ## Visual Changes N/A ## Reviewer Notes - The fix mirrors exactly how every OAuth provider in `useSignInFlow.ts` handles `callbackPath` — via `getSignInCallbackUrl(params)`. - Zero backend changes: the API route (`/api/auth/magic-link`), `sendMagicLinkEmail`, `getMagicLinkUrl`, and `verify-magic-link` page all already accepted and forwarded `callbackUrl`. Only the client-side call site was missing it. - `params` was added to the `useCallback` dependency array for `handleSendMagicLink` since it now reads from it.
2 parents 535d520 + aec7858 commit 63924db

2 files changed

Lines changed: 9 additions & 4 deletions

File tree

src/hooks/useSignInFlow.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,8 @@ export function useSignInFlow({
383383
}
384384

385385
try {
386-
const result = await sendMagicLink(email);
386+
const callbackUrl = getSignInCallbackUrl(params);
387+
const result = await sendMagicLink(email, callbackUrl);
387388
if (result.success) {
388389
saveHint({
389390
lastEmail: email,
@@ -401,7 +402,7 @@ export function useSignInFlow({
401402
});
402403
setError('Failed to send magic link. Please try again.');
403404
}
404-
}, [email, saveHint]);
405+
}, [email, params, saveHint]);
405406

406407
const handleTurnstileSuccess = useCallback(
407408
async (token: string) => {

src/lib/auth/send-magic-link.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ export type SendMagicLinkResult = { success: true } | { success: false; error: s
77
* Uses the Turnstile JWT cookie (from previous verification) for authentication.
88
*
99
* @param email - The email address to send the magic link to
10+
* @param callbackUrl - Optional post-sign-in redirect URL (e.g. from getSignInCallbackUrl)
1011
* @returns Promise resolving to success/error result
1112
*/
12-
export async function sendMagicLink(email: string): Promise<SendMagicLinkResult> {
13+
export async function sendMagicLink(
14+
email: string,
15+
callbackUrl?: string
16+
): Promise<SendMagicLinkResult> {
1317
try {
1418
const response = await fetch('/api/auth/magic-link', {
1519
method: 'POST',
1620
headers: { 'Content-Type': 'application/json' },
17-
body: JSON.stringify({ email }),
21+
body: JSON.stringify({ email, callbackUrl }),
1822
});
1923

2024
const result = await response.json();

0 commit comments

Comments
 (0)