[GH-ISSUE #8727] storeIdentifier: "hashed" breaks OAuth social sign-in (state_security_mismatch) #28495

Closed
opened 2026-04-17 19:56:52 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @BrahmaputraXXX on GitHub (Mar 21, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8727

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

export const auth = betterAuth({
    verification: {
        storeIdentifier: "hashed",
    },
    socialProviders: {
        github: {
            clientId: "...",
            clientSecret: "...",
        },
    },
});

Current vs. Expected behavior

	hooks: {
		before: createAuthMiddleware(async (ctx) => {
			console.log("Before hook:", ctx.path, ctx.headers?.get("cookie"));
			
		}),
	},

Callback fails with:
→ Before hook: /callback/:id auth.state=QAekgUF8rHDDXUFJq...
2026-03-21T20:53:04.560Z ERROR [Better Auth]: Failed to parse state [StateError [BetterAuthError]: State mismatch: State not persisted correctly] {
code: 'state_security_mismatch',
details: { state: 'gWR4rq7yWD7gCKeF2OAsouFlM5h180Zkj5IirKTIhQU' }
}

What version of Better Auth are you using?

1.5.5

System info

{
  "system": {
    "platform": "win32",
    "arch": "x64",
    "version": "Windows 11 Pro",
    "release": "10.0.26200",
    "cpuCount": 8,
    "cpuModel": "12th Gen Intel(R) Core(TM) i3-12100F",
    "totalMemory": "31.84 GB",
    "freeMemory": "7.02 GB"
  },
  "node": {
    "version": "v22.20.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.3"
  },
  "frameworks": [
    {
      "name": "react",
      "version": "^19.2.0"
    }
  ],
  "databases": [
    {
      "name": "@prisma/client",
      "version": "^7.4.2"
    }
  ],

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

Documentation, Backend

Auth config (if applicable)


Additional context

The docs for storeIdentifier describe it as applying to

tokens (OTP, magic-link, etc.) with no mention of it affecting OAuth state. There is no warning that enabling "hashed" breaks social sign-in.

The overrides option in storeIdentifier cannot work around this either, since OAuth state identifiers are random strings with no distinguishing prefix for startsWith() matching.

And the workaround it to use account.storeStateStrategy: "cookie" bypasses the verification table entirely for OAuth state, avoiding the issue.

Originally created by @BrahmaputraXXX on GitHub (Mar 21, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8727 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce ``` export const auth = betterAuth({ verification: { storeIdentifier: "hashed", }, socialProviders: { github: { clientId: "...", clientSecret: "...", }, }, }); ``` ### Current vs. Expected behavior ``` hooks: { before: createAuthMiddleware(async (ctx) => { console.log("Before hook:", ctx.path, ctx.headers?.get("cookie")); }), }, ``` Callback fails with: → Before hook: /callback/:id auth.state=QAekgUF8rHDDXUFJq... 2026-03-21T20:53:04.560Z ERROR [Better Auth]: Failed to parse state [StateError [BetterAuthError]: State mismatch: State not persisted correctly] { code: 'state_security_mismatch', details: { state: 'gWR4rq7yWD7gCKeF2OAsouFlM5h180Zkj5IirKTIhQU' } } ### What version of Better Auth are you using? 1.5.5 ### System info ```bash { "system": { "platform": "win32", "arch": "x64", "version": "Windows 11 Pro", "release": "10.0.26200", "cpuCount": 8, "cpuModel": "12th Gen Intel(R) Core(TM) i3-12100F", "totalMemory": "31.84 GB", "freeMemory": "7.02 GB" }, "node": { "version": "v22.20.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.3" }, "frameworks": [ { "name": "react", "version": "^19.2.0" } ], "databases": [ { "name": "@prisma/client", "version": "^7.4.2" } ], ``` ### Which area(s) are affected? (Select all that apply) Documentation, Backend ### Auth config (if applicable) ```typescript ``` ### Additional context > The [docs for storeIdentifier](https://better-auth.com/docs/reference/options#verification) describe it as applying to > > tokens (OTP, magic-link, etc.) with no mention of it affecting OAuth state. There is no warning that enabling "hashed" breaks social sign-in. > > The **overrides** option in storeIdentifier cannot work around this either, since OAuth state identifiers are random strings with no distinguishing prefix for startsWith() matching. > > And the workaround it to use account.storeStateStrategy: "cookie" bypasses the verification table entirely for OAuth state, avoiding the issue. > >
GiteaMirror added the bugoauth labels 2026-04-17 19:56:52 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Mar 21, 2026):

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

Thanks for the detailed report! This is indeed a real issue - when OAuth state is stored in the verification table (the default when a database is configured), setting storeIdentifier: "hashed" causes the state lookup to fail during the callback because the identifier gets hashed inconsistently between storage and retrieval.

Your workaround is correct. Using account.storeStateStrategy: "cookie" bypasses the verification table for OAuth state entirely, storing it in an encrypted cookie instead:

export const auth = betterAuth({
    account: {
        storeStateStrategy: "cookie"
    },
    verification: {
        storeIdentifier: "hashed" // Now only affects OTP/magic-link tokens
    },
    socialProviders: {
        github: { /* ... */ }
    }
});

You're also right that the overrides option doesn't help here since OAuth state identifiers are random strings without a distinguishing prefix. This seems like it could benefit from either documentation clarifying this limitation, or potentially supporting a built-in override for OAuth state specifically.

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:4104400112 --> @dosubot[bot] commented on GitHub (Mar 21, 2026): <!-- Greeting --> Hi @BrahmaputraXXX! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Thanks for the detailed report! This is indeed a real issue - when OAuth state is stored in the verification table (the default when a database is configured), setting `storeIdentifier: "hashed"` causes the state lookup to fail during the callback because the identifier gets hashed inconsistently between storage and retrieval. Your workaround is correct. Using [`account.storeStateStrategy: "cookie"`](https://github.com/better-auth/better-auth/blob/3d4489bd87de6ecc504d794517649f634917f3d4/packages/core/src/types/init-options.ts#L1107) bypasses the verification table for OAuth state entirely, storing it in an [encrypted cookie](https://github.com/better-auth/better-auth/blob/3d4489bd87de6ecc504d794517649f634917f3d4/packages/better-auth/src/state.ts#L59-L79) instead: ```typescript export const auth = betterAuth({ account: { storeStateStrategy: "cookie" }, verification: { storeIdentifier: "hashed" // Now only affects OTP/magic-link tokens }, socialProviders: { github: { /* ... */ } } }); ``` You're also right that the `overrides` option doesn't help here since OAuth state identifiers are random strings without a distinguishing prefix. This seems like it could benefit from either documentation clarifying this limitation, or potentially supporting a built-in override for OAuth state specifically. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=brand-link).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/4f53c18f-593b-4c25-af34-6bc9aba306b2?feedback_type=great_response&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/4f53c18f-593b-4c25-af34-6bc9aba306b2?feedback_type=irrelevant_answer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/4f53c18f-593b-4c25-af34-6bc9aba306b2?feedback_type=incorrect_sources&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/4f53c18f-593b-4c25-af34-6bc9aba306b2?feedback_type=too_verbose&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/4f53c18f-593b-4c25-af34-6bc9aba306b2?feedback_type=hallucination&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/4f53c18f-593b-4c25-af34-6bc9aba306b2?feedback_type=bug_report&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-bug_report) | [Other](https://app.dosu.dev/response-feedback/4f53c18f-593b-4c25-af34-6bc9aba306b2?feedback_type=other&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-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&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=chat-badge)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Thanks%20for%20the%20detailed%20report%21%20This%20is%20indeed%20a%20real%20issue%20-%20when%20OAuth%20state%20is%20stored%20in%20the%20verification%20table%20%28the%20default%20when%20a%20database%20is%20configured%29%2C%20setting%20%60storeIdentifier%3A%20%22hashed%22%60%20causes%20the%20state%20lookup%20to%20fail%20during%20the%20callback%20because%20the%20identifier%20gets%20hashed%20inconsistently%20between%20storage%20and%20retrieval.%0A%0AYour%20workaround%20is%20correct.%20Using%20%5B%60account.storeStateStrategy%3A%20%22cookie%22%60%5D%28https%3A//github.com/better-auth/better-auth/blob/3d4489bd87de6ecc504d794517649f634917f3d4/packages/core/src/types/init-options.ts%23L1107%29%20bypasses%20the%20verification%20table%20for%20OAuth%20state%20entirely%2C%20storing%20it%20in%20an%20%5Bencrypted%20cookie%5D%28https%3A//github.com/better-auth/better-auth/blob/3d4489bd87de6ecc504d794517649f634917f3d4/packages/better-auth/src/state.ts%23L59-L79%29%20instead%3A%0A%0A%60%60%60typescript%0Aexport%20const%20auth%20%3D%20betterAuth%28%7B%0A%20%20%20%20account%3A%20%7B%0A%20%20%20%20%20%20%20%20storeStateStrategy%3A%20%22cookie%22%0A%20%20%20%20%7D%2C%0A%20%20%20%20verification%3A%20%7B%0A%20%20%20%20%20%20%20%20storeIdentifier%3A%20%22hashed%22%20//%20Now%20only%20affects%20OTP/magic-link%20tokens%0A%20%20%20%20%7D%2C%0A%20%20%20%20socialProviders%3A%20%7B%0A%20%20%20%20%20%20%20%20github%3A%20%7B%20/%2A%20...%20%2A/%20%7D%0A%20%20%20%20%7D%0A%7D%29%3B%0A%60%60%60%0A%0AYou%27re%20also%20right%20that%20the%20%60overrides%60%20option%20doesn%27t%20help%20here%20since%20OAuth%20state%20identifiers%20are%20random%20strings%20without%20a%20distinguishing%20prefix.%20This%20seems%20like%20it%20could%20benefit%20from%20either%20documentation%20clarifying%20this%20limitation%2C%20or%20potentially%20supporting%20a%20built-in%20override%20for%20OAuth%20state%20specifically.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=join-discord)&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/8727)
Author
Owner

@bytaesu commented on GitHub (Apr 8, 2026):

Hi @BrahmaputraXXX,

It looks like this issue was resolved in PR #8980. The fix is included in v1.6, and since v1.6 is a light release, you should be able to upgrade and test it easily.

If the issue still persists, feel free to let me know 😁

<!-- gh-comment-id:4204532547 --> @bytaesu commented on GitHub (Apr 8, 2026): Hi @BrahmaputraXXX, It looks like this issue was resolved in PR #8980. The fix is included in v1.6, and since v1.6 is a light release, you should be able to upgrade and test it easily. If the issue still persists, feel free to let me know 😁
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28495