mirror of
https://github.com/better-auth/better-auth.git
synced 2026-07-30 06:04:15 -05:00
fix(two-factor): should respect remember me value when a user logins in with 2fa (#1566)
* fix(two-factor): respect remember me value when using 2fa login * fix(two-factor): clean up temporary cookies
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -148,6 +148,14 @@ export async function setSessionCookie(
|
||||
dontRememberMe?: boolean,
|
||||
overrides?: Partial<CookieOptions>,
|
||||
) {
|
||||
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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user