Revert "feat: support cross-domain cookie (#4482)"

This reverts commit 61b6a87435.
This commit is contained in:
Alex Yang
2025-09-12 00:34:01 -07:00
parent 7fc23ba8e4
commit 22b78cfe72
11 changed files with 56 additions and 477 deletions
+8 -86
View File
@@ -50,90 +50,18 @@ export const auth = betterAuth({
})
```
### Cross-Domain Cookies
Sometimes you may need to share cookies across subdomains.
For example, if you authenticate on `auth.example.com`, you may also want to access the same session on `app.example.com`.
Better Auth provides two approaches for this:
#### Option 1: Using crossOriginCookies (Recommended)
```ts title="auth.ts"
import { betterAuth } from "better-auth"
export const auth = betterAuth({
advanced: {
crossOriginCookies: {
enabled: true,
autoSecure: true, // Automatically set secure=true for SameSite=None
allowLocalhostUnsecure: true, // Allow unsecure cookies on localhost for development
},
defaultCookieAttributes: {
sameSite: "none", // Required for cross-domain cookies
// secure: true is automatically set when autoSecure: true
partitioned: true, // Recommended for modern browsers
},
},
trustedOrigins: [
'https://app.mydomain.com',
'https://admin.mydomain.com',
// Add all your frontend domains
],
})
```
#### Option 2: Manual Configuration
```ts title="auth.ts"
import { betterAuth } from "better-auth"
export const auth = betterAuth({
advanced: {
defaultCookieAttributes: {
secure: true,
httpOnly: true,
sameSite: "none", // Allows cross-domain cookie sharing
partitioned: true, // New browser standards will mandate this for foreign cookies
},
},
trustedOrigins: [
'https://app.mydomain.com',
'https://admin.otherdomain.com',
],
})
```
<Callout type="warn">
**Important Requirements for Cross-Domain Cookies:**
- `SameSite=None` cookies **must** have `Secure=true` (except on localhost for development)
- Your API must be served over HTTPS (except localhost)
- You must configure CORS on your backend with `credentials: true`
- Your frontend must use `credentials: 'include'` in fetch requests
- All frontend domains must be added to `trustedOrigins`
</Callout>
<Callout type="warn">Setting your `sameSite` cookie attribute to `none` makes you vulnerable to CSRF attacks. To mitigate risks, configure `trustedOrigins` with an array of authorized origins to allow.</Callout>
### Cross Subdomain Cookies
Sometimes you may need to share cookies across subdomains. For example, if you have `app.example.com` and `example.com`, and if you authenticate on `example.com`, you may want to access the same session on `app.example.com`.
By default, cookies are not shared between subdomains. However, if you need to access the same session across different subdomains, you can enable cross-subdomain cookies by configuring `crossSubDomainCookies` and `defaultCookieAttributes` in the `advanced` object of the auth options.
<Callout>The leading period of the `domain` attribute broadens the cookie's scope beyond your main domain, making it accessible across all subdomains.</Callout>
<Callout type="note">
If your frontend and backend are on different domains, you must configure CORS on your backend, set <code>credentials: 'include'</code> in your frontend requests, and add your frontend domain to <code>trustedOrigins</code>. See the example above for cookie attributes and trustedOrigins usage.
</Callout>
Sometimes you may need to share cookies across subdomains.
For example, if you authenticate on `auth.example.com`, you may also want to access the same session on `app.example.com`.
<Callout type="warn">
The `domain` attribute controls which domains can access the cookie. Setting it to your root domain (e.g. `example.com`) makes the cookie accessible across all subdomains. For security, follow these guidelines:
The `domain` attribute controls which domains can access the cookie. Setting it to your root domain (e.g. `example.com`) makes the cookie accessible across all subdomains. For security, follow these guidelines:
1. Only enable cross-subdomain cookies if it's necessary
2. Set the domain to the most specific scope needed (e.g. `app.example.com` instead of `.example.com`)
3. Be cautious of untrusted subdomains that could potentially access these cookies
4. Consider using separate domains for untrusted services (e.g. `status.company.com` vs `app.company.com`)
1. Only enable cross-subdomain cookies if it's necessary
2. Set the domain to the most specific scope needed (e.g. `app.example.com` instead of `.example.com`)
3. Be cautious of untrusted subdomains that could potentially access these cookies
4. Consider using separate domains for untrusted services (e.g. `status.company.com` vs `app.company.com`)
</Callout>
```ts title="auth.ts"
@@ -143,12 +71,7 @@ export const auth = betterAuth({
advanced: {
crossSubDomainCookies: {
enabled: true,
domain: ".example.com", // Domain with a leading period
},
defaultCookieAttributes: {
secure: true,
httpOnly: true,
sameSite: "lax", // Lax is safe for subdomains
domain: "app.example.com", // your domain
},
},
trustedOrigins: [
@@ -158,7 +81,6 @@ export const auth = betterAuth({
],
})
```
### Secure Cookies
By default, cookies are secure only when the server is running in production mode. You can force cookies to be always secure by setting `useSecureCookies` to `true` in the `advanced` object in the auth options.
-47
View File
@@ -1,15 +1,11 @@
import { createServer } from "node:http";
import { createServer as createHttpsServer } from "node:https";
import { betterAuth } from "better-auth";
import { toNodeHandler } from "better-auth/node";
import Database from "better-sqlite3";
import { getMigrations } from "better-auth/db";
import fs from "node:fs/promises";
import { join } from "path";
export async function createAuthServer(
baseURL: string = "http://localhost:3000",
https: boolean = false,
) {
const database = new Database(":memory:");
@@ -19,19 +15,6 @@ export async function createAuthServer(
emailAndPassword: {
enabled: true,
},
advanced:
https === true
? {
crossOriginCookies: {
enabled: true,
},
defaultCookieAttributes: {
sameSite: "none",
partitioned: true,
},
}
: {},
trustedOrigins: ["https://test.com:3000"],
});
const { runMigrations } = await getMigrations(auth.options);
@@ -47,36 +30,6 @@ export async function createAuthServer(
});
const authHandler = toNodeHandler(auth);
if (https) {
const options = {
key: await fs.readFile(
join(import.meta.dirname, "fixtures", "private-key.pem"),
),
cert: await fs.readFile(
join(import.meta.dirname, "fixtures", "certificate.pem"),
),
};
return createHttpsServer(options, async (req, res) => {
res.setHeader("Access-Control-Allow-Origin", req.headers.origin || "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
res.setHeader("Access-Control-Allow-Credentials", "true");
if (req.method === "OPTIONS") {
res.statusCode = 200;
res.end();
return;
}
const isAuthRoute = req.url?.startsWith("/api/auth");
if (isAuthRoute) {
return authHandler(req, res);
}
res.statusCode = 404;
res.end(JSON.stringify({ error: "Not found" }));
});
}
return createServer(async (req, res) => {
res.setHeader("Access-Control-Allow-Origin", req.headers.origin || "*");
@@ -3,26 +3,18 @@ import { runClient, setup } from "./utils";
const { ref, start, clean } = setup();
test.describe("cross domain", async () => {
test.beforeEach(async () =>
start({
baseURL: "https://demo.com",
https: true,
}),
);
test.beforeEach(async () => start());
test.afterEach(async () => clean());
test("should work across domains", async () => {
const browser = await chromium.launch({
args: [
"--host-resolver-rules=MAP * localhost",
"--ignore-certificate-errors",
],
args: [`--host-resolver-rules=MAP * localhost`],
});
const page = await browser.newPage();
await page.goto(
`https://test.com:${ref.clientPort}/?port=${ref.serverPort}&https=1`,
`http://test.com:${ref.clientPort}/?port=${ref.serverPort}`,
);
await page.locator("text=Ready").waitFor();
@@ -39,25 +31,10 @@ test.describe("cross domain", async () => {
}),
);
// Check that the session is set
// Check that the session is not set because of we didn't set the cookie domain correctly
const cookies = await page.context().cookies();
expect(
cookies.find((c) => c.name === "__Secure-better-auth.session_token"),
).toBeDefined();
// Check that we can get the session
await expect(
runClient(page, async ({ client }) => client.getSession()),
).resolves.toEqual(
expect.objectContaining({
data: expect.objectContaining({
session: expect.objectContaining({}),
user: expect.objectContaining({
email: "test@test.com",
}),
}),
error: null,
}),
);
cookies.find((c) => c.name === "better-auth.session_token"),
).not.toBeDefined();
});
});
@@ -1,19 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDCTCCAfGgAwIBAgIUVqpzTWbcJSV2HHoj4FH++LY8TQEwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDkwOTIyMTYwOVoXDTI1MTAw
OTIyMTYwOVowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA0T8Dqw0HFo3Sh7ZTAfMBk4ENSY7zDhqW6iQgXwHGyI4j
ah40KlHOqB5YKvkrNrJ5aIDdaZy39DzEeEmTnFLsQgVhE+b9A38maeqL+GEJLM4n
vEcKb2m8MgC4NdmnXwdKeEItF4sHQxMicL9LKqNTJMokQWg5UWuBdfcAl8iiK+uD
YMai5OYlvC8hTdq+7I26xGO49uyTuDQHU9PCBEZGvU9BfE7zWX44H68vwcVuaxWi
dGcNPiJZ6KdQa3c0vLbCtkEHoHrQj7s+6xGJT9nVcfjjVjvJFLsM4T3h7oAvebdq
tkJsCje91/WTRdf5TvxIR+uJOz8R3/tq9X1gHale9QIDAQABo1MwUTAdBgNVHQ4E
FgQUDukPU6fLX/U2L1G45aAYPyEJLOAwHwYDVR0jBBgwFoAUDukPU6fLX/U2L1G4
5aAYPyEJLOAwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAUNux
mcwxjOYDKm/6xxbe9EMsZrvLX86yD/wmbvyRZgE5wEn+pD/tgOtFWWNg/QNZwtbr
pwxKYWNRt3O+AXqt0RoPij+Ntn1X6hGp2NMbfVgRJ9HvP6u5CasGxA3AZBrKHtGB
5GLUFB/8CxdARUCML/R+JCrw1howMOl9KJ8s9T1fJic+kKm2g/fZ0pK6RV/nBkkt
veUCgPy0jxN6NcnHN9LTt9Np49sywdaQb2CchB13UyCw3EuBy0kxlyVM2x/wxCzT
y+D7ujdAQqDCJriVHH/XNG7J6633XiR+zRLI0yaPet3ZNp+sl+MSoyAAWz9ENfPg
fWS2EK3F8VkEwru2cQ==
-----END CERTIFICATE-----
@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDRPwOrDQcWjdKH
tlMB8wGTgQ1JjvMOGpbqJCBfAcbIjiNqHjQqUc6oHlgq+Ss2snlogN1pnLf0PMR4
SZOcUuxCBWET5v0DfyZp6ov4YQkszie8RwpvabwyALg12adfB0p4Qi0XiwdDEyJw
v0sqo1MkyiRBaDlRa4F19wCXyKIr64NgxqLk5iW8LyFN2r7sjbrEY7j27JO4NAdT
08IERka9T0F8TvNZfjgfry/BxW5rFaJ0Zw0+Ilnop1BrdzS8tsK2QQegetCPuz7r
EYlP2dVx+ONWO8kUuwzhPeHugC95t2q2QmwKN73X9ZNF1/lO/EhH64k7PxHf+2r1
fWAdqV71AgMBAAECggEAQfGoCEpMx5DenqKZOm4JOyFavKnuc61xjkzgXtDCgwY4
pwLp0cSCan1VsAVi1xQcKxEhtl0LpE9aY8ZcXNHNX2kulQUhC+8QfiTLA/Yg3BwE
bdO9uCsMgn2zkFUN6Gb10zyX1WmdWkg3fGztFXzvgRKrpmlgVwaYgELdzvgOE+TN
VDhToR301o9kHbRjXaDwSlj9NXZIYMXad5HvQHqaQ4eiPz3mxTb+9KRGzzs5E/e1
qxgReaTirA20Ommqpmagp0ymDcppdNIYqdi0an0Msdb322QEVkNkiva/WEt2dyaN
RkFii2QL6WCY276ffLb8DLsrWnWvxS3au1WBGKS/KQKBgQDr1/FdJlUrB0GiGddY
ghhIGmS71ns8z3qXFHm8q2zQm7390de/fpQm0wL98boJ3vWPqmYGvsqAxdkSOY/G
SOfZnQeGT4edK7baMCBd2fupz4uo7SO5GeUkGtKlXynY/JRiiiL9kBnr02T9bsye
pt0/1YCXDCg+Qvv1KhXXWmS6swKBgQDjISSzEo7SvWchSZLkfpWAZ/2n2HxGCgnX
AbIJrhoaW/KdcTNHjIIl+nSsU/LMQFvxvCAN/MXiZULl99LkhfzhvKtx91Sh4vHC
HNGCrfK0yHuJEBOtlle/ACMrhEVsDEhvECb1JeylmjZGT7m7cVSxSn3iUsXi7CFZ
LEDui9DztwKBgHyKnDrEc1U1j8M6Qi3LBWeOCIPoz0tdhS8i8OZg4CWJGNtgZL4K
6dFWvM29SLDNvH8RTK9jMSyvTeIB45qiBU01TzPt639kBjtSDsWAxxT1NJsQHz0w
H4DhaTtK9Z5QQ0uGBtQ/tHCEQWBTklp1Y4DCDhW1pcq7NLJSdxYx9d9hAoGAAd/7
KpNDpI+1szulP8efulChcmpCFF3u2NyFuLi8NG1/4jbWAogxZtjbb7S9s1vwpl00
MolcpNLLK5TRI9vLS53AGI+/Hhr+fei4/ggrkbx58Ja2Yt9z1/rLT4em/w5W5rvO
ZoWqn29XdVshIF/+H/yKb3zZb1cdq1vHKXD0B58CgYEA1rSgsOB/WUdCZL5QgiYs
Our713/AsI65BzDGVqfBXhXpulEffzC7GT4Gdp0WOguCm6iC5WFeWMs5/AxpvFmT
qc5/Wq57wOt0E9CG5aaXbZHQ/tWENEdHFThV4rBO8xFqUZJnUxLuSIyzQRAO2o33
HAQhmXetMKmi4igeSsWECQE=
-----END PRIVATE KEY-----
+6 -14
View File
@@ -26,15 +26,11 @@ export function setup() {
};
return {
ref,
start: async (options?: { baseURL?: string; https?: boolean }) => {
server = await createAuthServer(options?.baseURL, options?.https);
start: async () => {
server = await createAuthServer();
clientChild = spawn("pnpm", ["run", "start:client"], {
cwd: root,
stdio: "pipe",
env: {
...process.env,
HTTPS: options?.https ? "1" : "0",
},
});
clientChild.stderr.on("data", (data) => {
const message = data.toString();
@@ -51,7 +47,6 @@ export function setup() {
const address = server.address();
if (address && typeof address === "object") {
ref.serverPort = address.port;
console.log(`Server listening on port ${ref.serverPort}`);
resolve();
}
});
@@ -60,14 +55,11 @@ export function setup() {
clientChild.stdout.on("data", (data) => {
const message = data.toString();
// find: http://localhost:5173/
if (
message.includes("http://localhost:") ||
message.includes("https://localhost:")
) {
if (message.includes("http://localhost:")) {
const port: string = message
.split("http")[1]
.split("localhost:")[1]
.split("/")[0];
.split("http://localhost:")[1]
.split("/")[0]
.trim();
ref.clientPort = Number(port.replace(/\x1b\[[0-9;]*m/g, ""));
resolve();
}
+1 -2
View File
@@ -2,10 +2,9 @@ import { createAuthClient } from "better-auth/client";
const search = new URLSearchParams(window.location.search);
const port = search.get("port");
const https = search.get("https");
const client = createAuthClient({
baseURL: `http${https ? "s" : ""}://localhost:${port ?? 3000}`,
baseURL: `http://localhost:${port ?? 3000}`,
});
declare global {
@@ -3,12 +3,5 @@ import { defineConfig } from "vite";
export default defineConfig({
server: {
allowedHosts: ["test.com", "localhost"],
https:
process.env.HTTPS === "1"
? {
key: "./e2e/fixtures/private-key.pem",
cert: "./e2e/fixtures/certificate.pem",
}
: undefined,
},
});
@@ -1,8 +1,8 @@
import { describe, expect, it } from "vitest";
import { getCookieCache, getCookies, getSessionCookie } from "../cookies";
import { getTestInstance } from "../test-utils/test-instance";
import type { BetterAuthOptions } from "../types/options";
import { getCookieCache, getCookies, getSessionCookie } from "../cookies";
import { parseSetCookieHeader } from "./cookie-utils";
import type { BetterAuthOptions } from "../types/options";
describe("cookies", async () => {
const { client, testUser } = await getTestInstance();
@@ -369,142 +369,3 @@ describe("getSessionCookie", async () => {
await expect(getCookieCache(request)).rejects.toThrow();
});
});
describe("cross-origin cookies", () => {
it("should handle sameSite=none with secure=true correctly", async () => {
const { client, testUser } = await getTestInstance({
baseURL: "https://api.example.com",
advanced: {
defaultCookieAttributes: {
sameSite: "none",
secure: true,
},
},
});
await client.signIn.email(
{
email: testUser.email,
password: testUser.password,
},
{
onResponse(context) {
const setCookie = context.response.headers.get("set-cookie");
expect(setCookie).toContain("SameSite=None");
expect(setCookie).toContain("Secure");
},
},
);
});
it("should auto-enforce secure for sameSite=none", async () => {
const { client, testUser } = await getTestInstance({
baseURL: "https://api.example.com",
advanced: {
crossOriginCookies: {
enabled: true,
autoSecure: true,
},
defaultCookieAttributes: {
sameSite: "none",
// secure not explicitly set - should be auto-enforced
},
},
});
await client.signIn.email(
{
email: testUser.email,
password: testUser.password,
},
{
onResponse(context) {
const setCookie = context.response.headers.get("set-cookie");
expect(setCookie).toContain("SameSite=None");
expect(setCookie).toContain("Secure");
},
},
);
});
it("should allow unsecure cookies on localhost for development", async () => {
const { client, testUser } = await getTestInstance({
baseURL: "http://localhost:3000",
advanced: {
crossOriginCookies: {
enabled: true,
autoSecure: true,
allowLocalhostUnsecure: true,
},
defaultCookieAttributes: {
sameSite: "none",
secure: false,
},
},
});
await client.signIn.email(
{
email: testUser.email,
password: testUser.password,
},
{
onResponse(context) {
const setCookie = context.response.headers.get("set-cookie");
expect(setCookie).toContain("SameSite=None");
// Should not contain Secure on localhost when allowLocalhostUnsecure is true
expect(setCookie).not.toContain("Secure");
},
},
);
});
it("should throw error for sameSite=none without secure on non-localhost", async () => {
await expect(async () => {
await getTestInstance({
baseURL: "https://api.example.com",
advanced: {
crossOriginCookies: {
enabled: true,
autoSecure: false, // Disable auto-secure
},
defaultCookieAttributes: {
sameSite: "none",
secure: false, // Explicitly set to false
},
},
});
}).rejects.toThrow("SameSite=None cookies require Secure=true");
});
it("should work with partitioned attribute for cross-origin", async () => {
const { client, testUser } = await getTestInstance({
baseURL: "https://api.example.com",
advanced: {
crossOriginCookies: {
enabled: true,
},
defaultCookieAttributes: {
sameSite: "none",
secure: true,
partitioned: true,
},
},
});
await client.signIn.email(
{
email: testUser.email,
password: testUser.password,
},
{
onResponse(context) {
const setCookie = context.response.headers.get("set-cookie");
expect(setCookie).toContain("SameSite=None");
expect(setCookie).toContain("Secure");
expect(setCookie).toContain("Partitioned");
},
},
);
});
});
+19 -66
View File
@@ -1,16 +1,16 @@
import { base64Url } from "@better-auth/utils/base64";
import { binary } from "@better-auth/utils/binary";
import { createHMAC } from "@better-auth/utils/hmac";
import type { CookieOptions } from "better-call";
import { ms } from "ms";
import { BetterAuthError } from "../error";
import type { Session, User } from "../types";
import type { GenericEndpointContext } from "../types/context";
import type { BetterAuthOptions } from "../types/options";
import { getDate } from "../utils/date";
import { env, isProduction } from "../utils/env";
import { base64Url } from "@better-auth/utils/base64";
import { ms } from "ms";
import { createHMAC } from "@better-auth/utils/hmac";
import { safeJSONParse } from "../utils/json";
import { getBaseURL } from "../utils/url";
import { binary } from "@better-auth/utils/binary";
export function createCookieGetter(options: BetterAuthOptions) {
const secure =
@@ -24,22 +24,10 @@ export function createCookieGetter(options: BetterAuthOptions) {
const secureCookiePrefix = secure ? "__Secure-" : "";
const crossSubdomainEnabled =
!!options.advanced?.crossSubDomainCookies?.enabled;
const crossOriginEnabled = !!options.advanced?.crossOriginCookies?.enabled;
// Cross-origin cookie configuration
const crossOriginConfig = {
autoSecure: options.advanced?.crossOriginCookies?.autoSecure ?? true,
allowLocalhostUnsecure:
options.advanced?.crossOriginCookies?.allowLocalhostUnsecure ?? true,
...options.advanced?.crossOriginCookies,
};
const domain = crossOriginEnabled
? undefined
: crossSubdomainEnabled
? options.advanced?.crossSubDomainCookies?.domain ||
(options.baseURL ? new URL(options.baseURL).hostname : undefined)
: undefined;
const domain = crossSubdomainEnabled
? options.advanced?.crossSubDomainCookies?.domain ||
(options.baseURL ? new URL(options.baseURL).hostname : undefined)
: undefined;
if (crossSubdomainEnabled && !domain) {
throw new BetterAuthError(
"baseURL is required when crossSubdomainCookies are enabled",
@@ -57,53 +45,18 @@ export function createCookieGetter(options: BetterAuthOptions) {
const attributes =
options.advanced?.cookies?.[cookieName as "session_token"]?.attributes;
// Build base attributes
let baseAttributes: CookieOptions = {
secure: !!secureCookiePrefix,
sameSite: "lax",
path: "/",
httpOnly: true,
...(crossSubdomainEnabled ? { domain } : {}),
};
// Merge with user-defined attributes
const mergedAttributes = {
...baseAttributes,
...options.advanced?.defaultCookieAttributes,
...overrideAttributes,
...attributes,
};
// Enforce security constraints for SameSite=None cookies
if (mergedAttributes.sameSite === "none") {
const isLocalhost =
options.baseURL?.startsWith("http://localhost") ||
options.baseURL?.startsWith("http://127.0.0.1");
// SameSite=None requires Secure=true (except localhost in development)
if (!mergedAttributes.secure) {
if (crossOriginConfig.allowLocalhostUnsecure && isLocalhost) {
// Allow unsecure cookies on localhost for development
} else {
throw new BetterAuthError(
"SameSite=None cookies require Secure=true. Set secure: true in your cookie attributes, use HTTPS, or disable crossOriginCookies.autoSecure for development.",
);
}
}
// Auto-set secure for SameSite=None (except localhost for development)
if (crossOriginConfig.autoSecure && !isLocalhost) {
mergedAttributes.secure = true;
}
}
// Apply secure cookie prefix if secure is enforced
const finalSecurePrefix = mergedAttributes.secure ? "__Secure-" : "";
const finalName = `${finalSecurePrefix}${name}`;
return {
name: finalName,
attributes: mergedAttributes as CookieOptions,
name: `${secureCookiePrefix}${name}`,
attributes: {
secure: !!secureCookiePrefix,
sameSite: "lax",
path: "/",
httpOnly: true,
...(crossSubdomainEnabled ? { domain } : {}),
...options.advanced?.defaultCookieAttributes,
...overrideAttributes,
...attributes,
} as CookieOptions,
};
}
return createCookie;
+14 -38
View File
@@ -1,14 +1,4 @@
import type { CookieOptions } from "better-call";
import type { Database } from "better-sqlite3";
import type { Database as BunDatabase } from "bun:sqlite";
import type { Dialect, Kysely, MysqlPool, PostgresPool } from "kysely";
import type { DatabaseSync } from "node:sqlite";
import type { AuthContext } from ".";
import type { AdapterDebugLogs } from "../adapters";
import type { KyselyDatabaseType } from "../adapters/kysely-adapter/types";
import type { FieldAttribute } from "../db";
import type { AuthMiddleware } from "../plugins";
import type { SocialProviderList, SocialProviders } from "../social-providers";
import type {
Account,
GenericEndpointContext,
@@ -16,11 +6,21 @@ import type {
User,
Verification,
} from "../types";
import type { Logger } from "../utils";
import type { AdapterInstance, SecondaryStorage } from "./adapter";
import type { LiteralUnion, OmitId } from "./helper";
import type { Models, RateLimit } from "./models";
import type { BetterAuthPlugin } from "./plugins";
import type { SocialProviderList, SocialProviders } from "../social-providers";
import type { AdapterInstance, SecondaryStorage } from "./adapter";
import type { KyselyDatabaseType } from "../adapters/kysely-adapter/types";
import type { FieldAttribute } from "../db";
import type { Models, RateLimit } from "./models";
import type { AuthContext } from ".";
import type { CookieOptions } from "better-call";
import type { Database } from "better-sqlite3";
import type { Logger } from "../utils";
import type { AuthMiddleware } from "../plugins";
import type { LiteralUnion, OmitId } from "./helper";
import type { AdapterDebugLogs } from "../adapters";
import type { Database as BunDatabase } from "bun:sqlite";
import type { DatabaseSync } from "node:sqlite";
export type BetterAuthOptions = {
/**
@@ -711,30 +711,6 @@ export type BetterAuthOptions = {
*/
domain?: string;
};
/**
* Configure cookies for cross-origin scenarios
*
* This enables proper handling of SameSite=None cookies
* when your API and frontend are on different domains.
*/
crossOriginCookies?: {
/**
* Enable cross-origin cookie handling
*/
enabled: boolean;
/**
* Automatically set Secure=true when SameSite=None is detected
*
* @default true
*/
autoSecure?: boolean;
/**
* Allow localhost without secure cookies (for development)
*
* @default true
*/
allowLocalhostUnsecure?: boolean;
};
/*
* Allows you to change default cookie names and attributes
*