mirror of
https://github.com/better-auth/better-auth.git
synced 2026-10-25 10:13:54 -05:00
fix: respect additionalFields returned config for user data when setting cookie cache (#5327)
Co-authored-by: Bereket Engida <86073083+Bekacru@users.noreply.github.com> Co-authored-by: Bereket Engida <Bekacru@gmail.com>
This commit is contained in:
co-authored by
Bereket Engida
Bereket Engida
parent
713eaf7693
commit
a048f804ff
@@ -433,3 +433,263 @@ describe("getSessionCookie", async () => {
|
||||
expect(result?.user).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Cookie Cache Field Filtering", () => {
|
||||
it("should exclude user fields with returned: false from cookie cache", async () => {
|
||||
const { client, testUser, cookieSetter } = await getTestInstance({
|
||||
secret: "better-auth.secret",
|
||||
user: {
|
||||
additionalFields: {
|
||||
internalNote: {
|
||||
type: "string",
|
||||
defaultValue: "",
|
||||
returned: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
session: {
|
||||
cookieCache: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const headers = new Headers();
|
||||
|
||||
await client.signIn.email(
|
||||
{
|
||||
email: testUser.email,
|
||||
password: testUser.password,
|
||||
},
|
||||
{
|
||||
onSuccess: cookieSetter(headers),
|
||||
},
|
||||
);
|
||||
|
||||
const request = new Request("https://example.com/api/auth/session", {
|
||||
headers,
|
||||
});
|
||||
|
||||
const cache = await getCookieCache(request, {
|
||||
secret: "better-auth.secret",
|
||||
});
|
||||
|
||||
expect(cache).not.toBeNull();
|
||||
expect(cache?.user?.email).toEqual(testUser.email);
|
||||
expect(cache?.user?.internalNote).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should correctly filter multiple user fields based on returned config", async () => {
|
||||
const { client, testUser, cookieSetter } = await getTestInstance({
|
||||
secret: "better-auth.secret",
|
||||
user: {
|
||||
additionalFields: {
|
||||
publicBio: {
|
||||
type: "string",
|
||||
defaultValue: "default-bio",
|
||||
returned: true,
|
||||
},
|
||||
internalNotes: {
|
||||
type: "string",
|
||||
defaultValue: "internal-notes",
|
||||
returned: false,
|
||||
},
|
||||
preferences: {
|
||||
type: "string",
|
||||
defaultValue: "default-prefs",
|
||||
returned: true,
|
||||
},
|
||||
adminFlags: {
|
||||
type: "string",
|
||||
defaultValue: "admin-flags",
|
||||
returned: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
session: {
|
||||
cookieCache: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const headers = new Headers();
|
||||
await client.signIn.email(
|
||||
{
|
||||
email: testUser.email,
|
||||
password: testUser.password,
|
||||
},
|
||||
{
|
||||
onSuccess: cookieSetter(headers),
|
||||
},
|
||||
);
|
||||
|
||||
const request = new Request("https://example.com/api/auth/session", {
|
||||
headers,
|
||||
});
|
||||
|
||||
const cache = await getCookieCache(request, {
|
||||
secret: "better-auth.secret",
|
||||
});
|
||||
|
||||
expect(cache).not.toBeNull();
|
||||
// Fields with returned: true should be included
|
||||
expect(cache?.user?.publicBio).toBeDefined();
|
||||
expect(cache?.user?.preferences).toBeDefined();
|
||||
// Fields with returned: false should be excluded
|
||||
expect(cache?.user?.internalNotes).toBeUndefined();
|
||||
expect(cache?.user?.adminFlags).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should reduce cookie size when large fields are excluded", async () => {
|
||||
const largeString = "x".repeat(2000);
|
||||
const { client, testUser, cookieSetter } = await getTestInstance({
|
||||
secret: "better-auth.secret",
|
||||
user: {
|
||||
additionalFields: {
|
||||
largeBio: {
|
||||
type: "string",
|
||||
defaultValue: largeString,
|
||||
returned: false,
|
||||
},
|
||||
smallField: {
|
||||
type: "string",
|
||||
defaultValue: "small-value",
|
||||
returned: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
session: {
|
||||
cookieCache: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const headers = new Headers();
|
||||
|
||||
// Sign in with testUser
|
||||
await client.signIn.email(
|
||||
{
|
||||
email: testUser.email,
|
||||
password: testUser.password,
|
||||
},
|
||||
{
|
||||
onSuccess: cookieSetter(headers),
|
||||
},
|
||||
);
|
||||
|
||||
const request = new Request("https://example.com/api/auth/session", {
|
||||
headers,
|
||||
});
|
||||
|
||||
const cache = await getCookieCache(request, {
|
||||
secret: "better-auth.secret",
|
||||
});
|
||||
|
||||
// Cookie cache should exist (not exceed size limit)
|
||||
expect(cache).not.toBeNull();
|
||||
// Large field should be excluded
|
||||
expect(cache?.user?.largeBio).toBeUndefined();
|
||||
// Small field should be included
|
||||
expect(cache?.user?.smallField).toBeDefined();
|
||||
});
|
||||
|
||||
it("should maintain session field filtering (regression check)", async () => {
|
||||
const { client, testUser, cookieSetter } = await getTestInstance({
|
||||
secret: "better-auth.secret",
|
||||
session: {
|
||||
additionalFields: {
|
||||
internalSessionData: {
|
||||
type: "string",
|
||||
defaultValue: "internal-data",
|
||||
returned: false,
|
||||
},
|
||||
publicSessionData: {
|
||||
type: "string",
|
||||
defaultValue: "public-data",
|
||||
returned: true,
|
||||
},
|
||||
},
|
||||
cookieCache: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const headers = new Headers();
|
||||
|
||||
// Sign in with testUser
|
||||
await client.signIn.email(
|
||||
{
|
||||
email: testUser.email,
|
||||
password: testUser.password,
|
||||
},
|
||||
{
|
||||
onSuccess: cookieSetter(headers),
|
||||
},
|
||||
);
|
||||
|
||||
const request = new Request("https://example.com/api/auth/session", {
|
||||
headers,
|
||||
});
|
||||
|
||||
const cache = await getCookieCache(request, {
|
||||
secret: "better-auth.secret",
|
||||
});
|
||||
|
||||
expect(cache).not.toBeNull();
|
||||
// Verify session field filtering still works correctly
|
||||
// Session should have token
|
||||
expect(cache?.session?.token).toEqual(expect.any(String));
|
||||
// Session field with returned: false should be excluded
|
||||
expect(cache?.session?.internalSessionData).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should include unknown user fields for backward compatibility", async () => {
|
||||
const { client, testUser, cookieSetter } = await getTestInstance({
|
||||
secret: "better-auth.secret",
|
||||
user: {
|
||||
additionalFields: {
|
||||
knownField: {
|
||||
type: "string",
|
||||
defaultValue: "known-value",
|
||||
returned: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
session: {
|
||||
cookieCache: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const headers = new Headers();
|
||||
|
||||
await client.signIn.email(
|
||||
{
|
||||
email: testUser.email,
|
||||
password: testUser.password,
|
||||
},
|
||||
{
|
||||
onSuccess: cookieSetter(headers),
|
||||
},
|
||||
);
|
||||
|
||||
const request = new Request("https://example.com/api/auth/session", {
|
||||
headers,
|
||||
});
|
||||
|
||||
const cache = await getCookieCache(request, {
|
||||
secret: "better-auth.secret",
|
||||
});
|
||||
|
||||
expect(cache).not.toBeNull();
|
||||
// Known field with returned: false should be excluded
|
||||
expect(cache?.user?.knownField).toBeUndefined();
|
||||
// Standard fields like email, name should be included (backward compatibility)
|
||||
expect(cache?.user?.email).toEqual(testUser.email);
|
||||
expect(cache?.user?.name).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ import type {
|
||||
BetterAuthCookies,
|
||||
GenericEndpointContext,
|
||||
} from "@better-auth/core";
|
||||
import { parseUserOutput } from "../db/schema";
|
||||
|
||||
export function createCookieGetter(options: BetterAuthOptions) {
|
||||
const secure =
|
||||
@@ -119,7 +120,9 @@ export async function setCookieCache(
|
||||
{} as Record<string, any>,
|
||||
);
|
||||
|
||||
const sessionData = { session: filteredSession, user: session.user };
|
||||
// Apply field filtering to user data
|
||||
const filteredUser = parseUserOutput(ctx.context.options, session.user);
|
||||
const sessionData = { session: filteredSession, user: filteredUser };
|
||||
|
||||
const options = {
|
||||
...ctx.context.authCookies.sessionData.options,
|
||||
|
||||
Reference in New Issue
Block a user