[GH-ISSUE #7025] Expo + Express : Google SignIn stuck at Consent screen, no errors or warnings #28029

Closed
opened 2026-04-17 19:22:39 -05:00 by GiteaMirror · 4 comments
Owner

Originally created by @EnigmaByte7 on GitHub (Dec 27, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/7025

Originally assigned to: @bytaesu on GitHub.

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. An Expo app
  2. An Express based OAuth server deployed on render
  3. Upon initiating sign in via the app, it does correctly opens up the browser
  4. consent screen shows up,
  5. however after choosing an account, it loads forever
  6. no errors, no warnings, even the request does not end

Current vs. Expected behavior

followed expo integration docs.

upon clicking sign in, the browser opens up with the google consent screen,

i select my account,

and then it loads forever.. no errors on frontend, neither on backend.

Im dealing with an expo (not expo go) + express setup

What version of Better Auth are you using?

1.4.9

System info

{
  "system": {
    "platform": "linux",
    "arch": "x64",
    "version": "#89-Ubuntu SMP PREEMPT_DYNAMIC Sat Oct 11 01:02:46 UTC 2025",
    "release": "6.8.0-88-generic",
    "cpuCount": 12,
    "cpuModel": "13th Gen Intel(R) Core(TM) i5-1334U",
    "totalMemory": "15.31 GB",
    "freeMemory": "4.77 GB"
  },
  "node": {
    "version": "v22.17.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.7.0"
  },
  "frameworks": [
    {
      "name": "react",
      "version": "19.1.0"
    }
  ],
  "databases": [
    {
      "name": "pg",
      "version": "^8.16.3"
    }
  ],
  "betterAuth": {
    "version": "^1.4.9",
    "config": null
  }
}

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

Client

Auth config (if applicable)

import { expo } from "@better-auth/expo";
import { betterAuth } from "better-auth";
import dotenv from 'dotenv';
import { Pool } from 'pg';
dotenv.config()

export const auth = betterAuth({
  plugins: [expo()],
  database: new Pool({
    connectionString: process.env.DATABASE_URL
  }),
  baseUrl: '<render_url>',
  socialProviders: {
    google: {
      clientId: process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
      redirectURI:'https://<render_url>/api/auth/callback/google'
    },
  },
  trustedOrigins: ["myapp://"],
});

Additional context

Google redirect url is already set as , https://<render_url>/api/auth/callback/google

heres my login handler on frontend...

const handleSignUp = async () => {
    try {
      await authClient.signIn.social({
          provider: "google",
          callbackURL: "/",
      })
    }
    catch(e) {
      console.log(e);
      
    }

and authClient,

export const authClient = createAuthClient({
	baseURL: "<render_url>", //server
	disableDefaultFetchPlugins: true,
	plugins: [
		expoClient({
			scheme: "myapp",
			storage: SecureStore,
		}),
	],
});```
Originally created by @EnigmaByte7 on GitHub (Dec 27, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/7025 Originally assigned to: @bytaesu on GitHub. ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. An Expo app 2. An Express based OAuth server deployed on render 3. Upon initiating sign in via the app, it does correctly opens up the browser 4. consent screen shows up, 5. however after choosing an account, it loads forever 6. no errors, no warnings, even the request does not end ### Current vs. Expected behavior followed [expo integration docs](https://www.better-auth.com/docs/integrations/expo#making-authenticated-requests-to-your-server). upon clicking sign in, the browser opens up with the google consent screen, i select my account, and then it loads forever.. no errors on frontend, neither on backend. Im dealing with an expo (not expo go) + express setup ### What version of Better Auth are you using? 1.4.9 ### System info ```bash { "system": { "platform": "linux", "arch": "x64", "version": "#89-Ubuntu SMP PREEMPT_DYNAMIC Sat Oct 11 01:02:46 UTC 2025", "release": "6.8.0-88-generic", "cpuCount": 12, "cpuModel": "13th Gen Intel(R) Core(TM) i5-1334U", "totalMemory": "15.31 GB", "freeMemory": "4.77 GB" }, "node": { "version": "v22.17.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.7.0" }, "frameworks": [ { "name": "react", "version": "19.1.0" } ], "databases": [ { "name": "pg", "version": "^8.16.3" } ], "betterAuth": { "version": "^1.4.9", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Client ### Auth config (if applicable) ```typescript import { expo } from "@better-auth/expo"; import { betterAuth } from "better-auth"; import dotenv from 'dotenv'; import { Pool } from 'pg'; dotenv.config() export const auth = betterAuth({ plugins: [expo()], database: new Pool({ connectionString: process.env.DATABASE_URL }), baseUrl: '<render_url>', socialProviders: { google: { clientId: process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, redirectURI:'https://<render_url>/api/auth/callback/google' }, }, trustedOrigins: ["myapp://"], }); ``` ### Additional context Google redirect url is already set as , https://<render_url>/api/auth/callback/google heres my login handler on frontend... ```typescript const handleSignUp = async () => { try { await authClient.signIn.social({ provider: "google", callbackURL: "/", }) } catch(e) { console.log(e); } ``` and authClient, ```typescript export const authClient = createAuthClient({ baseURL: "<render_url>", //server disableDefaultFetchPlugins: true, plugins: [ expoClient({ scheme: "myapp", storage: SecureStore, }), ], });```
GiteaMirror added the lockedneeds: info labels 2026-04-17 19:22:39 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Dec 27, 2025):

It seems you're experiencing an issue with Google Sign-In on your Expo and Express setup, where it gets stuck on the consent screen without any errors or warnings. Here are some troubleshooting steps you can try:

  1. Check Redirect URI: Ensure that the redirect URI specified in your Google Cloud Console exactly matches the one defined in your Express app. Even small discrepancies can lead to issues.

  2. Inspect OAuth Scopes: Verify that the requested OAuth scopes are correct and properly configured in your Google credentials.

  3. Token Handling: Follow the latest integration guidance on how to handle the idToken from Google. Make sure your app is using the idToken correctly in its authentication process, as mentioned in the recommendations on improving social auth with idToken in Expo apps [1].

  4. Console and Network Logs: Check the console and network logs in the Expo app while trying to authenticate. This might reveal more information on what is happening after selecting the account.

  5. Demo or Test with Sample: Test the flow with a minimal setup or a different Expo app to identify whether the problem remains or is specific to your current implementation.

If none of these options resolve your issue, you might consider tagging @bekacru or @ping__ in your follow-up to get more direct support from the Better Auth team.

What specific aspect of the authentication process would you like to dive deeper into?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3694130929 --> @better-auth-agent[bot] commented on GitHub (Dec 27, 2025): It seems you're experiencing an issue with Google Sign-In on your Expo and Express setup, where it gets stuck on the consent screen without any errors or warnings. Here are some troubleshooting steps you can try: 1. **Check Redirect URI**: Ensure that the redirect URI specified in your Google Cloud Console exactly matches the one defined in your Express app. Even small discrepancies can lead to issues. 2. **Inspect OAuth Scopes**: Verify that the requested OAuth scopes are correct and properly configured in your Google credentials. 3. **Token Handling**: Follow the latest integration guidance on how to handle the idToken from Google. Make sure your app is using the idToken correctly in its authentication process, as mentioned in the recommendations on improving social auth with `idToken` in Expo apps [[1]](https://github.com/better-auth/better-auth/issues/6368). 4. **Console and Network Logs**: Check the console and network logs in the Expo app while trying to authenticate. This might reveal more information on what is happening after selecting the account. 5. **Demo or Test with Sample**: Test the flow with a minimal setup or a different Expo app to identify whether the problem remains or is specific to your current implementation. If none of these options resolve your issue, you might consider tagging @bekacru or @ping__ in your follow-up to get more direct support from the Better Auth team. What specific aspect of the authentication process would you like to dive deeper into? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@dosubot[bot] commented on GitHub (Dec 27, 2025):

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

This is a common issue with Expo + Express + Better Auth and usually comes down to redirect URI, deep linking, or cookie/session propagation problems. Here’s what to check:

  1. Make sure your Expo app’s scheme (e.g., myapp) is set in both your app.json and in the Better Auth server config’s trustedOrigins as myapp://—they must match exactly for deep linking and cookie handling to work (docs, issue).

  2. The Google OAuth redirect URI must be a public HTTPS URL (not a custom scheme or localhost), and it must match exactly in the Google Cloud Console and your Better Auth config (including protocol, path, and no trailing slashes). If the backend doesn’t receive the callback from Google, the flow will hang at the consent screen with no errors (issue, issue).

  3. In Better Auth v1.4.9, you may hit a bug where the OAuth state cookie is set with SameSite=Lax, which breaks state validation on mobile. Fix this by adding to your Better Auth config:

    advanced: {
      cookies: {
        state: {
          attributes: {
            sameSite: "none",
            secure: true,
          }
        }
      }
    }
    

    (details, details)

  4. After calling authClient.signIn.social, immediately call await authClient.getSession() to force a session refresh—this is a reliable workaround for session state not being available right after OAuth on Expo/mobile (issue, issue).

  5. Log the deep link URL after sign-in and check for a cookie query parameter. If it’s missing, it usually means a mismatch in trustedOrigins or the backend isn’t appending the cookie (issue).

  6. If you have custom middleware or session logic before the auth handler for /auth/* routes, it can break cookie propagation and cause state mismatches (issue).

  7. For CORS issues with Expo API routes, try enabling the disableOriginOverride option in the Expo plugin (PR).

If you’re still stuck, add logging on both client and server to see if the backend receives the callback and if the deep link contains the cookie. This will help pinpoint where the flow is breaking.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3694133448 --> @dosubot[bot] commented on GitHub (Dec 27, 2025): <!-- Greeting --> Hi @EnigmaByte7! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This is a common issue with Expo + Express + Better Auth and usually comes down to redirect URI, deep linking, or cookie/session propagation problems. Here’s what to check: 1. Make sure your Expo app’s scheme (e.g., `myapp`) is set in both your `app.json` and in the Better Auth server config’s `trustedOrigins` as `myapp://`—they must match exactly for deep linking and cookie handling to work ([docs](https://github.com/better-auth/better-auth/blob/4d7d7d5a76b5e0e90d42238f00751584ec07afa7/docs/content/docs/integrations/expo.mdx#L60-L535), [issue](https://github.com/better-auth/better-auth/issues/4070)). 2. The Google OAuth redirect URI must be a public HTTPS URL (not a custom scheme or localhost), and it must match exactly in the Google Cloud Console and your Better Auth config (including protocol, path, and no trailing slashes). If the backend doesn’t receive the callback from Google, the flow will hang at the consent screen with no errors ([issue](https://github.com/better-auth/better-auth/issues/4070), [issue](https://github.com/better-auth/better-auth/issues/3781)). 3. In Better Auth v1.4.9, you may hit a bug where the OAuth state cookie is set with `SameSite=Lax`, which breaks state validation on mobile. Fix this by adding to your Better Auth config: ```ts advanced: { cookies: { state: { attributes: { sameSite: "none", secure: true, } } } } ``` ([details](https://github.com/better-auth/better-auth/issues/6483), [details](https://github.com/better-auth/better-auth/issues/6582)) 4. After calling `authClient.signIn.social`, immediately call `await authClient.getSession()` to force a session refresh—this is a reliable workaround for session state not being available right after OAuth on Expo/mobile ([issue](https://github.com/better-auth/better-auth/issues/5034), [issue](https://github.com/better-auth/better-auth/issues/6582)). 5. Log the deep link URL after sign-in and check for a `cookie` query parameter. If it’s missing, it usually means a mismatch in `trustedOrigins` or the backend isn’t appending the cookie ([issue](https://github.com/better-auth/better-auth/issues/4070)). 6. If you have custom middleware or session logic before the auth handler for `/auth/*` routes, it can break cookie propagation and cause state mismatches ([issue](https://github.com/better-auth/better-auth/issues/6483)). 7. For CORS issues with Expo API routes, try enabling the `disableOriginOverride` option in the Expo plugin ([PR](https://github.com/better-auth/better-auth/pull/5545)). If you’re still stuck, add logging on both client and server to see if the backend receives the callback and if the deep link contains the cookie. This will help pinpoint where the flow is breaking. <!-- 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/8cab91d9-abf1-4c3a-a76b-1a9c461bbd19?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/8cab91d9-abf1-4c3a-a76b-1a9c461bbd19?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/8cab91d9-abf1-4c3a-a76b-1a9c461bbd19?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/8cab91d9-abf1-4c3a-a76b-1a9c461bbd19?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/8cab91d9-abf1-4c3a-a76b-1a9c461bbd19?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/8cab91d9-abf1-4c3a-a76b-1a9c461bbd19?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/8cab91d9-abf1-4c3a-a76b-1a9c461bbd19?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=This%20is%20a%20common%20issue%20with%20Expo%20%2B%20Express%20%2B%20Better%20Auth%20and%20usually%20comes%20down%20to%20redirect%20URI%2C%20deep%20linking%2C%20or%20cookie/session%20propagation%20problems.%20Here%E2%80%99s%20what%20to%20check%3A%0A%0A1.%20Make%20sure%20your%20Expo%20app%E2%80%99s%20scheme%20%28e.g.%2C%20%60myapp%60%29%20is%20set%20in%20both%20your%20%60app.json%60%20and%20in%20the%20Better%20Auth%20server%20config%E2%80%99s%20%60trustedOrigins%60%20as%20%60myapp%3A//%60%E2%80%94they%20must%20match%20exactly%20for%20deep%20linking%20and%20cookie%20handling%20to%20work%20%28%5Bdocs%5D%28https%3A//github.com/better-auth/better-auth/blob/4d7d7d5a76b5e0e90d42238f00751584ec07afa7/docs/content/docs/integrations/expo.mdx%23L60-L535%29%2C%20%5Bissue%5D%28https%3A//github.com/better-auth/better-auth/issues/4070%29%29.%0A%0A2.%20The%20Google%20OAuth%20redirect%20URI%20must%20be%20a%20public%20HTTPS%20URL%20%28not%20a%20custom%20scheme%20or%20localhost%29%2C%20and%20it%20must%20match%20exactly%20in%20the%20Google%20Cloud%20Console%20and%20your%20Better%20Auth%20config%20%28including%20protocol%2C%20path%2C%20and%20no%20trailing%20slashes%29.%20If%20the%20backend%20doesn%E2%80%99t%20receive%20the%20callback%20from%20Google%2C%20the%20flow%20will%20hang%20at%20the%20consent%20screen%20with%20no%20errors%20%28%5Bissue%5D%28https%3A//github.com/better-auth/better-auth/issues/4070%29%2C%20%5Bissue%5D%28https%3A//github.com/better-auth/better-auth/issues/3781%29%29.%0A%0A3.%20In%20Better%20Auth%20v1.4.9%2C%20you%20may%20hit%20a%20bug%20where%20the%20OAuth%20state%20cookie%20is%20set%20with%20%60SameSite%3DLax%60%2C%20which%20breaks%20state%20validation%20on%20mobile.%20Fix%20this%20by%20adding%20to%20your%20Better%20Auth%20config%3A%0A%20%20%20%60%60%60ts%0A%20%20%20advanced%3A%20%7B%0A%20%20%20%20%20cookies%3A%20%7B%0A%20%20%20%20%20%20%20state%3A%20%7B%0A%20%20%20%20%20%20%20%20%20attributes%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20sameSite%3A%20%22none%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20secure%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%7D%0A%20%20%20%7D%0A%20%20%20%60%60%60%0A%20%20%20%28%5Bdetails%5D%28https%3A//github.com/better-auth/better-auth/issues/6483%29%2C%20%5Bdetails%5D%28https%3A//github.com/better-auth/better-auth/issues/6582%29%29%0A%0A4.%20After%20calling%20%60authClient.signIn.social%60%2C%20immediately%20call%20%60await%20authClient.getSession%28%29%60%20to%20force%20a%20session%20refresh%E2%80%94this%20is%20a%20reliable%20workaround%20for%20session%20state%20not%20being%20available%20right%20after%20OAuth%20on%20Expo/mobile%20%28%5Bissue%5D%28https%3A//github.com/better-auth/better-auth/issues/5034%29%2C%20%5Bissue%5D%28https%3A//github.com/better-auth/better-auth/issues/6582%29%29.%0A%0A5.%20Log%20the%20deep%20link%20URL%20after%20sign-in%20and%20check%20for%20a%20%60cookie%60%20query%20parameter.%20If%20it%E2%80%99s%20missing%2C%20it%20usually%20means%20a%20mismatch%20in%20%60trustedOrigins%60%20or%20the%20backend%20isn%E2%80%99t%20appending%20the%20cookie%20%28%5Bissue%5D%28https%3A//github.com/better-auth/better-auth/issues/4070%29%29.%0A%0A6.%20If%20you%20have%20custom%20middleware%20or%20session%20logic%20before%20the%20auth%20handler%20for%20%60/auth/%2A%60%20routes%2C%20it%20can%20break%20cookie%20propagation%20and%20cause%20state%20mismatches%20%28%5Bissue%5D%28https%3A//github.com/better-auth/better-auth/issues/6483%29%29.%0A%0A7.%20For%20CORS%20issues%20with%20Expo%20API%20routes%2C%20try%20enabling%20the%20%60disableOriginOverride%60%20option%20in%20the%20Expo%20plugin%20%28%5BPR%5D%28https%3A//github.com/better-auth/better-auth/pull/5545%29%29.%0A%0AIf%20you%E2%80%99re%20still%20stuck%2C%20add%20logging%20on%20both%20client%20and%20server%20to%20see%20if%20the%20backend%20receives%20the%20callback%20and%20if%20the%20deep%20link%20contains%20the%20cookie.%20This%20will%20help%20pinpoint%20where%20the%20flow%20is%20breaking.)&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/7025)
Author
Owner

@bytaesu commented on GitHub (Jan 9, 2026):

Hi @EnigmaByte7,

I’ll look into this. In the meantime, could you share a minimal reproducible repo with me so I can investigate the issue more quickly? 🙂

<!-- gh-comment-id:3727607556 --> @bytaesu commented on GitHub (Jan 9, 2026): Hi @EnigmaByte7, I’ll look into this. In the meantime, could you share a minimal reproducible repo with me so I can investigate the issue more quickly? 🙂
Author
Owner

@bytaesu commented on GitHub (Mar 12, 2026):

https://better-auth.com/docs/integrations/expo

I tested this with the latest version following our docs guide and couldn’t reproduce the issue. If it persists, feel free to reopen or mention me!

<!-- gh-comment-id:4046278329 --> @bytaesu commented on GitHub (Mar 12, 2026): > https://better-auth.com/docs/integrations/expo I tested this with the latest version following our docs guide and couldn’t reproduce the issue. If it persists, feel free to reopen or mention 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#28029