Better AuthBA
Better Auth•9mo ago
Felix

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)
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;
image.png
Was this page helpful?