diff --git a/packages/better-auth/src/cookies/cookies.test.ts b/packages/better-auth/src/cookies/cookies.test.ts index b419c88ce5..4481f61393 100644 --- a/packages/better-auth/src/cookies/cookies.test.ts +++ b/packages/better-auth/src/cookies/cookies.test.ts @@ -14,7 +14,6 @@ describe("cookies", async () => { { onResponse(context) { const setCookie = context.response.headers.get("set-cookie"); - console; expect(setCookie).toBeDefined(); expect(setCookie).toContain("Path=/"); expect(setCookie).toContain("HttpOnly"); diff --git a/packages/better-auth/src/cookies/index.ts b/packages/better-auth/src/cookies/index.ts index bd9b22bc4b..b2d6ff54dc 100644 --- a/packages/better-auth/src/cookies/index.ts +++ b/packages/better-auth/src/cookies/index.ts @@ -148,6 +148,14 @@ export async function setSessionCookie( dontRememberMe?: boolean, overrides?: Partial, ) { + const dontRememberMeCookie = await ctx.getSignedCookie( + ctx.context.authCookies.dontRememberToken.name, + ctx.context.secret, + ); + // if dontRememberMe is not set, use the cookie value + dontRememberMe = + dontRememberMe !== undefined ? dontRememberMe : !!dontRememberMeCookie; + const options = ctx.context.authCookies.sessionToken.options; const maxAge = dontRememberMe ? undefined @@ -192,7 +200,10 @@ export async function setSessionCookie( } } -export function deleteSessionCookie(ctx: GenericEndpointContext) { +export function deleteSessionCookie( + ctx: GenericEndpointContext, + skipDontRememberMe?: boolean, +) { ctx.setCookie(ctx.context.authCookies.sessionToken.name, "", { ...ctx.context.authCookies.sessionToken.options, maxAge: 0, @@ -201,10 +212,12 @@ export function deleteSessionCookie(ctx: GenericEndpointContext) { ...ctx.context.authCookies.sessionData.options, maxAge: 0, }); - ctx.setCookie(ctx.context.authCookies.dontRememberToken.name, "", { - ...ctx.context.authCookies.dontRememberToken.options, - maxAge: 0, - }); + if (!skipDontRememberMe) { + ctx.setCookie(ctx.context.authCookies.dontRememberToken.name, "", { + ...ctx.context.authCookies.dontRememberToken.options, + maxAge: 0, + }); + } } export function parseCookies(cookieHeader: string) { diff --git a/packages/better-auth/src/plugins/two-factor/index.ts b/packages/better-auth/src/plugins/two-factor/index.ts index 93162aa139..d3e52ff29f 100644 --- a/packages/better-auth/src/plugins/two-factor/index.ts +++ b/packages/better-auth/src/plugins/two-factor/index.ts @@ -291,7 +291,7 @@ export const twoFactor = (options?: TwoFactorOptions) => { /** * remove the session cookie. It's set by the sign in credential */ - deleteSessionCookie(ctx); + deleteSessionCookie(ctx, true); await ctx.context.internalAdapter.deleteSession(data.session.token); const twoFactorCookie = ctx.context.createAuthCookie( TWO_FACTOR_COOKIE_NAME, diff --git a/packages/better-auth/src/plugins/two-factor/otp/index.ts b/packages/better-auth/src/plugins/two-factor/otp/index.ts index 9811e0b244..bfa5cfa30b 100644 --- a/packages/better-auth/src/plugins/two-factor/otp/index.ts +++ b/packages/better-auth/src/plugins/two-factor/otp/index.ts @@ -220,6 +220,7 @@ export const otp2fa = (options?: OTPOptions) => { await ctx.context.internalAdapter.deleteSession( ctx.context.session.session.token, ); + await setSessionCookie(ctx, { session: newSession, user: updatedUser, diff --git a/packages/better-auth/src/plugins/two-factor/two-factor.test.ts b/packages/better-auth/src/plugins/two-factor/two-factor.test.ts index f715f8daa4..5270f3fb2f 100644 --- a/packages/better-auth/src/plugins/two-factor/two-factor.test.ts +++ b/packages/better-auth/src/plugins/two-factor/two-factor.test.ts @@ -113,19 +113,27 @@ describe("two factor", async () => { const res = await client.signIn.email({ email: testUser.email, password: testUser.password, + rememberMe: false, fetchOptions: { - onSuccess(context) { + onResponse(context) { const parsed = parseSetCookieHeader( context.response.headers.get("Set-Cookie") || "", ); expect(parsed.get("better-auth.session_token")?.value).toBe(""); expect(parsed.get("better-auth.two_factor")?.value).toBeDefined(); + expect(parsed.get("better-auth.dont_remember")?.value).toBeDefined(); headers.append( "cookie", `better-auth.two_factor=${ parsed.get("better-auth.two_factor")?.value }`, ); + headers.append( + "cookie", + `better-auth.dont_remember=${ + parsed.get("better-auth.dont_remember")?.value + }`, + ); }, }, }); @@ -140,15 +148,18 @@ describe("two factor", async () => { code: OTP, fetchOptions: { headers, - onSuccess(context) { + onResponse(context) { const parsed = parseSetCookieHeader( context.response.headers.get("Set-Cookie") || "", ); expect(parsed.get("better-auth.session_token")?.value).toBeDefined(); + // max age should be undefined because we are not using remember me + expect( + parsed.get("better-auth.session_token")?.["max-age"], + ).not.toBeDefined(); }, }, }); - console.log({ verifyRes }); expect(verifyRes.data?.token).toBeDefined(); }); diff --git a/packages/better-auth/src/plugins/two-factor/verify-middleware.ts b/packages/better-auth/src/plugins/two-factor/verify-middleware.ts index 038cebb5ba..8747be88d6 100644 --- a/packages/better-auth/src/plugins/two-factor/verify-middleware.ts +++ b/packages/better-auth/src/plugins/two-factor/verify-middleware.ts @@ -40,9 +40,14 @@ export const verifyTwoFactorMiddleware = createAuthMiddleware( message: "invalid two factor cookie", }); } + const dontRememberMe = await ctx.getSignedCookie( + ctx.context.authCookies.dontRememberToken.name, + ctx.context.secret, + ); const session = await ctx.context.internalAdapter.createSession( userId, ctx.request, + !!dontRememberMe, ); if (!session) { throw new APIError("INTERNAL_SERVER_ERROR", { @@ -70,13 +75,20 @@ export const verifyTwoFactorMiddleware = createAuthMiddleware( ctx.context.secret, `${user.id}!${session.token}`, ); - await ctx.setSignedCookie( trustDeviceCookie.name, `${token}!${session.token}`, ctx.context.secret, trustDeviceCookie.attributes, ); + // delete the dont remember me cookie + ctx.setCookie(ctx.context.authCookies.dontRememberToken.name, "", { + maxAge: 0, + }); + // delete the two factor cookie + ctx.setCookie(cookieName.name, "", { + maxAge: 0, + }); } return ctx.json({ token: session.token,