state_mismatch error using Google OAuth on 1.4.5 #2444

Closed
opened 2026-03-13 09:54:54 -05:00 by GiteaMirror · 19 comments
Owner

Originally created by @ThomasBurgess2000 on GitHub (Dec 3, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

I've seen a lot of issues related to this and marked as closed, despite many reporting it's still not fixed, and I just wanted to report that it's still a problem in 1.4.5.

https://github.com/better-auth/better-auth/issues/5243
https://github.com/better-auth/better-auth/issues/6207
https://github.com/better-auth/better-auth/issues/4969
https://github.com/better-auth/better-auth/issues/5227
https://github.com/better-auth/better-auth/issues/5034

Current vs. Expected behavior

You should be able to Sign In with Google.

What version of Better Auth are you using?

1.4.5

System info

This command does not work for me (Windows 11).

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

Client, Backend

Additional context

No response

Originally created by @ThomasBurgess2000 on GitHub (Dec 3, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce I've seen a lot of issues related to this and marked as closed, despite many reporting it's still not fixed, and I just wanted to report that it's still a problem in 1.4.5. https://github.com/better-auth/better-auth/issues/5243 https://github.com/better-auth/better-auth/issues/6207 https://github.com/better-auth/better-auth/issues/4969 https://github.com/better-auth/better-auth/issues/5227 https://github.com/better-auth/better-auth/issues/5034 ### Current vs. Expected behavior You should be able to Sign In with Google. ### What version of Better Auth are you using? 1.4.5 ### System info ```bash This command does not work for me (Windows 11). ``` ### Which area(s) are affected? (Select all that apply) Client, Backend ### Additional context _No response_
GiteaMirror added the social-provider label 2026-03-13 09:54:54 -05:00
Author
Owner

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

Hello, thanks for reporting this issue with Google OAuth on version 1.4.5. A state_mismatch error generally indicates that the state parameter sent in your initial OAuth request isn’t matching the state parameter received in the callback. To troubleshoot, please ensure that your OAuth client’s redirect URI exactly matches the configuration in your Google Developer Console [1]. Also, verify that your application properly stores and validates the state parameter between the request and callback—this could include checking your session or cookie handling on Windows 11 [2]. Finally, it may help to clear any stale cookies or sessions that could interfere with state validation. Have you confirmed that your callback URL and state-handling logic align with Google’s recommendations?

tag @better-auth-agent if you would like an answer from the Agent

If you need more help, tag @Skyvern in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Dec 3, 2025): Hello, thanks for reporting this issue with Google OAuth on version 1.4.5. A state_mismatch error generally indicates that the state parameter sent in your initial OAuth request isn’t matching the state parameter received in the callback. To troubleshoot, please ensure that your OAuth client’s redirect URI exactly matches the configuration in your Google Developer Console [[1]](https://github.com/better-auth/better-auth/issues/6446). Also, verify that your application properly stores and validates the state parameter between the request and callback—this could include checking your session or cookie handling on Windows 11 [[2]](https://github.com/better-auth/better-auth/issues/4125). Finally, it may help to clear any stale cookies or sessions that could interfere with state validation. Have you confirmed that your callback URL and state-handling logic align with Google’s recommendations? tag @better-auth-agent if you would like an answer from the Agent _If you need more help, tag @Skyvern 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 3, 2025):

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

The persistent state_mismatch error with Google OAuth in Better Auth v1.4.5 is a known issue, especially in mobile, Expo/React Native, and cross-domain setups. The main cause is that the OAuth state cookie is set with SameSite=Lax by default, which browsers do not send during POST redirects—breaking state validation in many OAuth flows, particularly on mobile and with providers like Apple and Google. The fix to set SameSite=None for OAuth state cookies was merged after v1.4.5, so upgrading to a newer version is required for a full solution (details).

If you’re stuck on v1.4.5, you can try these workarounds:

  • In your Better Auth config, set the state cookie to SameSite=None and Secure=true:
    advanced: {
      cookies: {
        state: {
          attributes: {
            sameSite: "none",
            secure: true,
          }
        }
      }
    }
    
  • Always initiate social sign-in from the client using authClient.signIn.social, not from server actions or API routes (reference).
  • Make sure your Google OAuth redirect URI matches the callback endpoint, and set the callbackURL in signIn.social to a user-facing route (not the callback endpoint itself).
  • Double-check that all your app URLs (local, preview, production) are listed in trustedOrigins.
  • If you use Expo/React Native, ensure you’re using the Expo plugin and the /api/auth/expo-authorization-proxy endpoint is available on your backend (reference).
  • After sign-in on mobile, immediately call await authClient.getSession() to refresh the session (reference).

For custom backends (like NestJS), the Expo proxy endpoint is required for mobile OAuth to work reliably. If you’re using a community package that doesn’t provide this endpoint, you’ll need to implement it or switch to the official backend (reference).

If you still see issues, check for custom middleware or session logic running before the auth handler for /auth/* routes—this can break cookie propagation and cause persistent state mismatches (reference).

Let me know if you need help with a specific environment or config!

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

@dosubot[bot] commented on GitHub (Dec 3, 2025): <!-- Greeting --> Hi @ThomasBurgess2000! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The persistent `state_mismatch` error with Google OAuth in Better Auth v1.4.5 is a known issue, especially in mobile, Expo/React Native, and cross-domain setups. The main cause is that the OAuth state cookie is set with `SameSite=Lax` by default, which browsers do not send during POST redirects—breaking state validation in many OAuth flows, particularly on mobile and with providers like Apple and Google. The fix to set `SameSite=None` for OAuth state cookies was merged after v1.4.5, so upgrading to a newer version is required for a full solution [(details)](https://github.com/better-auth/better-auth/pull/5748). If you’re stuck on v1.4.5, you can try these workarounds: - In your Better Auth config, set the state cookie to `SameSite=None` and `Secure=true`: ```typescript advanced: { cookies: { state: { attributes: { sameSite: "none", secure: true, } } } } ``` - Always initiate social sign-in from the client using `authClient.signIn.social`, not from server actions or API routes [(reference)](https://github.com/better-auth/better-auth/issues/5478). - Make sure your Google OAuth redirect URI matches the callback endpoint, and set the `callbackURL` in `signIn.social` to a user-facing route (not the callback endpoint itself). - Double-check that all your app URLs (local, preview, production) are listed in `trustedOrigins`. - If you use Expo/React Native, ensure you’re using the Expo plugin and the `/api/auth/expo-authorization-proxy` endpoint is available on your backend [(reference)](https://github.com/better-auth/better-auth/issues/6207). - After sign-in on mobile, immediately call `await authClient.getSession()` to refresh the session [(reference)](https://github.com/better-auth/better-auth/issues/5034). For custom backends (like NestJS), the Expo proxy endpoint is required for mobile OAuth to work reliably. If you’re using a community package that doesn’t provide this endpoint, you’ll need to implement it or switch to the official backend [(reference)](https://github.com/better-auth/better-auth/issues/6207). If you still see issues, check for custom middleware or session logic running before the auth handler for `/auth/*` routes—this can break cookie propagation and cause persistent state mismatches [(reference)](https://github.com/better-auth/better-auth/issues/5478). Let me know if you need help with a specific environment or config! <!-- 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/dde7d3c0-b644-41e8-9aa6-9ab5c5cb30d7?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/dde7d3c0-b644-41e8-9aa6-9ab5c5cb30d7?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/dde7d3c0-b644-41e8-9aa6-9ab5c5cb30d7?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/dde7d3c0-b644-41e8-9aa6-9ab5c5cb30d7?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/dde7d3c0-b644-41e8-9aa6-9ab5c5cb30d7?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/dde7d3c0-b644-41e8-9aa6-9ab5c5cb30d7?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/dde7d3c0-b644-41e8-9aa6-9ab5c5cb30d7?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=The%20persistent%20%60state_mismatch%60%20error%20with%20Google%20OAuth%20in%20Better%20Auth%20v1.4.5%20is%20a%20known%20issue%2C%20especially%20in%20mobile%2C%20Expo/React%20Native%2C%20and%20cross-domain%20setups.%20The%20main%20cause%20is%20that%20the%20OAuth%20state%20cookie%20is%20set%20with%20%60SameSite%3DLax%60%20by%20default%2C%20which%20browsers%20do%20not%20send%20during%20POST%20redirects%E2%80%94breaking%20state%20validation%20in%20many%20OAuth%20flows%2C%20particularly%20on%20mobile%20and%20with%20providers%20like%20Apple%20and%20Google.%20The%20fix%20to%20set%20%60SameSite%3DNone%60%20for%20OAuth%20state%20cookies%20was%20merged%20after%20v1.4.5%2C%20so%20upgrading%20to%20a%20newer%20version%20is%20required%20for%20a%20full%20solution%20%5B%28details%29%5D%28https%3A//github.com/better-auth/better-auth/pull/5748%29.%0A%0AIf%20you%E2%80%99re%20stuck%20on%20v1.4.5%2C%20you%20can%20try%20these%20workarounds%3A%0A-%20In%20your%20Better%20Auth%20config%2C%20set%20the%20state%20cookie%20to%20%60SameSite%3DNone%60%20and%20%60Secure%3Dtrue%60%3A%0A%20%20%60%60%60typescript%0A%20%20advanced%3A%20%7B%0A%20%20%20%20cookies%3A%20%7B%0A%20%20%20%20%20%20state%3A%20%7B%0A%20%20%20%20%20%20%20%20attributes%3A%20%7B%0A%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%20secure%3A%20true%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%20%20%60%60%60%0A-%20Always%20initiate%20social%20sign-in%20from%20the%20client%20using%20%60authClient.signIn.social%60%2C%20not%20from%20server%20actions%20or%20API%20routes%20%5B%28reference%29%5D%28https%3A//github.com/better-auth/better-auth/issues/5478%29.%0A-%20Make%20sure%20your%20Google%20OAuth%20redirect%20URI%20matches%20the%20callback%20endpoint%2C%20and%20set%20the%20%60callbackURL%60%20in%20%60signIn.social%60%20to%20a%20user-facing%20route%20%28not%20the%20callback%20endpoint%20itself%29.%0A-%20Double-check%20that%20all%20your%20app%20URLs%20%28local%2C%20preview%2C%20production%29%20are%20listed%20in%20%60trustedOrigins%60.%0A-%20If%20you%20use%20Expo/React%20Native%2C%20ensure%20you%E2%80%99re%20using%20the%20Expo%20plugin%20and%20the%20%60/api/auth/expo-authorization-proxy%60%20endpoint%20is%20available%20on%20your%20backend%20%5B%28reference%29%5D%28https%3A//github.com/better-auth/better-auth/issues/6207%29.%0A-%20After%20sign-in%20on%20mobile%2C%20immediately%20call%20%60await%20authClient.getSession%28%29%60%20to%20refresh%20the%20session%20%5B%28reference%29%5D%28https%3A//github.com/better-auth/better-auth/issues/5034%29.%0A%0AFor%20custom%20backends%20%28like%20NestJS%29%2C%20the%20Expo%20proxy%20endpoint%20is%20required%20for%20mobile%20OAuth%20to%20work%20reliably.%20If%20you%E2%80%99re%20using%20a%20community%20package%20that%20doesn%E2%80%99t%20provide%20this%20endpoint%2C%20you%E2%80%99ll%20need%20to%20implement%20it%20or%20switch%20to%20the%20official%20backend%20%5B%28reference%29%5D%28https%3A//github.com/better-auth/better-auth/issues/6207%29.%0A%0AIf%20you%20still%20see%20issues%2C%20check%20for%20custom%20middleware%20or%20session%20logic%20running%20before%20the%20auth%20handler%20for%20%60/auth/%2A%60%20routes%E2%80%94this%20can%20break%20cookie%20propagation%20and%20cause%20persistent%20state%20mismatches%20%5B%28reference%29%5D%28https%3A//github.com/better-auth/better-auth/issues/5478%29.%0A%0ALet%20me%20know%20if%20you%20need%20help%20with%20a%20specific%20environment%20or%20config%21)&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/6483)
Author
Owner

@ping-maxwell commented on GitHub (Dec 3, 2025):

Hey have you read the state-mismatch error docs?
https://www.better-auth.com/docs/errors/state_mismatch

@ping-maxwell commented on GitHub (Dec 3, 2025): Hey have you read the state-mismatch error docs? https://www.better-auth.com/docs/errors/state_mismatch
Author
Owner

@ping-maxwell commented on GitHub (Dec 3, 2025):

I've seen a lot of issues related to this and marked as closed

This isn't a bug in Better-Auth, rather most cases I've seen this issue, it's a valid issue and an indication of misconfiguration or incorrect setup on the user-land.

@ping-maxwell commented on GitHub (Dec 3, 2025): > I've seen a lot of issues related to this and marked as closed This isn't a bug in Better-Auth, rather most cases I've seen this issue, it's a valid issue and an indication of misconfiguration or incorrect setup on the user-land.
Author
Owner

@krzkz94 commented on GitHub (Dec 3, 2025):

Can confirm it's happening for me too. 1.4.1 and 1.4.5 both share the same issue

Downgrading to 1.3.13 fixed the issue for me btw

@krzkz94 commented on GitHub (Dec 3, 2025): Can confirm it's happening for me too. 1.4.1 and 1.4.5 both share the same issue Downgrading to 1.3.13 fixed the issue for me btw
Author
Owner

@ThomasBurgess2000 commented on GitHub (Dec 3, 2025):

I think it was a configuration error on my part, I think related to the fact that our backend is on a different domain from our frontend. Sorry about that!

@ThomasBurgess2000 commented on GitHub (Dec 3, 2025): I think it was a configuration error on my part, I think related to the fact that our backend is on a different domain from our frontend. Sorry about that!
Author
Owner

@ceIia commented on GitHub (Dec 4, 2025):

@ThomasBurgess2000 would you be okay sharing more details about how you fixed this?
i think we share a similar setup, but i have been stuck since yesterday with it!

@ceIia commented on GitHub (Dec 4, 2025): @ThomasBurgess2000 would you be okay sharing more details about how you fixed this? i think we share a similar setup, but i have been stuck since yesterday with it!
Author
Owner

@ilaloov commented on GitHub (Dec 6, 2025):

Same issue here on 1.4.5 with Expo and stateless setup. Downgrading to 1.3.18 also fixed the issue, as previously mentioned, without any code changes.

@ilaloov commented on GitHub (Dec 6, 2025): Same issue here on 1.4.5 with Expo and stateless setup. Downgrading to 1.3.18 also fixed the issue, as previously mentioned, without any code changes.
Author
Owner

@Novianto778 commented on GitHub (Dec 7, 2025):

Downgrading to 1.3.* is work on hono and nextjs

@Novianto778 commented on GitHub (Dec 7, 2025): Downgrading to 1.3.* is work on hono and nextjs
Author
Owner

@Shinchan3102 commented on GitHub (Dec 9, 2025):

Hey @ThomasBurgess2000 @ceIia @ilaloov have you found any solution for this? I am using tanstack start and my domain for backend and frontend are same but still i am getting the issue, it's fixed with samesite=none setup but is there any workaround with samesite=lax?

@Shinchan3102 commented on GitHub (Dec 9, 2025): Hey @ThomasBurgess2000 @ceIia @ilaloov have you found any solution for this? I am using tanstack start and my domain for backend and frontend are same but still i am getting the issue, it's fixed with samesite=none setup but is there any workaround with samesite=lax?
Author
Owner

@ceIia commented on GitHub (Dec 9, 2025):

@Shinchan3102 account.skipStateCookieCheck: true did allow me to make Google OAuth work locally - haven't tried in production yet.

note: i'm using Expo and have auth on a different domain (well, technically an other localhost port)

@ceIia commented on GitHub (Dec 9, 2025): @Shinchan3102 `account.skipStateCookieCheck: true` did allow me to make Google OAuth work locally - haven't tried in production yet. note: i'm using Expo and have auth on a different domain (well, technically an other localhost port)
Author
Owner

@ilaloov commented on GitHub (Dec 9, 2025):

@Shinchan3102 no, except by downgrading to 1.3.18. I also tried 1.4.6 and the issue persists. @ceIia, do you use stateless? I tried your suggestion, but the issue persists.

@ilaloov commented on GitHub (Dec 9, 2025): @Shinchan3102 no, except by downgrading to 1.3.18. I also tried 1.4.6 and the issue persists. @ceIia, do you use [stateless](https://www.better-auth.com/docs/concepts/session-management#stateless-session-management)? I tried your suggestion, but the issue persists.
Author
Owner

@DanielBoxer commented on GitHub (Dec 13, 2025):

Setting skipStateCookieCheck: true worked for me with separate domains. It also worked in production.

I wonder if its ok to skip this check? Is there a reason it does it?

@DanielBoxer commented on GitHub (Dec 13, 2025): Setting `skipStateCookieCheck: true` worked for me with separate domains. It also worked in production. I wonder if its ok to skip this check? Is there a reason it does it?
Author
Owner

@ceIia commented on GitHub (Dec 13, 2025):

@DanielBoxer: i would not disable it in production.
184f378ef3/packages/better-auth/src/oauth2/state.ts (L173-L178)

@ilaloov: i do not use stateless.

@ceIia commented on GitHub (Dec 13, 2025): @DanielBoxer: i would not disable it in production. https://github.com/better-auth/better-auth/blob/184f378ef3c5df60533cde80bc0401a74fda2d38/packages/better-auth/src/oauth2/state.ts#L173-L178 @ilaloov: i do not use stateless.
Author
Owner

@sanjaydotpro commented on GitHub (Jan 6, 2026):

Is this being fixed in v.1.5.0?

@sanjaydotpro commented on GitHub (Jan 6, 2026): Is this being fixed in v.1.5.0?
Author
Owner

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

Is this being fixed in v.1.5.0?

Same question. I've got this error on Safari and Orion (and probably some other browsers), but not on Brave and Firefox.

@davidroulier commented on GitHub (Jan 9, 2026): > Is this being fixed in v.1.5.0? Same question. I've got this error on Safari and Orion (and probably some other browsers), but not on Brave and Firefox.
Author
Owner

@Bekacru commented on GitHub (Feb 2, 2026):

We're working on a fix for expo on 1.5

@Bekacru commented on GitHub (Feb 2, 2026): We're working on a fix for expo on 1.5
Author
Owner

@pranavgoel29 commented on GitHub (Feb 16, 2026):

Does anyone have solution for this when having multi-domain setup? (not sub-domain), I overcame the prev cookie not being send cross domain even with same site set to none issue with the proxy but this persists.

@pranavgoel29 commented on GitHub (Feb 16, 2026): Does anyone have solution for this when having multi-domain setup? (not sub-domain), I overcame the prev cookie not being send cross domain even with same site set to none issue with the proxy but this persists.
Author
Owner

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

You'll have to disable state-mismatch checks entirely for your case.
The purpose of the state-mismatch check is to ensure the oauth flow starts and ends on the same domain & browser.

If you sign-in via oauth on domain-a.com you'll be redirected to the oauth page, then redirected to your auth server at domain-b.com/api/auth/callback/... at which case the state cookie wouldn't exist so your error occurs

@pranavgoel29

@ping-maxwell commented on GitHub (Feb 19, 2026): You'll have to disable state-mismatch checks entirely for your case. The purpose of the state-mismatch check is to ensure the oauth flow starts and ends on the same domain & browser. If you sign-in via oauth on `domain-a.com` you'll be redirected to the oauth page, then redirected to your auth server at `domain-b.com/api/auth/callback/...` at which case the `state` cookie wouldn't exist so your error occurs @pranavgoel29
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2444