[Bug] Expo Client Session Remains Null After Google Social Sign-In #1607

Closed
opened 2026-03-13 08:51:09 -05:00 by GiteaMirror · 7 comments
Owner

Originally created by @ayhamDev on GitHub (Jul 31, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create a Hono backend using Bun and configure better-auth with the MongoDB adapter and Google social provider as specified in the server-side code below.
  2. Create an Expo frontend and configure the authClient using @better-auth/react and the @better-auth/expo/client plugin, ensuring expo-secure-store is integrated.
  3. Implement a login screen with a button that triggers the authClient.signIn.social({ provider: "google", callbackURL: "/" }) function.
  4. Run the application, press the "Sign In With Google" button, and complete the authentication flow in the browser that opens.
  5. After successful authentication, the app correctly re-opens via the deep link (waain://).
  6. Observe that the session object, logged via useEffect listening to authClient.useSession(), remains null.

Current vs. Expected behavior

Current Behavior:
Following a successful Google sign-in and redirect back to the Expo app, the authClient.useSession() hook does not update. The session variable remains null, and session.isLoggedIn is false. The user is not recognized as authenticated on the client side, even though the authentication process completes without visible errors and the app is reopened.

Expected Behavior:
After the redirect from the Google sign-in flow, the @better-auth/expo/client plugin should handle the callback, securely store the session token, and update the state. The authClient.useSession() hook should then return a valid session object containing the user's data, and session.isLoggedIn should be true.

What version of Better Auth are you using?

1.3.4

Provide environment information

**Provide environment information**
-   **OS:** Backend: [Windows 11], Client: [Android 13]
-   **Browser:** In-App Browser used by Expo for authentication flow.
-   **Runtime:** Bun (backend), Expo Go / Development Build (client)

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

Backend, Client

Auth config (if applicable)

### **Auth config (if applicable)**

**Client-Side Config (`/lib/auth-client.ts`)**

import { expoClient } from "@better-auth/expo/client";
import { createAuthClient } from "better-auth/react";
import * as SecureStore from "expo-secure-store";

export const authClient = createAuthClient({
  baseURL: "http://192.168.8.113:3000", // Base URL of your Better Auth backend.
  plugins: [
    expoClient({
      scheme: "waain",
      storagePrefix: "waain-auth",
      storage: SecureStore,
    }),
  ],
});


**Server-Side Config (`/api/lib/auth.ts`)**

import { betterAuth } from "better-auth";
import { mongodbAdapter } from "better-auth/adapters/mongodb";
import { MongoClient } from "mongodb";

const client = new MongoClient(process.env.MONGO_URI as string);
const db = client.db();

export const auth = betterAuth({
  // @ts-ignore
  database: mongodbAdapter(db),
  trustedOrigins: ["*"], // Using wildcard for testing
  socialProviders: {
    google: {
      prompt: "select_account",
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    },
  },
});

Additional context

Additional context

The issue appears to be specific to the handling of the authentication callback within the Expo client environment. The deep linking itself functions correctly, as the app is reopened post-authentication. However, the session data is not being successfully captured or propagated to the React context. Manually calling session.refetch() after the redirect has no effect. This issue is reproducible in a local development environment.

Originally created by @ayhamDev on GitHub (Jul 31, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Create a Hono backend using `Bun` and configure `better-auth` with the MongoDB adapter and Google social provider as specified in the server-side code below. 2. Create an Expo frontend and configure the `authClient` using `@better-auth/react` and the `@better-auth/expo/client` plugin, ensuring `expo-secure-store` is integrated. 3. Implement a login screen with a button that triggers the `authClient.signIn.social({ provider: "google", callbackURL: "/" })` function. 4. Run the application, press the "Sign In With Google" button, and complete the authentication flow in the browser that opens. 5. After successful authentication, the app correctly re-opens via the deep link (`waain://`). 6. Observe that the session object, logged via `useEffect` listening to `authClient.useSession()`, remains `null`. ### Current vs. Expected behavior **Current Behavior:** Following a successful Google sign-in and redirect back to the Expo app, the `authClient.useSession()` hook does not update. The `session` variable remains `null`, and `session.isLoggedIn` is false. The user is not recognized as authenticated on the client side, even though the authentication process completes without visible errors and the app is reopened. **Expected Behavior:** After the redirect from the Google sign-in flow, the `@better-auth/expo/client` plugin should handle the callback, securely store the session token, and update the state. The `authClient.useSession()` hook should then return a valid session object containing the user's data, and `session.isLoggedIn` should be `true`. ### What version of Better Auth are you using? 1.3.4 ### Provide environment information ```bash **Provide environment information** - **OS:** Backend: [Windows 11], Client: [Android 13] - **Browser:** In-App Browser used by Expo for authentication flow. - **Runtime:** Bun (backend), Expo Go / Development Build (client) ``` ### Which area(s) are affected? (Select all that apply) Backend, Client ### Auth config (if applicable) ```typescript ### **Auth config (if applicable)** **Client-Side Config (`/lib/auth-client.ts`)** import { expoClient } from "@better-auth/expo/client"; import { createAuthClient } from "better-auth/react"; import * as SecureStore from "expo-secure-store"; export const authClient = createAuthClient({ baseURL: "http://192.168.8.113:3000", // Base URL of your Better Auth backend. plugins: [ expoClient({ scheme: "waain", storagePrefix: "waain-auth", storage: SecureStore, }), ], }); **Server-Side Config (`/api/lib/auth.ts`)** import { betterAuth } from "better-auth"; import { mongodbAdapter } from "better-auth/adapters/mongodb"; import { MongoClient } from "mongodb"; const client = new MongoClient(process.env.MONGO_URI as string); const db = client.db(); export const auth = betterAuth({ // @ts-ignore database: mongodbAdapter(db), trustedOrigins: ["*"], // Using wildcard for testing socialProviders: { google: { prompt: "select_account", clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }, }, }); ``` ### Additional context ### **Additional context** The issue appears to be specific to the handling of the authentication callback within the Expo client environment. The deep linking itself functions correctly, as the app is reopened post-authentication. However, the session data is not being successfully captured or propagated to the React context. Manually calling `session.refetch()` after the redirect has no effect. This issue is reproducible in a local development environment.
GiteaMirror added the expo label 2026-03-13 08:51:09 -05:00
Author
Owner

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

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

The Expo client plugin for Better Auth is designed to automatically handle the OAuth callback and update the session state after social sign-in, provided the deep link contains the expected cookie parameter. If the session remains null after Google sign-in, the most common causes are: the deep link missing the cookie parameter, issues with SecureStore not saving/replaying the cookie, the backend not accepting cookies, or a misconfigured callbackURL.

Here’s a focused troubleshooting checklist:

  1. After sign-in, inspect the deep link URL that reopens your app—confirm it contains a cookie query parameter. If it’s missing, the backend may not be appending it correctly in the callback handler, or the trustedOrigins config may not match your scheme (e.g., waain://). The backend plugin logic specifically checks for trusted origins and appends the cookie to the redirect URL if matched (source).

  2. Check that SecureStore is actually storing the cookie. You can log the value of waain-auth_cookie after sign-in. If it’s empty or missing, the plugin may not be extracting or saving the cookie from the callback URL (source).

  3. Make sure your backend’s trustedOrigins includes your app’s scheme (e.g., waain://). Using ["*"] is permissive, but for debugging, try explicitly adding your scheme and exp:// if using Expo Go (source).

  4. Confirm your callbackURL is being set and resolved correctly. The plugin converts relative URLs (like /) to full deep links using your scheme. If the callbackURL is malformed or missing, the session update may break (source).

  5. There was a known bug in cookie expiration handling in older versions of the Expo client plugin, but this was fixed in v1.2.9. Since you’re on 1.3.4, you should have the fix, but if you upgraded from an older version, clear your Expo cache and reinstall node_modules (source).

If these steps don’t resolve the issue, try logging the full redirect URL, SecureStore contents, and backend logs for the callback request. This will help pinpoint whether the problem is in the deep link/cookie propagation, storage, or session fetch.

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 (Jul 31, 2025): <!-- Greeting --> Hi @ayhamDev! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The Expo client plugin for Better Auth is designed to automatically handle the OAuth callback and update the session state after social sign-in, provided the deep link contains the expected `cookie` parameter. If the session remains null after Google sign-in, the most common causes are: the deep link missing the `cookie` parameter, issues with SecureStore not saving/replaying the cookie, the backend not accepting cookies, or a misconfigured callbackURL. Here’s a focused troubleshooting checklist: 1. After sign-in, inspect the deep link URL that reopens your app—confirm it contains a `cookie` query parameter. If it’s missing, the backend may not be appending it correctly in the callback handler, or the trustedOrigins config may not match your scheme (e.g., `waain://`). The backend plugin logic specifically checks for trusted origins and appends the cookie to the redirect URL if matched ([source](https://github.com/better-auth/better-auth/blob/33b0635c4dc1a28ce217b4eadecc4ed24092f12e/packages/expo/src/index.ts)). 2. Check that SecureStore is actually storing the cookie. You can log the value of `waain-auth_cookie` after sign-in. If it’s empty or missing, the plugin may not be extracting or saving the cookie from the callback URL ([source](https://github.com/better-auth/better-auth/blob/33b0635c4dc1a28ce217b4eadecc4ed24092f12e/packages/expo/src/client.ts)). 3. Make sure your backend’s `trustedOrigins` includes your app’s scheme (e.g., `waain://`). Using `["*"]` is permissive, but for debugging, try explicitly adding your scheme and `exp://` if using Expo Go ([source](https://github.com/better-auth/better-auth/blob/33b0635c4dc1a28ce217b4eadecc4ed24092f12e/packages/expo/src/expo.test.ts)). 4. Confirm your callbackURL is being set and resolved correctly. The plugin converts relative URLs (like `/`) to full deep links using your scheme. If the callbackURL is malformed or missing, the session update may break ([source](https://github.com/better-auth/better-auth/issues/2729)). 5. There was a known bug in cookie expiration handling in older versions of the Expo client plugin, but this was fixed in v1.2.9. Since you’re on 1.3.4, you should have the fix, but if you upgraded from an older version, clear your Expo cache and reinstall node_modules ([source](https://github.com/better-auth/better-auth/issues/3034)). If these steps don’t resolve the issue, try logging the full redirect URL, SecureStore contents, and backend logs for the callback request. This will help pinpoint whether the problem is in the deep link/cookie propagation, storage, or session fetch. <!-- 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/05d34cc7-7833-4599-973c-f30e3216af08?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/05d34cc7-7833-4599-973c-f30e3216af08?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/05d34cc7-7833-4599-973c-f30e3216af08?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/05d34cc7-7833-4599-973c-f30e3216af08?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/05d34cc7-7833-4599-973c-f30e3216af08?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/05d34cc7-7833-4599-973c-f30e3216af08?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/05d34cc7-7833-4599-973c-f30e3216af08?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/3711)
Author
Owner

@ayhamDev commented on GitHub (Jul 31, 2025):

@dosu
i tried anonymous login and it worked fine so maybe the problem with oauth only.

@ayhamDev commented on GitHub (Jul 31, 2025): @dosu i tried anonymous login and it worked fine so maybe the problem with oauth only.
Author
Owner

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

That’s a helpful clue—anonymous login works because it sets the session cookie directly in the response, while OAuth login in Expo relies on the backend appending the session cookie as a query parameter to the deep link, and the Expo client extracting and storing it. If any step in that OAuth flow fails (for example, the deep link is missing the cookie parameter, or SecureStore isn’t saving it), the session will stay null even though the redirect works as expected (source).

To pinpoint where it’s breaking, can you log and share:

  • The full deep link URL your app receives after Google sign-in (does it have a cookie query param?).
  • The value of waain-auth_cookie in SecureStore after sign-in.

If the deep link is missing the cookie, it’s likely a backend trustedOrigins or callback handling config issue (source). If the cookie is present in SecureStore but the session is still null, it could be an expiration, naming, or CORS/network issue (source). This will help narrow it down!

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 (Jul 31, 2025): <!-- Answer --> That’s a helpful clue—anonymous login works because it sets the session cookie directly in the response, while OAuth login in Expo relies on the backend appending the session cookie as a query parameter to the deep link, and the Expo client extracting and storing it. If any step in that OAuth flow fails (for example, the deep link is missing the `cookie` parameter, or SecureStore isn’t saving it), the session will stay null even though the redirect works as expected ([source](https://github.com/better-auth/better-auth/blob/33b0635c4dc1a28ce217b4eadecc4ed24092f12e/packages/expo/src/client.ts)). To pinpoint where it’s breaking, can you log and share: - The full deep link URL your app receives after Google sign-in (does it have a `cookie` query param?). - The value of `waain-auth_cookie` in SecureStore after sign-in. If the deep link is missing the cookie, it’s likely a backend trustedOrigins or callback handling config issue ([source](https://github.com/better-auth/better-auth/blob/33b0635c4dc1a28ce217b4eadecc4ed24092f12e/packages/expo/src/index.ts)). If the cookie is present in SecureStore but the session is still null, it could be an expiration, naming, or CORS/network issue ([source](https://github.com/better-auth/better-auth/issues/3180)). This will help narrow it down! <!-- 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/6e48d3f2-77c8-438a-8a2b-2442f60eb8b2?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/6e48d3f2-77c8-438a-8a2b-2442f60eb8b2?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/6e48d3f2-77c8-438a-8a2b-2442f60eb8b2?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/6e48d3f2-77c8-438a-8a2b-2442f60eb8b2?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/6e48d3f2-77c8-438a-8a2b-2442f60eb8b2?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/6e48d3f2-77c8-438a-8a2b-2442f60eb8b2?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/6e48d3f2-77c8-438a-8a2b-2442f60eb8b2?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/3711)
Author
Owner

@ayhamDev commented on GitHub (Jul 31, 2025):

@dosu
this is the c.req.raw after the successfull sign in: Request (0 KB) {
method: "GET",
url: "http://192.168.8.113:3000/api/auth/get-session",
headers: Headers {
"cookie": "; null=undefined; __Secure-better-auth.session_token=the Token",
"host": "192.168.8.113:3000",
"connection": "Keep-Alive",
"accept-encoding": "gzip",
"user-agent": "okhttp/4.12.0",
"if-modified-since": "Thu, 31 Jul 2025 11:31:23 GMT",
"expo-origin": "exp://192.168.8.113:8081",
"x-skip-oauth-proxy": "true",
}
}

@ayhamDev commented on GitHub (Jul 31, 2025): @dosu this is the c.req.raw after the successfull sign in: Request (0 KB) { method: "GET", url: "http://192.168.8.113:3000/api/auth/get-session", headers: Headers { "cookie": "; null=undefined; __Secure-better-auth.session_token=the Token", "host": "192.168.8.113:3000", "connection": "Keep-Alive", "accept-encoding": "gzip", "user-agent": "okhttp/4.12.0", "if-modified-since": "Thu, 31 Jul 2025 11:31:23 GMT", "expo-origin": "exp://192.168.8.113:8081", "x-skip-oauth-proxy": "true", } }
Author
Owner

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

Your request headers show that the session token is being sent as __Secure-better-auth.session_token, which is correct for Better Auth. However, if the session still remains null, the most common causes are: the session token is expired or invalid, the backend is not recognizing the cookie due to a config mismatch, or the cookie was not properly extracted/stored after OAuth.

To narrow this down, please check: (1) Does the deep link URL after Google sign-in contain a cookie query parameter? (2) Is waain-auth_cookie in SecureStore populated with a non-empty, unexpired token right after sign-in? (3) Are there any errors or warnings in your backend logs when /get-session is called?

If the cookie is present and unexpired in SecureStore but the session is still null, double-check that your backend trustedOrigins includes waain:// and exp:// (not just "*"), and that your CORS config allows credentials. There were also previous issues with cookie expiration parsing in older versions, but 1.3.4 should have those fixes—still, verify the expires field in your stored cookie just in case (source). If all of these look correct, enabling debug logging on the backend for /get-session can help pinpoint if the token is being rejected or ignored (source).

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 (Jul 31, 2025): <!-- Answer --> Your request headers show that the session token is being sent as __Secure-better-auth.session_token, which is correct for Better Auth. However, if the session still remains null, the most common causes are: the session token is expired or invalid, the backend is not recognizing the cookie due to a config mismatch, or the cookie was not properly extracted/stored after OAuth. To narrow this down, please check: (1) Does the deep link URL after Google sign-in contain a cookie query parameter? (2) Is waain-auth_cookie in SecureStore populated with a non-empty, unexpired token right after sign-in? (3) Are there any errors or warnings in your backend logs when /get-session is called? If the cookie is present and unexpired in SecureStore but the session is still null, double-check that your backend trustedOrigins includes waain:// and exp:// (not just "*"), and that your CORS config allows credentials. There were also previous issues with cookie expiration parsing in older versions, but 1.3.4 should have those fixes—still, verify the expires field in your stored cookie just in case ([source](https://github.com/better-auth/better-auth/issues/3034)). If all of these look correct, enabling debug logging on the backend for /get-session can help pinpoint if the token is being rejected or ignored ([source](https://github.com/better-auth/better-auth/pull/3347)). <!-- 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/beec0556-5d41-44ec-958c-9b006b90c97e?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/beec0556-5d41-44ec-958c-9b006b90c97e?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/beec0556-5d41-44ec-958c-9b006b90c97e?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/beec0556-5d41-44ec-958c-9b006b90c97e?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/beec0556-5d41-44ec-958c-9b006b90c97e?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/beec0556-5d41-44ec-958c-9b006b90c97e?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/beec0556-5d41-44ec-958c-9b006b90c97e?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/3711)
Author
Owner

@ayhamDev commented on GitHub (Aug 4, 2025):

@dosu
i fixed the problem by adding the expo plug to the betterauth server , but i have a problem now , when the user finshes the login with google for example and gets redirect back to the app what happens is that the auth does not get untill the app is restarted , when restarted the session is their meaning the auth worked

const HandleSignIn = async () => {
console.log("start");

const user = await authClient.signIn.social({
  provider: "google",
  callbackURL: "/auth",
});
console.log("end");
console.log(user);

};

the "end" doesnot gets logged in the console

@ayhamDev commented on GitHub (Aug 4, 2025): @dosu i fixed the problem by adding the expo plug to the betterauth server , but i have a problem now , when the user finshes the login with google for example and gets redirect back to the app what happens is that the auth does not get untill the app is restarted , when restarted the session is their meaning the auth worked const HandleSignIn = async () => { console.log("start"); const user = await authClient.signIn.social({ provider: "google", callbackURL: "/auth", }); console.log("end"); console.log(user); }; the "end" doesnot gets logged in the console
Author
Owner

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

This is a known issue with Expo deep link handling in Better Auth: if the deep link event from the OAuth redirect is missed (due to timing or app state), the signIn.social() promise hangs and only resolves after an app restart, when the deep link is finally processed and the session is loaded from storage. This usually happens if the expoClient plugin isn't fully initialized before you trigger the sign-in, or if the deep link listener isn't active at the right moment (discussion).

To work around this, make sure the expoClient plugin is registered before any sign-in attempt. As a practical fix, call await authClient.getSession() immediately after await authClient.signIn.social(...)—this forces a session refresh and makes the session available to your hooks without needing a restart (issue). Example:

const HandleSignIn = async () => {
  console.log("start");
  await authClient.signIn.social({ provider: "google", callbackURL: "/auth" });
  await authClient.getSession(); // <-- workaround
  console.log("end");
};

If you want to debug further, add logging to your deep link event handlers and check if the event fires right after OAuth redirect. If not, it's a listener timing issue. Also, double-check that your callbackURL is a user-facing route (not the backend OAuth endpoint), and that your trustedOrigins includes your app scheme and exp:// (callbackURL docs).

Let me know if this workaround solves it or if you see any errors in the logs!

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 4, 2025): <!-- Answer --> This is a known issue with Expo deep link handling in Better Auth: if the deep link event from the OAuth redirect is missed (due to timing or app state), the signIn.social() promise hangs and only resolves after an app restart, when the deep link is finally processed and the session is loaded from storage. This usually happens if the expoClient plugin isn't fully initialized before you trigger the sign-in, or if the deep link listener isn't active at the right moment ([discussion](https://github.com/better-auth/better-auth/discussions/3448)). To work around this, make sure the expoClient plugin is registered before any sign-in attempt. As a practical fix, call `await authClient.getSession()` immediately after `await authClient.signIn.social(...)`—this forces a session refresh and makes the session available to your hooks without needing a restart ([issue](https://github.com/better-auth/better-auth/issues/1443)). Example: ```js const HandleSignIn = async () => { console.log("start"); await authClient.signIn.social({ provider: "google", callbackURL: "/auth" }); await authClient.getSession(); // <-- workaround console.log("end"); }; ``` If you want to debug further, add logging to your deep link event handlers and check if the event fires right after OAuth redirect. If not, it's a listener timing issue. Also, double-check that your callbackURL is a user-facing route (not the backend OAuth endpoint), and that your trustedOrigins includes your app scheme and exp:// ([callbackURL docs](https://github.com/better-auth/better-auth/issues/3488)). Let me know if this workaround solves it or if you see any errors in the logs! <!-- 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/bc70be7c-d541-4842-9ff1-43eb74fa8bf0?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/bc70be7c-d541-4842-9ff1-43eb74fa8bf0?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/bc70be7c-d541-4842-9ff1-43eb74fa8bf0?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/bc70be7c-d541-4842-9ff1-43eb74fa8bf0?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/bc70be7c-d541-4842-9ff1-43eb74fa8bf0?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/bc70be7c-d541-4842-9ff1-43eb74fa8bf0?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/bc70be7c-d541-4842-9ff1-43eb74fa8bf0?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/3711)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1607