api/auth/get-session returns null in prod but works locally

hi, my backend is made with express/node.js and my frontend with nextjs but the get-session api returns null in production whereas everything works perfectly locally.
27 Replies
M_Cavus
M_CavusOP2w ago
when I go to the url localhost:8080/api/auth/get-session it sends me back
{
“session": {
“id": ‘h8BWGy8cuJK5ymrdvkaYOj8DqKwKdkZ4’,
“expiresAt": ‘2025-05-15T17:52:49.661Z’,
“token": ‘lnQcBgIeRif5T5kM1FEPjd2Lf6Sg4dKdf’,
“createdAt": ‘2025-05-08T17:52:49.661Z’,
“updatedAt": ‘2025-05-08T17:52:49.661Z’,
“ipAddress": ‘’,
“userAgent": ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36’,
“userId": ”vWOE8LJWO5oKiPY5KIwVWjbGiVyc4t9q”
},
“user": {
.....
}
}
{
“session": {
“id": ‘h8BWGy8cuJK5ymrdvkaYOj8DqKwKdkZ4’,
“expiresAt": ‘2025-05-15T17:52:49.661Z’,
“token": ‘lnQcBgIeRif5T5kM1FEPjd2Lf6Sg4dKdf’,
“createdAt": ‘2025-05-08T17:52:49.661Z’,
“updatedAt": ‘2025-05-08T17:52:49.661Z’,
“ipAddress": ‘’,
“userAgent": ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36’,
“userId": ”vWOE8LJWO5oKiPY5KIwVWjbGiVyc4t9q”
},
“user": {
.....
}
}
but when I'm in production it gives me a blank page. Of course with the https link instead of localhost
M_Cavus
M_CavusOP2w ago
No description
Josh
Josh2w ago
Do your server logs say anything?
M_Cavus
M_CavusOP2w ago
No description
M_Cavus
M_CavusOP2w ago
no it says everything is ok
Josh
Josh2w ago
Odd I have something similar but I think that might just be a CORS issue Your requests look like they come in whereas mine stay stuck on pending for 5min and then they’re cancelled
M_Cavus
M_CavusOP2w ago
what I find suspicious is that when I'm local and I go to the get-session api link, it displays the session correctly, whereas in production it returns null, and even worse, there's no error that could facilitate debugging.
Felix
Felix2w ago
I have exactly the same setup and the exact same issue. Various solutions about a month ago didn't help, see: https://discord.com/channels/1288403910284935179/1359765737140523060 I'm still having the same problem. Everything works fine on localhost. In deployment, only client-side useSession works; there's no chance of a server-side getSession, even though the cookies are logged correctly... There's a Notion link to my code in my blog post.
M_Cavus
M_CavusOP2w ago
ok thanks for your help, i'll try to solve it if i can i'll give you the solution
daveycodez
daveycodez2w ago
Hey Is your API on a different domain from your website This looks like a cross-domain cookie issue Add this to your auth.ts
advanced: {
defaultCookieAttributes:
process.env.NODE_ENV === "production"
? {
sameSite: "none",
secure: true
}
: undefined
},
advanced: {
defaultCookieAttributes:
process.env.NODE_ENV === "production"
? {
sameSite: "none",
secure: true
}
: undefined
},
sebastian
sebastian2w ago
Yep, also got simmilar problem and cross domain cookies are the way. Remember to also clear cookies regularly so you will know when exactly you fixed the issue.
daveycodez
daveycodez2w ago
the NODE_ENV check is because Safari won't work on localhost if you use sameSite none secure true on dev
M_Cavus
M_CavusOP2w ago
Thank you very much, you should have added the advenced parameter so that cookies can reach the frontend. ah bas I got excited too early it works on ARC PC but when I switch to mobile it doesn't work the same way as safari on PC.
sebastian
sebastian2w ago
Try in incognito
M_Cavus
M_CavusOP2w ago
Yes I tried with incognito and even on other mobile but still no and strangely on pc with arc it works but not with safari here's my auth.js config on the backend
const { betterAuth } = require("better-auth");
const { admin } = require("better-auth/plugins");
const { prismaAdapter } = require("better-auth/adapters/prisma");
const prisma = require("../db/prisma");
const { nextCookies } = require("better-auth/next-js");

const CLIENT_SIDE_URL = process.env.BETTER_AUTH_URL;

const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
emailAndPassword: {
enabled: true,
},
advanced: {
defaultCookieAttributes:
process.env.NODE_ENV === "production"
? {
sameSite: "none",
secure: true,
}
: undefined,
},
trustedOrigins: [`${CLIENT_SIDE_URL}`],
plugins: [admin(), nextCookies()],
secret: process.env.BETTER_AUTH_SECRET,
baseURL: process.env.BETTER_AUTH_URL,
});

module.exports = { auth };
const { betterAuth } = require("better-auth");
const { admin } = require("better-auth/plugins");
const { prismaAdapter } = require("better-auth/adapters/prisma");
const prisma = require("../db/prisma");
const { nextCookies } = require("better-auth/next-js");

const CLIENT_SIDE_URL = process.env.BETTER_AUTH_URL;

const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
emailAndPassword: {
enabled: true,
},
advanced: {
defaultCookieAttributes:
process.env.NODE_ENV === "production"
? {
sameSite: "none",
secure: true,
}
: undefined,
},
trustedOrigins: [`${CLIENT_SIDE_URL}`],
plugins: [admin(), nextCookies()],
secret: process.env.BETTER_AUTH_SECRET,
baseURL: process.env.BETTER_AUTH_URL,
});

module.exports = { auth };
sebastian
sebastian2w ago
Try adding also crosssubdomain cookies. advanced: { crossSubDomainCookies: { enabled: true } }
M_Cavus
M_CavusOP2w ago
by adding sub-domains even the pc version on arc no longer works This is my protected page
import { Header } from "@/components/dashboard/header/Header";
import { Call_Table } from "@/components/dashboard/table/Call_Table";
import { Footer } from "@/components/navigations/footer/Footer";
import { Navigation_Container } from "@/components/navigations/Navigation_Container";
import { authClient } from "@/lib/auth-client";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";

const BACKEN_URL = process.env.NEXT_PUBLIC_CLIENT_SIDE_URL;

interface User {
id: string;
name: string;
}

export default function Dashboard() {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const router = useRouter();

const fetchUserData = async () => {
try {
const response = await fetch(`${BACKEN_URL}/api/auth/get-session`, {
credentials: "include",
headers: {
"Content-Type": "application/json",
},
});

const data = await response.json();
console.log("Données utilisateur récupérées :", data);
setUser(data.user);
} catch (error) {
console.error("Erreur lors de la récupération des données.", error);
} finally {
setLoading(false);
}
};

useEffect(() => {
if (!user && !loading) {
router.push("/");
} else if (user && !loading) {
setLoading(false);
}
}, [user, loading]);

useEffect(() => {
if (!user) {
fetchUserData();
}
}, [user]);

const signOut = async () => {
try {
setLoading(true);
await authClient.signOut();
router.push("/");
} catch (error) {
console.error("Sign out error:", error);
}
};

return (
<section>
<Navigation_Container
userName={user?.name || "NaN"}
logOut={signOut}
loading={loading}
/>
<Header />
<Call_Table userId={user?.id ?? ""} />
<Footer />
</section>
);
}
import { Header } from "@/components/dashboard/header/Header";
import { Call_Table } from "@/components/dashboard/table/Call_Table";
import { Footer } from "@/components/navigations/footer/Footer";
import { Navigation_Container } from "@/components/navigations/Navigation_Container";
import { authClient } from "@/lib/auth-client";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";

const BACKEN_URL = process.env.NEXT_PUBLIC_CLIENT_SIDE_URL;

interface User {
id: string;
name: string;
}

export default function Dashboard() {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const router = useRouter();

const fetchUserData = async () => {
try {
const response = await fetch(`${BACKEN_URL}/api/auth/get-session`, {
credentials: "include",
headers: {
"Content-Type": "application/json",
},
});

const data = await response.json();
console.log("Données utilisateur récupérées :", data);
setUser(data.user);
} catch (error) {
console.error("Erreur lors de la récupération des données.", error);
} finally {
setLoading(false);
}
};

useEffect(() => {
if (!user && !loading) {
router.push("/");
} else if (user && !loading) {
setLoading(false);
}
}, [user, loading]);

useEffect(() => {
if (!user) {
fetchUserData();
}
}, [user]);

const signOut = async () => {
try {
setLoading(true);
await authClient.signOut();
router.push("/");
} catch (error) {
console.error("Sign out error:", error);
}
};

return (
<section>
<Navigation_Container
userName={user?.name || "NaN"}
logOut={signOut}
loading={loading}
/>
<Header />
<Call_Table userId={user?.id ?? ""} />
<Footer />
</section>
);
}
and my auth-client.ts
import { adminClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";
import {nextCookies} from "better-auth/next-js";

const CLIENT_SIDE_URL = process.env.NEXT_PUBLIC_CLIENT_SIDE_URL;

export const authClient = createAuthClient({
/** the base url of the server (optional if you're using the same domain) */
baseURL: CLIENT_SIDE_URL,
plugins: [adminClient(), nextCookies()],
});
import { adminClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";
import {nextCookies} from "better-auth/next-js";

const CLIENT_SIDE_URL = process.env.NEXT_PUBLIC_CLIENT_SIDE_URL;

export const authClient = createAuthClient({
/** the base url of the server (optional if you're using the same domain) */
baseURL: CLIENT_SIDE_URL,
plugins: [adminClient(), nextCookies()],
});
daveycodez
daveycodez2w ago
show auth.ts oh nvm i see it above trustedOrigins you probably need more trustedOrigins
sebastian
sebastian2w ago
Cant you use their provided solution for fetching the session on the client-side? Maybe this would be the solution you can export the useSession hook from the client auth
M_Cavus
M_CavusOP2w ago
Then I think it's more of a server-side problem, but I'll give it a try with useSession. Meaning?
daveycodez
daveycodez2w ago
Trusted origins is used for which domains are allowed to get cookies. I’d make sure to double check your error logs for origin issues
Ping
Ping2w ago
He means to set it in the auth config. @M_Cavus trustedOrigins: []
M_Cavus
M_CavusOP2w ago
Yes, I've already configured trustedOrigins here's what I've put
trustedOrigins: [`${CLIENT_SIDE_URL}`],
trustedOrigins: [`${CLIENT_SIDE_URL}`],
hater.js
hater.js2w ago
@M_Cavus am also facing issue of 401, but signin and signup wrks am trying to access backend from server but returns 401, by server mean Nextjs app router use server
M_Cavus
M_CavusOP4d ago
I found this not working because I had not added partitioned: true in defaultCookieAttributes
advanced: {
defaultCookieAttributes:
process.env.NODE_ENV === "production"
? {
sameSite: "none",
secure: true,
httpOnly: true,
partitioned: true, // That
}
: undefined,
},
advanced: {
defaultCookieAttributes:
process.env.NODE_ENV === "production"
? {
sameSite: "none",
secure: true,
httpOnly: true,
partitioned: true, // That
}
: undefined,
},
daveycodez
daveycodez4d ago
Oh interesting I wonder why that is required for you, I haven't had to set that option
Josh
Josh4d ago
Neither

Did you find this page helpful?