Session cookie not working in production deployment
Hello everyone,
Unfortunately, my authentication only works on localhost and not in production or the deployed development environment.
We have multiple frontends. Central authentication runs via an Express API (api-ts.playin.gg).
The test frontend for authentication is auth.playin.gg.
Signing in via Google works; you are redirected to /protected and the cookie is set, but the frontend apparently can't retrieve the sessions. What could be the reason for this?
Can anyone help me here? I'm also open to any suggestions for improvement
auth.ts (Express API)
Frontend (auth.playin.gg/protected, NextJS)
Unfortunately, my authentication only works on localhost and not in production or the deployed development environment.
We have multiple frontends. Central authentication runs via an Express API (api-ts.playin.gg).
The test frontend for authentication is auth.playin.gg.
Signing in via Google works; you are redirected to /protected and the cookie is set, but the frontend apparently can't retrieve the sessions. What could be the reason for this?
Can anyone help me here? I'm also open to any suggestions for improvement
auth.ts (Express API)
import { betterAuth } from "better-auth";
import { jwt, twoFactor } from "better-auth/plugins";
import { passkey } from "better-auth/plugins/passkey";
import { createPool } from "mysql2/promise";
export const auth = betterAuth({
appName: "PlayinGG",
advanced: {
cookiePrefix: "playingg_gguardian",
crossSubDomainCookies: {
enabled: true,
domain: ".playin.gg",
},
defaultCookieAttributes: {
secure: true,
httpOnly: true,
sameSite: "none",
partitioned: true,
},
},
emailAndPassword: {
requireEmailVerification: true,
enabled: true,
},
emailVerification: {
sendVerificationEmail: async ({ user, url, token }, request) => {
/* await sendEmail({
to: user.email,
subject: "Verify your email address",
text: `Click the link to verify your email: ${url}`,
}); */
console.log(user, url, token);
},
},
socialProviders: {
discord: {
clientId: process.env.DISCORD_CLIENT_ID as string,
clientSecret: process.env.DISCORD_CLIENT_SECRET as string,
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
twitch: {
clientId: process.env.TWITCH_CLIENT_ID as string,
clientSecret: process.env.TWITCH_CLIENT_SECRET as string,
},
},
user: {
modelName: "users",
fields: {
name: "name",
email: "email",
emailVerified: "email_verified",
image: "image",
createdAt: "created_at",
updatedAt: "updated_at",
},
},
database: createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
}),
trustedOrigins: ["http://localhost:3000", "https://www.playin.gg", "https://playin.gg", "https://portal.playin.gg", "https://auth.playin.gg"], // @WARN: http:localhost:3000 only for development purposes
/* session: {
expiresIn: 60,
}, */
plugins: [jwt(), passkey(), twoFactor()],
});import { betterAuth } from "better-auth";
import { jwt, twoFactor } from "better-auth/plugins";
import { passkey } from "better-auth/plugins/passkey";
import { createPool } from "mysql2/promise";
export const auth = betterAuth({
appName: "PlayinGG",
advanced: {
cookiePrefix: "playingg_gguardian",
crossSubDomainCookies: {
enabled: true,
domain: ".playin.gg",
},
defaultCookieAttributes: {
secure: true,
httpOnly: true,
sameSite: "none",
partitioned: true,
},
},
emailAndPassword: {
requireEmailVerification: true,
enabled: true,
},
emailVerification: {
sendVerificationEmail: async ({ user, url, token }, request) => {
/* await sendEmail({
to: user.email,
subject: "Verify your email address",
text: `Click the link to verify your email: ${url}`,
}); */
console.log(user, url, token);
},
},
socialProviders: {
discord: {
clientId: process.env.DISCORD_CLIENT_ID as string,
clientSecret: process.env.DISCORD_CLIENT_SECRET as string,
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
},
twitch: {
clientId: process.env.TWITCH_CLIENT_ID as string,
clientSecret: process.env.TWITCH_CLIENT_SECRET as string,
},
},
user: {
modelName: "users",
fields: {
name: "name",
email: "email",
emailVerified: "email_verified",
image: "image",
createdAt: "created_at",
updatedAt: "updated_at",
},
},
database: createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
}),
trustedOrigins: ["http://localhost:3000", "https://www.playin.gg", "https://playin.gg", "https://portal.playin.gg", "https://auth.playin.gg"], // @WARN: http:localhost:3000 only for development purposes
/* session: {
expiresIn: 60,
}, */
plugins: [jwt(), passkey(), twoFactor()],
});Frontend (auth.playin.gg/protected, NextJS)
import AccountList from "@/components/settings/account-list";
import LogoutButton from "@/components/auth/logout-button";
import MFASection from "@/components/settings/mfa-section";
import PasskeyList from "@/components/settings/passkey-list";
import SessionList from "@/components/settings/session-list";
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
const ProtectedSSRPage = async () => {
const { data: session } = await auth.getSession({
fetchOptions: {
headers: await headers(),
},
});
if (!session) {
return redirect("/auth/login");
}
return(...)
}
export default ProtectedSSRPage;import AccountList from "@/components/settings/account-list";
import LogoutButton from "@/components/auth/logout-button";
import MFASection from "@/components/settings/mfa-section";
import PasskeyList from "@/components/settings/passkey-list";
import SessionList from "@/components/settings/session-list";
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
const ProtectedSSRPage = async () => {
const { data: session } = await auth.getSession({
fetchOptions: {
headers: await headers(),
},
});
if (!session) {
return redirect("/auth/login");
}
return(...)
}
export default ProtectedSSRPage;