Cookies disappear on web app after refresh in production with Turborepo setup using better-auth
I have a Turborepo monorepo with two apps:
apps/server — handles backend and authentication
apps/web — frontend app consuming the auth API from the server
All my better-auth configuration is centralized in a shared package at packages/db.
Issue:
On localhost, everything works perfectly — authentication cookies are set and persist on both server and web apps, even after page refresh.
In production, the cookies are correctly set initially, but after refreshing the page in the web app, the authentication cookies disappear and the user session is lost.
Interestingly, on the server side the cookies persist correctly after refresh.
Auth configuration (auth.ts):
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@repo/db/db/index";
import * as schema from "../db/db/schema/auth";
import { emailOTP } from "better-auth/plugins";
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg",
schema: schema,
}),
trustedOrigins: [
process.env.CORS_ORIGIN!
],
emailAndPassword: {
enabled: true,
},
plugins: [
emailOTP({
async sendVerificationOTP({ email, otp, type }) {
console.log({ email, otp, type });
// Implement sending OTP email here
},
}),
],
advanced: {
cookies: {
session_token: {
attributes: {
sameSite: "none",
secure: true,
httpOnly: true,
},
},
},
},
secret: process.env.BETTER_AUTH_SECRET,
baseURL: process.env.BETTER_AUTH_URL,
});
DATABASE_URL=database_url
CORS_ORIGIN=https://turborepo-web-eta.vercel.app # localhost:3001 (web) in dev
BETTER_AUTH_SECRET=betterauthsecret
BETTER_AUTH_URL=https://turborepo-server-rbj2.vercel.app # localhost:3000 (server) in devCreate Next App
Generated by create next app
3 Replies