From b4b7bd8298d7ff7508b0d13eb0a0553d65515113 Mon Sep 17 00:00:00 2001 From: Tom Ballinger Date: Thu, 19 Dec 2024 17:43:49 -0800 Subject: [PATCH 1/3] Rename signin code to cvxAuthCode --- src/nextjs/server/request.ts | 4 ++-- src/react/client.tsx | 12 +++++++----- src/server/implementation/index.ts | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/nextjs/server/request.ts b/src/nextjs/server/request.ts index 548c953..d96404c 100644 --- a/src/nextjs/server/request.ts +++ b/src/nextjs/server/request.ts @@ -26,7 +26,7 @@ export async function handleAuthenticationInRequest( const refreshTokens = await getRefreshedTokens(verbose); // Handle code exchange for OAuth and magic links via server-side redirect - const code = requestUrl.searchParams.get("code"); + const code = requestUrl.searchParams.get("cvxAuthCode"); if ( code && request.method === "GET" && @@ -35,7 +35,7 @@ export async function handleAuthenticationInRequest( logVerbose(`Handling code exchange for OAuth or magic link`, verbose); const verifier = (await getRequestCookies()).verifier ?? undefined; const redirectUrl = new URL(requestUrl); - redirectUrl.searchParams.delete("code"); + redirectUrl.searchParams.delete("cvxAuthCode"); try { const result = await fetchAction( "auth:signIn" as unknown as SignInAction, diff --git a/src/react/client.tsx b/src/react/client.tsx index 1e4b60c..fb7b58a 100644 --- a/src/react/client.tsx +++ b/src/react/client.tsx @@ -166,12 +166,14 @@ export function AuthProvider({ const verifyCodeAndSetToken = useCallback( async ( - args: { code: string; verifier?: string } | { refreshToken: string }, + args: + | { cvxAuthCode: string; verifier?: string } + | { refreshToken: string }, ) => { const { tokens } = await client.unauthenticatedCall( "auth:signIn" as unknown as SignInAction, - "code" in args - ? { params: { code: args.code }, verifier: args.verifier } + "cvxAuthCode" in args + ? { params: { code: args.cvxAuthCode }, verifier: args.verifier } : args, ); logVerbose(`retrieved tokens, is null: ${tokens === null}`); @@ -322,7 +324,7 @@ export function AuthProvider({ } const code = typeof window?.location !== "undefined" - ? new URLSearchParams(window.location.search).get("code") + ? new URLSearchParams(window.location.search).get("cvxAuthCode") : null; // code from URL is only consumed initially, // ref avoids racing in Strict mode @@ -330,7 +332,7 @@ export function AuthProvider({ if (code && !signingInWithCodeFromURL.current) { signingInWithCodeFromURL.current = true; const url = new URL(window.location.href); - url.searchParams.delete("code"); + url.searchParams.delete("cvxAuthCode"); void (async () => { await replaceURL(url.pathname + url.search + url.hash); await signIn(undefined, { code }); diff --git a/src/server/implementation/index.ts b/src/server/implementation/index.ts index 20a2857..a2dd78c 100644 --- a/src/server/implementation/index.ts +++ b/src/server/implementation/index.ts @@ -341,7 +341,7 @@ export function convexAuth(config_: ConvexAuthConfig) { headers: { Location: setURLSearchParam( destinationUrl, - "code", + "cvxAuthCode", verificationCode, ), "Cache-Control": "must-revalidate", From 813c3b08e70047ee95214b197681450c3dd27d32 Mon Sep 17 00:00:00 2001 From: Tom Ballinger Date: Fri, 20 Dec 2024 15:08:22 -0800 Subject: [PATCH 2/3] more --- src/react/client.tsx | 13 ++++++++----- .../implementation/mutations/verifyCodeAndSignIn.ts | 2 +- src/server/implementation/signIn.ts | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/react/client.tsx b/src/react/client.tsx index fb7b58a..a17700e 100644 --- a/src/react/client.tsx +++ b/src/react/client.tsx @@ -173,7 +173,10 @@ export function AuthProvider({ const { tokens } = await client.unauthenticatedCall( "auth:signIn" as unknown as SignInAction, "cvxAuthCode" in args - ? { params: { code: args.cvxAuthCode }, verifier: args.verifier } + ? { + params: { cvxAuthCode: args.cvxAuthCode }, + verifier: args.verifier, + } : args, ); logVerbose(`retrieved tokens, is null: ${tokens === null}`); @@ -322,20 +325,20 @@ export function AuthProvider({ return; } - const code = + const cvxAuthCode = typeof window?.location !== "undefined" ? new URLSearchParams(window.location.search).get("cvxAuthCode") : null; // code from URL is only consumed initially, // ref avoids racing in Strict mode - if (signingInWithCodeFromURL.current || code) { - if (code && !signingInWithCodeFromURL.current) { + if (signingInWithCodeFromURL.current || cvxAuthCode) { + if (cvxAuthCode && !signingInWithCodeFromURL.current) { signingInWithCodeFromURL.current = true; const url = new URL(window.location.href); url.searchParams.delete("cvxAuthCode"); void (async () => { await replaceURL(url.pathname + url.search + url.hash); - await signIn(undefined, { code }); + await signIn(undefined, { cvxAuthCode }); signingInWithCodeFromURL.current = false; })(); } diff --git a/src/server/implementation/mutations/verifyCodeAndSignIn.ts b/src/server/implementation/mutations/verifyCodeAndSignIn.ts index 03f1af8..16ce726 100644 --- a/src/server/implementation/mutations/verifyCodeAndSignIn.ts +++ b/src/server/implementation/mutations/verifyCodeAndSignIn.ts @@ -116,7 +116,7 @@ async function verifyCodeOnly( sessionId: GenericId<"authSessions"> | null, ) { const { params, verifier } = args; - const codeHash = await sha256(params.code); + const codeHash = await sha256(params.cvxAuthCode); const verificationCode = await ctx.db .query("authVerificationCodes") .withIndex("code", (q) => q.eq("code", codeHash)) diff --git a/src/server/implementation/signIn.ts b/src/server/implementation/signIn.ts index 458e068..66aade0 100644 --- a/src/server/implementation/signIn.ts +++ b/src/server/implementation/signIn.ts @@ -57,7 +57,7 @@ export async function signInImpl( }))!; return { kind: "refreshTokens", signedIn: { tokens } }; } - if (provider === null && args.params?.code !== undefined) { + if (provider === null && args.params?.cvxAuthCode !== undefined) { const result = await callVerifyCodeAndSignIn(ctx, { params: args.params, verifier: args.verifier, @@ -72,7 +72,7 @@ export async function signInImpl( if (provider === null) { throw new Error( - "Cannot sign in: Missing `provider`, `params.code` or `refreshToken`", + "Cannot sign in: Missing `provider`, `params.cvxAuthCode` or `refreshToken`", ); } if (provider.type === "email" || provider.type === "phone") { From ae6dfd8bd29d2943b768d6d18a2d8bd065f83694 Mon Sep 17 00:00:00 2001 From: Tom Ballinger Date: Fri, 20 Dec 2024 15:44:00 -0800 Subject: [PATCH 3/3] a few more --- src/nextjs/server/proxy.ts | 2 +- src/nextjs/server/request.ts | 6 +++--- src/server/implementation/signIn.ts | 3 ++- src/server/implementation/types.ts | 1 + 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/nextjs/server/proxy.ts b/src/nextjs/server/proxy.ts index c664ad3..dfa63c8 100644 --- a/src/nextjs/server/proxy.ts +++ b/src/nextjs/server/proxy.ts @@ -64,7 +64,7 @@ export async function proxyAuthActionToConvex( // Do not require auth when refreshing tokens or validating a code since they // are steps in the auth flow. const fetchActionAuthOptions = - args.refreshToken !== undefined || args.params?.code !== undefined + args.refreshToken !== undefined || args.params?.cvxAuthCode !== undefined ? {} : { token }; try { diff --git a/src/nextjs/server/request.ts b/src/nextjs/server/request.ts index d96404c..043f24a 100644 --- a/src/nextjs/server/request.ts +++ b/src/nextjs/server/request.ts @@ -26,9 +26,9 @@ export async function handleAuthenticationInRequest( const refreshTokens = await getRefreshedTokens(verbose); // Handle code exchange for OAuth and magic links via server-side redirect - const code = requestUrl.searchParams.get("cvxAuthCode"); + const cvxAuthCode = requestUrl.searchParams.get("cvxAuthCode"); if ( - code && + cvxAuthCode && request.method === "GET" && request.headers.get("accept")?.includes("text/html") ) { @@ -39,7 +39,7 @@ export async function handleAuthenticationInRequest( try { const result = await fetchAction( "auth:signIn" as unknown as SignInAction, - { params: { code }, verifier }, + { params: { cvxAuthCode }, verifier }, ); if (result.tokens === undefined) { throw new Error("Invalid `signIn` action result for code exchange"); diff --git a/src/server/implementation/signIn.ts b/src/server/implementation/signIn.ts index 66aade0..3dd4b14 100644 --- a/src/server/implementation/signIn.ts +++ b/src/server/implementation/signIn.ts @@ -105,7 +105,8 @@ async function handleEmailAndPhoneProvider( | { kind: "started"; started: true } | { kind: "signedIn"; signedIn: SessionInfoWithTokens } > { - if (args.params?.code !== undefined) { + // TODO this this flow + if (args.params?.cvxAuthCode !== undefined) { const result = await callVerifyCodeAndSignIn(ctx, { params: args.params, provider: provider.id, diff --git a/src/server/implementation/types.ts b/src/server/implementation/types.ts index f637204..40d3617 100644 --- a/src/server/implementation/types.ts +++ b/src/server/implementation/types.ts @@ -102,6 +102,7 @@ export const authTables = { * - OTP tokens * - magic link tokens * - OAuth codes + * Let's call all of these "cvxAuthCodes" to distinguish them from oauth code= param. */ authVerificationCodes: defineTable({ accountId: v.id("authAccounts"),