mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-06 12:27:44 +00:00
fix: refersh cookie cache properly when it's expired (#909)
This commit is contained in:
@@ -42,6 +42,22 @@ export const auth = betterAuth({
|
|||||||
dialect,
|
dialect,
|
||||||
type: process.env.USE_MYSQL ? "mysql" : "sqlite",
|
type: process.env.USE_MYSQL ? "mysql" : "sqlite",
|
||||||
},
|
},
|
||||||
|
databaseHooks: {
|
||||||
|
user: {
|
||||||
|
update: {
|
||||||
|
async before(user) {
|
||||||
|
if (user.emailVerified) {
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
...user,
|
||||||
|
emailVerifiedAt: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
emailVerification: {
|
emailVerification: {
|
||||||
async sendVerificationEmail({ user, url }) {
|
async sendVerificationEmail({ user, url }) {
|
||||||
const res = await resend.emails.send({
|
const res = await resend.emails.send({
|
||||||
|
|||||||
@@ -435,7 +435,7 @@ describe("cookie cache", async () => {
|
|||||||
};
|
};
|
||||||
const adapter = memoryAdapter(database);
|
const adapter = memoryAdapter(database);
|
||||||
|
|
||||||
const { client, testUser, auth } = await getTestInstance({
|
const { client, testUser, auth, cookieSetter } = await getTestInstance({
|
||||||
database: adapter,
|
database: adapter,
|
||||||
session: {
|
session: {
|
||||||
cookieCache: {
|
cookieCache: {
|
||||||
@@ -498,4 +498,33 @@ describe("cookie cache", async () => {
|
|||||||
expect(session.data).not.toBeNull();
|
expect(session.data).not.toBeNull();
|
||||||
expect(fn).toHaveBeenCalledTimes(3);
|
expect(fn).toHaveBeenCalledTimes(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should reset cache when expires", async () => {
|
||||||
|
expect(fn).toHaveBeenCalledTimes(3);
|
||||||
|
await client.getSession({
|
||||||
|
fetchOptions: {
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
vi.useFakeTimers();
|
||||||
|
await vi.advanceTimersByTimeAsync(1000 * 60 * 10); // 10 minutes
|
||||||
|
await client.getSession({
|
||||||
|
fetchOptions: {
|
||||||
|
headers,
|
||||||
|
onSuccess(context) {
|
||||||
|
cookieSetter(headers)(context);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(fn).toHaveBeenCalledTimes(5);
|
||||||
|
await client.getSession({
|
||||||
|
fetchOptions: {
|
||||||
|
headers,
|
||||||
|
onSuccess(context) {
|
||||||
|
cookieSetter(headers)(context);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(fn).toHaveBeenCalledTimes(5);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { APIError } from "better-call";
|
import { APIError } from "better-call";
|
||||||
import { createAuthEndpoint, createAuthMiddleware } from "../call";
|
import { createAuthEndpoint, createAuthMiddleware } from "../call";
|
||||||
import { getDate } from "../../utils/date";
|
import { getDate } from "../../utils/date";
|
||||||
import { deleteSessionCookie, setSessionCookie } from "../../cookies";
|
import {
|
||||||
|
deleteSessionCookie,
|
||||||
|
setCookieCache,
|
||||||
|
setSessionCookie,
|
||||||
|
} from "../../cookies";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import type {
|
import type {
|
||||||
BetterAuthOptions,
|
BetterAuthOptions,
|
||||||
@@ -229,7 +233,7 @@ export const getSession = <Option extends BetterAuthOptions>() =>
|
|||||||
user: InferUser<Option>;
|
user: InferUser<Option>;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
await setCookieCache(ctx, session);
|
||||||
return ctx.json(
|
return ctx.json(
|
||||||
session as unknown as {
|
session as unknown as {
|
||||||
session: InferSession<Option>;
|
session: InferSession<Option>;
|
||||||
|
|||||||
@@ -92,38 +92,13 @@ export function getCookies(options: BetterAuthOptions) {
|
|||||||
|
|
||||||
export type BetterAuthCookies = ReturnType<typeof getCookies>;
|
export type BetterAuthCookies = ReturnType<typeof getCookies>;
|
||||||
|
|
||||||
export async function setSessionCookie(
|
export async function setCookieCache(
|
||||||
ctx: GenericEndpointContext,
|
ctx: GenericEndpointContext,
|
||||||
session: {
|
session: {
|
||||||
session: Session & Record<string, any>;
|
session: Session & Record<string, any>;
|
||||||
user: User;
|
user: User;
|
||||||
},
|
},
|
||||||
dontRememberMe?: boolean,
|
|
||||||
overrides?: Partial<CookieOptions>,
|
|
||||||
) {
|
) {
|
||||||
const options = ctx.context.authCookies.sessionToken.options;
|
|
||||||
const maxAge = dontRememberMe
|
|
||||||
? undefined
|
|
||||||
: ctx.context.sessionConfig.expiresIn;
|
|
||||||
await ctx.setSignedCookie(
|
|
||||||
ctx.context.authCookies.sessionToken.name,
|
|
||||||
session.session.token,
|
|
||||||
ctx.context.secret,
|
|
||||||
{
|
|
||||||
...options,
|
|
||||||
maxAge,
|
|
||||||
...overrides,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dontRememberMe) {
|
|
||||||
await ctx.setSignedCookie(
|
|
||||||
ctx.context.authCookies.dontRememberToken.name,
|
|
||||||
"true",
|
|
||||||
ctx.context.secret,
|
|
||||||
ctx.context.authCookies.dontRememberToken.options,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const shouldStoreSessionDataInCookie =
|
const shouldStoreSessionDataInCookie =
|
||||||
ctx.context.options.session?.cookieCache?.enabled;
|
ctx.context.options.session?.cookieCache?.enabled;
|
||||||
|
|
||||||
@@ -157,7 +132,41 @@ export async function setSessionCookie(
|
|||||||
ctx.context.authCookies.sessionData.options,
|
ctx.context.authCookies.sessionData.options,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setSessionCookie(
|
||||||
|
ctx: GenericEndpointContext,
|
||||||
|
session: {
|
||||||
|
session: Session & Record<string, any>;
|
||||||
|
user: User;
|
||||||
|
},
|
||||||
|
dontRememberMe?: boolean,
|
||||||
|
overrides?: Partial<CookieOptions>,
|
||||||
|
) {
|
||||||
|
const options = ctx.context.authCookies.sessionToken.options;
|
||||||
|
const maxAge = dontRememberMe
|
||||||
|
? undefined
|
||||||
|
: ctx.context.sessionConfig.expiresIn;
|
||||||
|
await ctx.setSignedCookie(
|
||||||
|
ctx.context.authCookies.sessionToken.name,
|
||||||
|
session.session.token,
|
||||||
|
ctx.context.secret,
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
maxAge,
|
||||||
|
...overrides,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (dontRememberMe) {
|
||||||
|
await ctx.setSignedCookie(
|
||||||
|
ctx.context.authCookies.dontRememberToken.name,
|
||||||
|
"true",
|
||||||
|
ctx.context.secret,
|
||||||
|
ctx.context.authCookies.dontRememberToken.options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await setCookieCache(ctx, session);
|
||||||
ctx.context.setNewSession(session);
|
ctx.context.setNewSession(session);
|
||||||
/**
|
/**
|
||||||
* If secondary storage is enabled, store the session data in the secondary storage
|
* If secondary storage is enabled, store the session data in the secondary storage
|
||||||
|
|||||||
Reference in New Issue
Block a user