auth.api.getSession returns null in Next.js server components #1770

Closed
opened 2026-03-13 09:02:04 -05:00 by GiteaMirror · 10 comments
Owner

Originally created by @iatomic1 on GitHub (Aug 24, 2025).

Originally assigned to: @himself65 on GitHub.

I’m using Better Auth with a Hono backend and a Next.js frontend.

  • Backend (Hono, port 3000):
    Configured betterAuth with Drizzle adapter, Postgres, and cookie settings. Exported the auth object through package.json exports.

    import { betterAuth } from "better-auth";
    import { drizzleAdapter } from "better-auth/adapters/drizzle";
    import { db } from "../db";
    import * as schema from "../db/schema/auth";
    
    export const auth = betterAuth({
      database: drizzleAdapter(db, {
        provider: "pg",
        schema: schema,
      }),
      trustedOrigins: [process.env.CORS_ORIGIN || ""],
      emailAndPassword: {
        enabled: true,
      },
      advanced: {
        defaultCookieAttributes: {
          sameSite: "none",
          secure: true,
          httpOnly: true,
        },
      },
    });
    
  • Frontend (Next.js, port 3001):
    I import the auth object from the backend.

    In a server component:

    const session = await auth.api.getSession({ headers: await headers() });
    

    This always returns null.

    However, in a client component, using authClient.useSession, the session works fine.

Problem:
auth.api.getSession does not work in server components, even when passing headers().

Expected behavior:
Calling auth.api.getSession in a server component should return the active session, just like authClient.useSession does in client components.

Environment:

  • Backend: Hono + Better Auth
  • Frontend: Next.js (App Router)
  • Auth transport: cookies
  • Ports: backend 3000, frontend 3001

Originally created by @iatomic1 on GitHub (Aug 24, 2025). Originally assigned to: @himself65 on GitHub. I’m using **Better Auth** with a Hono backend and a Next.js frontend. * **Backend (Hono, port 3000):** Configured `betterAuth` with Drizzle adapter, Postgres, and cookie settings. Exported the `auth` object through `package.json` exports. ```ts import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { db } from "../db"; import * as schema from "../db/schema/auth"; export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg", schema: schema, }), trustedOrigins: [process.env.CORS_ORIGIN || ""], emailAndPassword: { enabled: true, }, advanced: { defaultCookieAttributes: { sameSite: "none", secure: true, httpOnly: true, }, }, }); ``` * **Frontend (Next.js, port 3001):** I import the `auth` object from the backend. In a server component: ```ts const session = await auth.api.getSession({ headers: await headers() }); ``` This always returns `null`. However, in a client component, using `authClient.useSession`, the session works fine. **Problem:** `auth.api.getSession` does not work in server components, even when passing `headers()`. **Expected behavior:** Calling `auth.api.getSession` in a server component should return the active session, just like `authClient.useSession` does in client components. **Environment:** * Backend: Hono + Better Auth * Frontend: Next.js (App Router) * Auth transport: cookies * Ports: backend 3000, frontend 3001 ---
GiteaMirror added the nextjshono labels 2026-03-13 09:02:04 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Aug 24, 2025):

Hi @iatomic1! I'm Dosu and I’m helping the better-auth team.

This happens because Next.js server components run on the server and don’t have automatic access to browser cookies. When you call auth.api.getSession in a server component, the headers you pass (from headers()) often don’t include the user’s session cookie, especially in cross-origin setups (frontend on 3001, backend on 3000). As a result, Better Auth can’t find the session token and returns null see docs.

To fix this, you need to forward the cookie header from the browser to your auth backend. The recommended pattern is to create a custom server action or proxy API route in Next.js that fetches the session from your auth server, explicitly passing the cookie header see example:

import { cookies } from 'next/headers';

export async function getServerSession() {
  const cookieHeader = cookies().toString();
  const res = await fetch(`${process.env.AUTH_API_URL}/get-session`, {
    headers: { Cookie: cookieHeader },
    credentials: 'include',
  });
  if (!res.ok) return null;
  return await res.json();
}

Also, make sure your cookie settings use sameSite: "none" and secure: true for cross-origin requests see config fix.

Recent Better Auth updates have fixed bugs with cookie parsing and session context, so make sure you’re on the latest version see PRs.

In summary: proxy session requests through Next.js API routes or server actions, forward cookies explicitly, and check your cookie config for cross-origin compatibility. This will let you reliably access the session in server components.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Aug 24, 2025): <!-- Greeting --> Hi @iatomic1! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This happens because Next.js server components run on the server and don’t have automatic access to browser cookies. When you call `auth.api.getSession` in a server component, the headers you pass (from `headers()`) often don’t include the user’s session cookie, especially in cross-origin setups (frontend on 3001, backend on 3000). As a result, Better Auth can’t find the session token and returns `null` [see docs](https://better-auth.com/docs/concepts/session-management). To fix this, you need to forward the cookie header from the browser to your auth backend. The recommended pattern is to create a custom server action or proxy API route in Next.js that fetches the session from your auth server, explicitly passing the cookie header [see example](https://github.com/better-auth/better-auth/issues/4044): ```ts import { cookies } from 'next/headers'; export async function getServerSession() { const cookieHeader = cookies().toString(); const res = await fetch(`${process.env.AUTH_API_URL}/get-session`, { headers: { Cookie: cookieHeader }, credentials: 'include', }); if (!res.ok) return null; return await res.json(); } ``` Also, make sure your cookie settings use `sameSite: "none"` and `secure: true` for cross-origin requests [see config fix](https://github.com/better-auth/better-auth/issues/3470). Recent Better Auth updates have fixed bugs with cookie parsing and session context, so make sure you’re on the latest version [see PRs](https://github.com/better-auth/better-auth/pull/3909). In summary: proxy session requests through Next.js API routes or server actions, forward cookies explicitly, and check your cookie config for cross-origin compatibility. This will let you reliably access the session in server components. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/c420f7b4-afd6-4210-891b-faa9f6198068?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/c420f7b4-afd6-4210-891b-faa9f6198068?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/c420f7b4-afd6-4210-891b-faa9f6198068?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/c420f7b4-afd6-4210-891b-faa9f6198068?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/c420f7b4-afd6-4210-891b-faa9f6198068?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/c420f7b4-afd6-4210-891b-faa9f6198068?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/c420f7b4-afd6-4210-891b-faa9f6198068?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4188)
Author
Owner

@himself65 commented on GitHub (Aug 26, 2025):

I've encountered this issue before. and I'm pretty sure because of different domain issue

@himself65 commented on GitHub (Aug 26, 2025): I've encountered this issue before. and I'm pretty sure because of different domain issue
Author
Owner

@ArifAA14 commented on GitHub (Aug 27, 2025):

I had the same issue; you cannot simply use the following if your Better-Auth server is not within your nextjs app.

const session = await auth.api.getSession({ headers: await headers() });

https://github.com/better-auth/better-auth/issues/4044

Have a look at the issue here, I posted the solution for my use case, I think yours is pretty similar.

@ArifAA14 commented on GitHub (Aug 27, 2025): I had the same issue; you cannot simply use the following if your Better-Auth server is not within your nextjs app. `const session = await auth.api.getSession({ headers: await headers() }); ` https://github.com/better-auth/better-auth/issues/4044 Have a look at the issue here, I posted the solution for my use case, I think yours is pretty similar.
Author
Owner

@ping-maxwell commented on GitHub (Oct 8, 2025):

I assume this is a monorepo project, I wonder if it has something to do with the import from backend to the nextjs app and then using the auth.api. 🤔

@ping-maxwell commented on GitHub (Oct 8, 2025): I assume this is a monorepo project, I wonder if it has something to do with the import from backend to the nextjs app and then using the `auth.api`. 🤔
Author
Owner

@alimehasin commented on GitHub (Nov 6, 2025):

Take a look at crossSubDomainCookies configs option

advanced: {
  crossSubDomainCookies: {
    enabled: true,
    domain: 'example.com',
  },
},

Resources

https://www.better-auth.com/docs/reference/options#advanced
https://www.better-auth.com/docs/reference/security#cookies
https://www.better-auth.com/docs/concepts/cookies#cross-subdomain-cookies

@alimehasin commented on GitHub (Nov 6, 2025): Take a look at `crossSubDomainCookies` configs option ```ts advanced: { crossSubDomainCookies: { enabled: true, domain: 'example.com', }, }, ``` ### Resources https://www.better-auth.com/docs/reference/options#advanced https://www.better-auth.com/docs/reference/security#cookies https://www.better-auth.com/docs/concepts/cookies#cross-subdomain-cookies
Author
Owner

@mitesh9991 commented on GitHub (Dec 29, 2025):

@iatomic1 found something related to this??

@mitesh9991 commented on GitHub (Dec 29, 2025): @iatomic1 found something related to this??
Author
Owner

@jeevenmotion commented on GitHub (Jan 29, 2026):

@himself65 Any update on this?

@jeevenmotion commented on GitHub (Jan 29, 2026): @himself65 Any update on this?
Author
Owner

@abdtriedcoding commented on GitHub (Feb 7, 2026):

Getting same error, session as null in server components. Any update on this?

@abdtriedcoding commented on GitHub (Feb 7, 2026): Getting same error, session as null in server components. Any update on this?
Author
Owner

@ping-maxwell commented on GitHub (Feb 10, 2026):

Assuming there is valid session headers then the session should return correctly.

If everyone here can console.log the header values and check if the session cookie exists and let me know that would be great!

cc @abdtriedcoding @jeevenmotion @mitesh9991 @iatomic1

@ping-maxwell commented on GitHub (Feb 10, 2026): Assuming there is valid session headers then the session should return correctly. If everyone here can console.log the header values and check if the session cookie exists and let me know that would be great! cc @abdtriedcoding @jeevenmotion @mitesh9991 @iatomic1
Author
Owner

@himself65 commented on GitHub (Feb 10, 2026):

I would say this is a cross-domain issue. Please set your cookie domian correctly, see https://github.com/better-auth/better-auth/issues/4188#issuecomment-3496476832

@himself65 commented on GitHub (Feb 10, 2026): I would say this is a cross-domain issue. Please set your cookie domian correctly, see https://github.com/better-auth/better-auth/issues/4188#issuecomment-3496476832
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1770