[GH-ISSUE #5600] Session is null #10297

Closed
opened 2026-04-13 06:20:05 -05:00 by GiteaMirror · 9 comments
Owner

Originally created by @timothygachengo on GitHub (Oct 26, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/5600

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Login with any sign-in method (email, google, e.t.c) when using expo.
  2. Try and use authClient.getSession()
  3. authClient.getSession() returns null

Current vs. Expected behavior

authClient.getSession() should return the user data.

What version of Better Auth are you using?

1.3.31

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 25.0.0: Wed Sep 17 21:35:32 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T6020",
    "release": "25.0.0",
    "cpuCount": 12,
    "cpuModel": "Apple M2 Pro",
    "totalMemory": "16.00 GB",
    "freeMemory": "0.16 GB"
  },
  "node": {
    "version": "v22.20.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.3"
  },
  "frameworks": [
    {
      "name": "react",
      "version": "19.0.0"
    }
  ],
  "databases": null,
  "betterAuth": {
    "version": "1.3.31",
    "config": null
  }
}

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

Backend, Client

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @timothygachengo on GitHub (Oct 26, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/5600 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Login with any sign-in method (email, google, e.t.c) when using expo. 2. Try and use `authClient.getSession()` 3. `authClient.getSession()` returns `null` ### Current vs. Expected behavior `authClient.getSession()` should return the user data. ### What version of Better Auth are you using? 1.3.31 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 25.0.0: Wed Sep 17 21:35:32 PDT 2025; root:xnu-12377.1.9~141/RELEASE_ARM64_T6020", "release": "25.0.0", "cpuCount": 12, "cpuModel": "Apple M2 Pro", "totalMemory": "16.00 GB", "freeMemory": "0.16 GB" }, "node": { "version": "v22.20.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.3" }, "frameworks": [ { "name": "react", "version": "19.0.0" } ], "databases": null, "betterAuth": { "version": "1.3.31", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Backend, Client ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the lockedbug labels 2026-04-13 06:20:06 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Oct 26, 2025):

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

This is a known issue in Expo environments and is usually caused by session cookie handling or storage bugs. In particular, older versions of the @better-auth/expo client plugin had bugs in cookie expiration logic, causing cookies to expire immediately or be considered invalid, which results in getSession() returning null. This was fixed in @better-auth/expo@1.2.9 and later, so make sure you are using the latest version of both better-auth and @better-auth/expo in your project (details).

For Expo, you should use the expoClient plugin from @better-auth/expo/client and expo-secure-store for secure cookie storage. If you are using SecureStore directly, you need a custom adapter that replaces colons in keys with underscores and uses an in-memory cache for sync access, since SecureStore only allows certain characters in keys and is async by default (adapter example).

Other common causes: if you are using OAuth/social login, make sure your backend trustedOrigins includes your app scheme (e.g., exp://, yourapp://), and that the callback URL is set up correctly. After sign-in, call await authClient.getSession() to force a session refresh—this is a known workaround for session not updating after OAuth login in Expo (workaround).

Finally, enabling session.cookieCache.enabled in your Better Auth config is required for getSession to work as expected in some environments (reference).

If you still see null after these changes, log the deep link URL after sign-in to check for the cookie parameter, and verify that SecureStore contains the session cookie. If the session token is present but still null, check for token expiration, backend config mismatches, and CORS settings allowing credentials (troubleshooting).

To reply, just mention @dosu.


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

<!-- gh-comment-id:3448712350 --> @dosubot[bot] commented on GitHub (Oct 26, 2025): <!-- Greeting --> Hi @timothygachengo! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This is a known issue in Expo environments and is usually caused by session cookie handling or storage bugs. In particular, older versions of the @better-auth/expo client plugin had bugs in cookie expiration logic, causing cookies to expire immediately or be considered invalid, which results in getSession() returning null. This was fixed in @better-auth/expo@1.2.9 and later, so make sure you are using the latest version of both better-auth and @better-auth/expo in your project [(details)](https://github.com/better-auth/better-auth/issues/3180). For Expo, you should use the expoClient plugin from @better-auth/expo/client and expo-secure-store for secure cookie storage. If you are using SecureStore directly, you need a custom adapter that replaces colons in keys with underscores and uses an in-memory cache for sync access, since SecureStore only allows certain characters in keys and is async by default [(adapter example)](https://github.com/better-auth/better-auth/issues/5426). Other common causes: if you are using OAuth/social login, make sure your backend trustedOrigins includes your app scheme (e.g., exp://, yourapp://), and that the callback URL is set up correctly. After sign-in, call await authClient.getSession() to force a session refresh—this is a known workaround for session not updating after OAuth login in Expo [(workaround)](https://github.com/better-auth/better-auth/issues/3711). Finally, enabling session.cookieCache.enabled in your Better Auth config is required for getSession to work as expected in some environments [(reference)](https://github.com/better-auth/better-auth/issues/4942). If you still see null after these changes, log the deep link URL after sign-in to check for the cookie parameter, and verify that SecureStore contains the session cookie. If the session token is present but still null, check for token expiration, backend config mismatches, and CORS settings allowing credentials [(troubleshooting)](https://github.com/better-auth/better-auth/issues/3711). <!-- 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/4d185204-ee8e-4323-ac11-9e3c03cca6fd?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/4d185204-ee8e-4323-ac11-9e3c03cca6fd?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/4d185204-ee8e-4323-ac11-9e3c03cca6fd?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/4d185204-ee8e-4323-ac11-9e3c03cca6fd?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/4d185204-ee8e-4323-ac11-9e3c03cca6fd?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/4d185204-ee8e-4323-ac11-9e3c03cca6fd?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/4d185204-ee8e-4323-ac11-9e3c03cca6fd?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/5600)
Author
Owner

@Mokhtar25 commented on GitHub (Nov 5, 2025):

facing the same issue, workaround to downgrade to 1.3.27

<!-- gh-comment-id:3492146832 --> @Mokhtar25 commented on GitHub (Nov 5, 2025): facing the same issue, workaround to downgrade to 1.3.27
Author
Owner

@lucasoliveirabr commented on GitHub (Nov 5, 2025):

I'm facing the same issue and downgrading back to v.1.3.27 is really a workaround for now. Thanks @Mokhtar25.

<!-- gh-comment-id:3492517382 --> @lucasoliveirabr commented on GitHub (Nov 5, 2025): I'm facing the same issue and downgrading back to v.1.3.27 is really a workaround for now. Thanks @Mokhtar25.
Author
Owner

@Mokhtar25 commented on GitHub (Nov 5, 2025):

after some further investigating, turns out that they added cookiePrefix on the client in that update. so if the prefix missmatch on the client and the server you get that error. what to do is to make sure the cookie prefix is the same on client and server after that update.

<!-- gh-comment-id:3492669895 --> @Mokhtar25 commented on GitHub (Nov 5, 2025): after some further investigating, turns out that they added cookiePrefix on the client in that update. so if the prefix missmatch on the client and the server you get that error. what to do is to make sure the cookie prefix is the same on client and server after that update.
Author
Owner

@lucasoliveirabr commented on GitHub (Nov 5, 2025):

Adding the cookiePrefix to expoClient in authClient solved the issue.
Thanks again @Mokhtar25!

<!-- gh-comment-id:3492747932 --> @lucasoliveirabr commented on GitHub (Nov 5, 2025): Adding the cookiePrefix to expoClient in authClient solved the issue. Thanks again @Mokhtar25!
Author
Owner

@ping-maxwell commented on GitHub (Jan 8, 2026):

Hello we're now on Better Auth 1.4.10, lots have changed since including bug fixes that potentially have solved some of your issues regarding this. I'm going to mark this as resolved for now, please open a new issue describing your specific situation if you're facing something similar. This will also help reduce the number of users related to this thread given the broad issue title, these situations tend to be very specific with cause, so new issues per case makes sense.

<!-- gh-comment-id:3724173831 --> @ping-maxwell commented on GitHub (Jan 8, 2026): Hello we're now on Better Auth 1.4.10, lots have changed since including bug fixes that potentially have solved some of your issues regarding this. I'm going to mark this as resolved for now, please open a new issue describing your specific situation if you're facing something similar. This will also help reduce the number of users related to this thread given the broad issue title, these situations tend to be very specific with cause, so new issues per case makes sense.
Author
Owner

@danieltorscho commented on GitHub (Feb 13, 2026):

problem still persists on v1.4.18

<!-- gh-comment-id:3898352151 --> @danieltorscho commented on GitHub (Feb 13, 2026): problem still persists on v1.4.18
Author
Owner

@danieltorscho commented on GitHub (Feb 14, 2026):

For anyone having the same issue - Apple's Intelligent Tracking Prevention (ITP) in Safari is a privacy feature that blocks third-party cookies.
In my case, I had a server API on domainA.com and client app on domainB.com. ITP blocks in that case. A solution for this issue is by tricking to act domainA as a first-party api by Proxying the requests to the domainA via domainB.com/api
As my client app is hosted on netlify, all I had to do is to set a proxy in a netlify config file netlify.toml like so:

[[redirects]]
  from = "/api/*"
  to = "https://domainA.com/v1/:splat"
  status = 200
  force = true

@ping-maxwell - it would be useful if you mention that somewhere in documentation (https://www.better-auth.com/docs/concepts/client)

<!-- gh-comment-id:3902121967 --> @danieltorscho commented on GitHub (Feb 14, 2026): For anyone having the same issue - Apple's Intelligent Tracking Prevention (ITP) in Safari is a privacy feature that blocks third-party cookies. In my case, I had a server API on domainA.com and client app on domainB.com. ITP blocks in that case. A solution for this issue is by tricking to act domainA as a first-party api by Proxying the requests to the domainA via domainB.com/api As my client app is hosted on netlify, all I had to do is to set a proxy in a netlify config file `netlify.toml` like so: ``` [[redirects]] from = "/api/*" to = "https://domainA.com/v1/:splat" status = 200 force = true ``` @ping-maxwell - it would be useful if you mention that somewhere in documentation (https://www.better-auth.com/docs/concepts/client)
Author
Owner

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

For anyone having the same issue - Apple's Intelligent Tracking Prevention (ITP) in Safari is a privacy feature that blocks third-party cookies. In my case, I had a server API on domainA.com and client app on domainB.com. ITP blocks in that case. A solution for this issue is by tricking to act domainA as a first-party api by Proxying the requests to the domainA via domainB.com/api As my client app is hosted on netlify, all I had to do is to set a proxy in a netlify config file netlify.toml like so:

[[redirects]]
  from = "/api/*"
  to = "https://domainA.com/v1/:splat"
  status = 200
  force = true

@ping-maxwell - it would be useful if you mention that somewhere in documentation (better-auth.com/docs/concepts/client)

Thanks for the feedback, I'll update the docs.

<!-- gh-comment-id:3903848954 --> @ping-maxwell commented on GitHub (Feb 15, 2026): > For anyone having the same issue - Apple's Intelligent Tracking Prevention (ITP) in Safari is a privacy feature that blocks third-party cookies. In my case, I had a server API on domainA.com and client app on domainB.com. ITP blocks in that case. A solution for this issue is by tricking to act domainA as a first-party api by Proxying the requests to the domainA via domainB.com/api As my client app is hosted on netlify, all I had to do is to set a proxy in a netlify config file `netlify.toml` like so: > > ``` > [[redirects]] > from = "/api/*" > to = "https://domainA.com/v1/:splat" > status = 200 > force = true > ``` > > [@ping-maxwell](https://github.com/ping-maxwell) - it would be useful if you mention that somewhere in documentation ([better-auth.com/docs/concepts/client](https://www.better-auth.com/docs/concepts/client)) Thanks for the feedback, I'll update the docs.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10297