[GH-ISSUE #3470] Session is null when using diffrent frontend and backend #9616

Closed
opened 2026-04-13 05:10:38 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @1sma31L on GitHub (Jul 19, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/3470

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. create a frontend using nextjs and react-query
  2. create a backend (with hono)
  3. set up cors
app.use(
	"/*",
	cors({
		origin: "https://test-better-auth-with-hono-web.vercel.app", // hard coded to eliminate env cause
		allowMethods: ["GET", "POST", "OPTIONS"],
		allowHeaders: ["Content-Type", "Authorization"],
		credentials: true,
	})
);

  1. i sign up using email provider, it shows success
  2. the cookie is returned the first time / tho session is null
  3. refresh makes the cookie disappear and then obv the session is null

headers in this the sign in phase

preflight: 

Request URL
https://test-better-auth-with-hono-web-vocr.vercel.app/api/auth/sign-in/email
Request Method
OPTIONS
Status Code
204 No Content
Remote Address
216.198.79.3:443
Referrer Policy
strict-origin-when-cross-origin
access-control-allow-credentials
true
access-control-allow-headers
Content-Type,Authorization
access-control-allow-methods
GET,POST,OPTIONS
access-control-allow-origin
https://test-better-auth-with-hono-web.vercel.app
cache-control
public, max-age=0, must-revalidate
date
Sat, 19 Jul 2025 16:58:56 GMT
server
Vercel
strict-transport-security
max-age=63072000; includeSubDomains; preload
vary
Origin, Access-Control-Request-Headers
x-vercel-cache
MISS
x-vercel-id
cdg1::iad1::jdkvn-1752944335855-14d23e111548
:authority
test-better-auth-with-hono-web-vocr.vercel.app
:method
OPTIONS
:path
/api/auth/sign-in/email
:scheme
https
accept
*/*
accept-encoding
gzip, deflate, br, zstd
accept-language
fr,en;q=0.9,ar;q=0.8
access-control-request-headers
content-type
access-control-request-method
POST
cache-control
no-cache
origin
https://test-better-auth-with-hono-web.vercel.app
pragma
no-cache
priority
u=1, i
referer
https://test-better-auth-with-hono-web.vercel.app/
sec-fetch-dest
empty
sec-fetch-mode
cors
sec-fetch-site
cross-site
user-agent
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36
fetch 
access-control-allow-credentials
true
access-control-allow-origin
https://test-better-auth-with-hono-web.vercel.app
cache-control
public, max-age=0, must-revalidate
content-encoding
br
content-type
application/json
date
Sat, 19 Jul 2025 16:58:57 GMT
server
Vercel
set-cookie
__Secure-better-auth.session_token=1HWenloOW2NORtxT1LFVRb8VSrNLCN0b.uPb6%2B7fZ5k1eozt4wkIoVQS24uT%2BI2sjuKMbIpbpDgQ%3D; Max-Age=604800; Path=/; HttpOnly; Secure; SameSite=Lax
strict-transport-security
max-age=63072000; includeSubDomains; preload
vary
Origin
x-vercel-cache
MISS
x-vercel-id
cdg1::iad1::5mgmj-1752944336167-0bec46f7ba65
:authority
test-better-auth-with-hono-web-vocr.vercel.app
:method
POST
:path
/api/auth/sign-in/email
:scheme
https
accept
*/*
accept-encoding
gzip, deflate, br, zstd
accept-language
fr;q=0.7
cache-control
no-cache
content-length
50
content-type
application/json
origin
https://test-better-auth-with-hono-web.vercel.app
pragma
no-cache
priority
u=1, i
referer
https://test-better-auth-with-hono-web.vercel.app/
sec-ch-ua
"Not)A;Brand";v="8", "Chromium";v="138", "Brave";v="138"
sec-ch-ua-mobile
?0
sec-ch-ua-platform
"Linux"
sec-fetch-dest
empty
sec-fetch-mode
cors
sec-fetch-site
cross-site
sec-fetch-storage-access
none
sec-gpc
1
user-agent
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36
get session 
Request URL
https://test-better-auth-with-hono-web-vocr.vercel.app/api/auth/get-session
Request Method
GET
Status Code
200 OK
Remote Address
64.29.17.3:443
Referrer Policy
strict-origin-when-cross-origin
access-control-allow-credentials
true
access-control-allow-origin
https://test-better-auth-with-hono-web.vercel.app
age
0
cache-control
public, max-age=0, must-revalidate
content-encoding
br
content-type
application/json
date
Sat, 19 Jul 2025 16:58:58 GMT
server
Vercel
strict-transport-security
max-age=63072000; includeSubDomains; preload
vary
Origin
x-vercel-cache
MISS
x-vercel-id
cdg1::iad1::5mgmj-1752944338126-8786fc070440
:authority
test-better-auth-with-hono-web-vocr.vercel.app
:method
GET
:path
/api/auth/get-session
:scheme
https
accept
*/*
accept-encoding
gzip, deflate, br, zstd
accept-language
fr;q=0.7
cache-control
no-cache
origin
https://test-better-auth-with-hono-web.vercel.app
pragma
no-cache
priority
u=1, i
referer
https://test-better-auth-with-hono-web.vercel.app/
sec-ch-ua
"Not)A;Brand";v="8", "Chromium";v="138", "Brave";v="138"
sec-ch-ua-mobile
?0
sec-ch-ua-platform
"Linux"
sec-fetch-dest
empty
sec-fetch-mode
cors
sec-fetch-site
cross-site
sec-fetch-storage-access
none
sec-gpc
1
user-agent
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36

Now there is a cookie but when fetching another path i get

Request URL
https://test-better-auth-with-hono-web-vocr.vercel.app/api/auth/get-session
Request Method
GET
Status Code
200 OK
Remote Address
64.29.17.3:443
Referrer Policy
strict-origin-when-cross-origin
access-control-allow-credentials
true
access-control-allow-origin
https://test-better-auth-with-hono-web.vercel.app
age
0
cache-control
public, max-age=0, must-revalidate
content-encoding
br
content-type
application/json
date
Sat, 19 Jul 2025 17:01:27 GMT
server
Vercel
strict-transport-security
max-age=63072000; includeSubDomains; preload
vary
Origin
x-vercel-cache
MISS
x-vercel-id
cdg1::iad1::bxfh5-1752944487041-8145c610bcb5
:authority
test-better-auth-with-hono-web-vocr.vercel.app
:method
GET
:path
/api/auth/get-session
:scheme
https
accept
*/*
accept-encoding
gzip, deflate, br, zstd
accept-language
fr;q=0.7
cache-control
no-cache
origin
https://test-better-auth-with-hono-web.vercel.app
pragma
no-cache
priority
u=1, i
referer
https://test-better-auth-with-hono-web.vercel.app/
sec-ch-ua
"Not)A;Brand";v="8", "Chromium";v="138", "Brave";v="138"
sec-ch-ua-mobile
?0
sec-ch-ua-platform
"Linux"
sec-fetch-dest
empty
sec-fetch-mode
cors
sec-fetch-site
cross-site
sec-fetch-storage-access
none
sec-gpc
1
user-agent
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36

with cookie deleted

Current vs. Expected behavior

Current: session is null and cookie deleted
Expected: session is fetched after successful login and cookie preserved

What version of Better Auth are you using?

1.2.12

Provide environment information

- OS: Arch linux
- Browser: Brave

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

export const auth = betterAuth({
	database: drizzleAdapter(db, {
		provider: "pg",

		schema: schema,
	}),
	trustedOrigins: [process.env.CORS_ORIGIN || ""],
	emailAndPassword: {
		enabled: true,
	},

	secret: process.env.BETTER_AUTH_SECRET,
	baseURL: process.env.BETTER_AUTH_URL,
});

export const authClient = createAuthClient({
	baseURL: process.env.NEXT_PUBLIC_SERVER_URL,
});

Additional context

No response

Originally created by @1sma31L on GitHub (Jul 19, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/3470 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. create a frontend using nextjs and react-query 2. create a backend (with hono) 3. set up cors ```ts app.use( "/*", cors({ origin: "https://test-better-auth-with-hono-web.vercel.app", // hard coded to eliminate env cause allowMethods: ["GET", "POST", "OPTIONS"], allowHeaders: ["Content-Type", "Authorization"], credentials: true, }) ); ``` 4. i sign up using email provider, it shows success 5. the cookie is returned the first time / tho session is null 6. refresh makes the cookie disappear and then obv the session is null headers in this the sign in phase ``` preflight: Request URL https://test-better-auth-with-hono-web-vocr.vercel.app/api/auth/sign-in/email Request Method OPTIONS Status Code 204 No Content Remote Address 216.198.79.3:443 Referrer Policy strict-origin-when-cross-origin access-control-allow-credentials true access-control-allow-headers Content-Type,Authorization access-control-allow-methods GET,POST,OPTIONS access-control-allow-origin https://test-better-auth-with-hono-web.vercel.app cache-control public, max-age=0, must-revalidate date Sat, 19 Jul 2025 16:58:56 GMT server Vercel strict-transport-security max-age=63072000; includeSubDomains; preload vary Origin, Access-Control-Request-Headers x-vercel-cache MISS x-vercel-id cdg1::iad1::jdkvn-1752944335855-14d23e111548 :authority test-better-auth-with-hono-web-vocr.vercel.app :method OPTIONS :path /api/auth/sign-in/email :scheme https accept */* accept-encoding gzip, deflate, br, zstd accept-language fr,en;q=0.9,ar;q=0.8 access-control-request-headers content-type access-control-request-method POST cache-control no-cache origin https://test-better-auth-with-hono-web.vercel.app pragma no-cache priority u=1, i referer https://test-better-auth-with-hono-web.vercel.app/ sec-fetch-dest empty sec-fetch-mode cors sec-fetch-site cross-site user-agent Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 ``` ``` fetch access-control-allow-credentials true access-control-allow-origin https://test-better-auth-with-hono-web.vercel.app cache-control public, max-age=0, must-revalidate content-encoding br content-type application/json date Sat, 19 Jul 2025 16:58:57 GMT server Vercel set-cookie __Secure-better-auth.session_token=1HWenloOW2NORtxT1LFVRb8VSrNLCN0b.uPb6%2B7fZ5k1eozt4wkIoVQS24uT%2BI2sjuKMbIpbpDgQ%3D; Max-Age=604800; Path=/; HttpOnly; Secure; SameSite=Lax strict-transport-security max-age=63072000; includeSubDomains; preload vary Origin x-vercel-cache MISS x-vercel-id cdg1::iad1::5mgmj-1752944336167-0bec46f7ba65 :authority test-better-auth-with-hono-web-vocr.vercel.app :method POST :path /api/auth/sign-in/email :scheme https accept */* accept-encoding gzip, deflate, br, zstd accept-language fr;q=0.7 cache-control no-cache content-length 50 content-type application/json origin https://test-better-auth-with-hono-web.vercel.app pragma no-cache priority u=1, i referer https://test-better-auth-with-hono-web.vercel.app/ sec-ch-ua "Not)A;Brand";v="8", "Chromium";v="138", "Brave";v="138" sec-ch-ua-mobile ?0 sec-ch-ua-platform "Linux" sec-fetch-dest empty sec-fetch-mode cors sec-fetch-site cross-site sec-fetch-storage-access none sec-gpc 1 user-agent Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 ``` ``` get session Request URL https://test-better-auth-with-hono-web-vocr.vercel.app/api/auth/get-session Request Method GET Status Code 200 OK Remote Address 64.29.17.3:443 Referrer Policy strict-origin-when-cross-origin access-control-allow-credentials true access-control-allow-origin https://test-better-auth-with-hono-web.vercel.app age 0 cache-control public, max-age=0, must-revalidate content-encoding br content-type application/json date Sat, 19 Jul 2025 16:58:58 GMT server Vercel strict-transport-security max-age=63072000; includeSubDomains; preload vary Origin x-vercel-cache MISS x-vercel-id cdg1::iad1::5mgmj-1752944338126-8786fc070440 :authority test-better-auth-with-hono-web-vocr.vercel.app :method GET :path /api/auth/get-session :scheme https accept */* accept-encoding gzip, deflate, br, zstd accept-language fr;q=0.7 cache-control no-cache origin https://test-better-auth-with-hono-web.vercel.app pragma no-cache priority u=1, i referer https://test-better-auth-with-hono-web.vercel.app/ sec-ch-ua "Not)A;Brand";v="8", "Chromium";v="138", "Brave";v="138" sec-ch-ua-mobile ?0 sec-ch-ua-platform "Linux" sec-fetch-dest empty sec-fetch-mode cors sec-fetch-site cross-site sec-fetch-storage-access none sec-gpc 1 user-agent Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 ``` Now there is a cookie but when fetching another path i get ``` Request URL https://test-better-auth-with-hono-web-vocr.vercel.app/api/auth/get-session Request Method GET Status Code 200 OK Remote Address 64.29.17.3:443 Referrer Policy strict-origin-when-cross-origin access-control-allow-credentials true access-control-allow-origin https://test-better-auth-with-hono-web.vercel.app age 0 cache-control public, max-age=0, must-revalidate content-encoding br content-type application/json date Sat, 19 Jul 2025 17:01:27 GMT server Vercel strict-transport-security max-age=63072000; includeSubDomains; preload vary Origin x-vercel-cache MISS x-vercel-id cdg1::iad1::bxfh5-1752944487041-8145c610bcb5 :authority test-better-auth-with-hono-web-vocr.vercel.app :method GET :path /api/auth/get-session :scheme https accept */* accept-encoding gzip, deflate, br, zstd accept-language fr;q=0.7 cache-control no-cache origin https://test-better-auth-with-hono-web.vercel.app pragma no-cache priority u=1, i referer https://test-better-auth-with-hono-web.vercel.app/ sec-ch-ua "Not)A;Brand";v="8", "Chromium";v="138", "Brave";v="138" sec-ch-ua-mobile ?0 sec-ch-ua-platform "Linux" sec-fetch-dest empty sec-fetch-mode cors sec-fetch-site cross-site sec-fetch-storage-access none sec-gpc 1 user-agent Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 ``` with cookie deleted ### Current vs. Expected behavior Current: session is null and cookie deleted Expected: session is fetched after successful login and cookie preserved ### What version of Better Auth are you using? 1.2.12 ### Provide environment information ```bash - OS: Arch linux - Browser: Brave ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript export const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg", schema: schema, }), trustedOrigins: [process.env.CORS_ORIGIN || ""], emailAndPassword: { enabled: true, }, secret: process.env.BETTER_AUTH_SECRET, baseURL: process.env.BETTER_AUTH_URL, }); export const authClient = createAuthClient({ baseURL: process.env.NEXT_PUBLIC_SERVER_URL, }); ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-13 05:10:38 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jul 19, 2025):

The root cause is that Better Auth sets cookies with SameSite=Lax by default, which browsers block in cross-origin scenarios. For your setup (different frontend and backend domains), you need to set the session cookie to SameSite=None and Secure=true so browsers will accept and send it on cross-origin requests ref.

Update your Better Auth backend config to override the cookie attributes like this:

export const auth = betterAuth({
  // ...your existing config
  advanced: {
    defaultCookieAttributes: {
      sameSite: "none",
      secure: true,
      httpOnly: true,
    },
  },
});

Or, for more granular control, set it just for the session token:

export const auth = betterAuth({
  // ...your existing config
  advanced: {
    cookies: {
      session_token: {
        attributes: {
          sameSite: "none",
          secure: true,
          httpOnly: true,
        },
      },
    },
  },
});

Make sure your frontend fetches use credentials: 'include' and that your CORS config allows credentials and matches the frontend origin exactly ref.

If you’re still seeing issues, try testing in Chrome or Edge to rule out Brave-specific behavior, and avoid using public suffix domains (like vercel.app) for production—use custom domains for both frontend and backend ref.

If the session is still null and the cookie is deleted, double-check for any mismatches in cookie expiration or signature, as there was a recent fix for this in Better Auth ref.

To reply, just mention @dosu.


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

<!-- gh-comment-id:3092460530 --> @dosubot[bot] commented on GitHub (Jul 19, 2025): <!-- Answer --> The root cause is that Better Auth sets cookies with `SameSite=Lax` by default, which browsers block in cross-origin scenarios. For your setup (different frontend and backend domains), you need to set the session cookie to `SameSite=None` and `Secure=true` so browsers will accept and send it on cross-origin requests [ref](https://github.com/better-auth/better-auth/discussions/2826). Update your Better Auth backend config to override the cookie attributes like this: ```ts export const auth = betterAuth({ // ...your existing config advanced: { defaultCookieAttributes: { sameSite: "none", secure: true, httpOnly: true, }, }, }); ``` Or, for more granular control, set it just for the session token: ```ts export const auth = betterAuth({ // ...your existing config advanced: { cookies: { session_token: { attributes: { sameSite: "none", secure: true, httpOnly: true, }, }, }, }, }); ``` Make sure your frontend fetches use `credentials: 'include'` and that your CORS config allows credentials and matches the frontend origin exactly [ref](https://github.com/better-auth/better-auth/issues/3180). If you’re still seeing issues, try testing in Chrome or Edge to rule out Brave-specific behavior, and avoid using public suffix domains (like vercel.app) for production—use custom domains for both frontend and backend [ref](https://github.com/better-auth/better-auth/discussions/3262). If the session is still null and the cookie is deleted, double-check for any mismatches in cookie expiration or signature, as there was a recent fix for this in Better Auth [ref](https://github.com/better-auth/better-auth/pull/3283). <!-- 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/c1583bf4-8f7b-41c3-8e89-73bc2f059a63?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/c1583bf4-8f7b-41c3-8e89-73bc2f059a63?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/c1583bf4-8f7b-41c3-8e89-73bc2f059a63?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/c1583bf4-8f7b-41c3-8e89-73bc2f059a63?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/c1583bf4-8f7b-41c3-8e89-73bc2f059a63?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/c1583bf4-8f7b-41c3-8e89-73bc2f059a63?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/c1583bf4-8f7b-41c3-8e89-73bc2f059a63?feedback_type=other)</sup>&nbsp;&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/3470)
Author
Owner

@1sma31L commented on GitHub (Jul 19, 2025):

OMGGGG THANK YOU SO MUCH:

export const auth = betterAuth({
	advanced: {
		defaultCookieAttributes: {
			sameSite: "none",
			secure: true,
			httpOnly: true,
		},
	},
});

Adding this fixed it, Thank you.

<!-- gh-comment-id:3092471311 --> @1sma31L commented on GitHub (Jul 19, 2025): OMGGGG THANK YOU SO MUCH: ```ts export const auth = betterAuth({ advanced: { defaultCookieAttributes: { sameSite: "none", secure: true, httpOnly: true, }, }, }); ``` Adding this fixed it, Thank you.
Author
Owner

@yk-sgr commented on GitHub (Aug 25, 2025):

Adding some information for future reference:

I had the same issue that the session was null in localhost.

I'm using Tanstack Router and Hono backend.

  advanced: {
    defaultCookieAttributes: {
      sameSite: "none",
      secure: true,
      httpOnly: true,
    },
  },

is working completely fine in Chrome, but not in Safari.

Safari doesnt treat localhost as "secure".
Setting secure: false in dev worked for me.

<!-- gh-comment-id:3219082753 --> @yk-sgr commented on GitHub (Aug 25, 2025): Adding some information for future reference: I had the same issue that the session was null in localhost. I'm using Tanstack Router and Hono backend. ``` advanced: { defaultCookieAttributes: { sameSite: "none", secure: true, httpOnly: true, }, }, ``` is working completely fine in Chrome, but not in Safari. Safari doesnt treat localhost as "secure". Setting `secure: false` in dev worked for me.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#9616