Skip to content

Commit cf38b22

Browse files
authored
feat: adds cookies.encode option allowing minimal cookie sizes (#126)
Adds an experimental option `encode` on the `cookies` object when using `createBrowserClient()` and `createServerClient()`. If this is set to `tokens-only` then only the user's access token and refresh token will be encoded in the cookies, causing significant cookie size savings, often greater than 50%. It utilizes [split session storage in `auth-js`](supabase/supabase-js#1545), with some trade-offs such as the inability to access the `user` property on the `supabase.auth.getSession()` object in the server. This wasn't supposed to be done anyway, and `getClaims()` is a secure alternative for it.
1 parent e8b6102 commit cf38b22

File tree

6 files changed

+85
-29
lines changed

6 files changed

+85
-29
lines changed

package-lock.json

Lines changed: 28 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"homepage": "https://github.com/supabase/ssr#readme",
3434
"devDependencies": {
3535
"@eslint/js": "^9.3.0",
36-
"@supabase/supabase-js": "^2.43.4",
36+
"@supabase/supabase-js": "^2.57.4",
3737
"@types/node": "^24.3.0",
3838
"@vitest/coverage-v8": "^1.6.0",
3939
"eslint": "^8.57.0",

src/createBrowserClient.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ export function createBrowserClient<
141141
detectSessionInUrl: isBrowser(),
142142
persistSession: true,
143143
storage,
144+
...(options?.cookies &&
145+
"encode" in options.cookies &&
146+
options.cookies.encode === "tokens-only"
147+
? {
148+
userStorage: options?.auth?.userStorage ?? window.localStorage,
149+
}
150+
: null),
144151
},
145152
});
146153

src/createServerClient.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
CookieMethodsServer,
1313
CookieMethodsServerDeprecated,
1414
} from "./types";
15+
import { memoryLocalStorageAdapter } from "./utils/helpers";
1516

1617
/**
1718
* @deprecated Please specify `getAll` and `setAll` cookie methods instead of
@@ -170,6 +171,14 @@ export function createServerClient<
170171
detectSessionInUrl: false,
171172
persistSession: true,
172173
storage,
174+
...(options?.cookies &&
175+
"encode" in options.cookies &&
176+
options.cookies.encode === "tokens-only"
177+
? {
178+
userStorage:
179+
options?.auth?.userStorage ?? memoryLocalStorageAdapter(),
180+
}
181+
: null),
173182
},
174183
});
175184

src/types.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ export type CookieMethodsBrowserDeprecated = {
3333
};
3434

3535
export type CookieMethodsBrowser = {
36+
/**
37+
* If set to true, only the user's session (access and refresh tokens) will be encoded in cookies. The user object will be encoded in local storage if the `userStorage` option is not provided when creating the client.
38+
*
39+
* You should keep this option the same between `createBrowserClient()` and `createServerClient()`. When set to `tokens-only` accessing the `user` property on the data returned from `getSession()` will only be possible if the user has already been stored in the separate storage. It's best to use `getClaims()` instead to avoid surprizes.
40+
*
41+
* @experimental
42+
*/
43+
encode?: "user-and-tokens" | "tokens-only";
44+
3645
getAll: GetAllCookies;
3746
setAll: SetAllCookies;
3847
};
@@ -44,6 +53,15 @@ export type CookieMethodsServerDeprecated = {
4453
};
4554

4655
export type CookieMethodsServer = {
56+
/**
57+
* If set to `tokens-only`, only the user's access and refresh tokens will be encoded in cookies. The user object will be encoded in memory if the `userStorage` option is not provided when creating the client. Unset value defaults to `user-and-tokens`.
58+
*
59+
* You should keep this option the same between `createBrowserClient()` and `createServerClient()`. When set to `tokens-only` accessing the `user` property on the data returned from `getSession()` will not be possible. Use `getUser()` or preferably `getClaims()` instead.
60+
*
61+
* @experimental
62+
*/
63+
encode?: "user-and-tokens" | "tokens-only";
64+
4765
getAll: GetAllCookies;
4866
setAll?: SetAllCookies;
4967
};

src/utils/helpers.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,25 @@ export function isBrowser() {
5151
typeof window !== "undefined" && typeof window.document !== "undefined"
5252
);
5353
}
54+
55+
/**
56+
* Returns a localStorage-like object that stores the key-value pairs in
57+
* memory.
58+
*/
59+
export function memoryLocalStorageAdapter(
60+
store: { [key: string]: string } = {},
61+
) {
62+
return {
63+
getItem: (key: string) => {
64+
return store[key] || null;
65+
},
66+
67+
setItem: (key: string, value: string) => {
68+
store[key] = value;
69+
},
70+
71+
removeItem: (key: string) => {
72+
delete store[key];
73+
},
74+
};
75+
}

0 commit comments

Comments
 (0)