[GH-ISSUE #6770] Missing account data related fields in account_data cookie which generates Account Not Found message #10621

Closed
opened 2026-04-13 06:51:50 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @dikiigr on GitHub (Dec 15, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/6770

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Hi, I am doing integration with Fusionauth provider using Nextjs 16 but having problems with access access token via auth.api.getAccessToken on the page.tsx receiving Account Not Found

Steps:

  1. Login using getSession call
  2. Works as expected
  3. Logout at the same time using await authClient.signOut()
  4. Getting Account not found error and account_data token missing required params
  5. Wait 10 minutes
  6. Clear cache
  7. Login as usual
  8. Works as expected

Current vs. Expected behavior

When I am receireceiving Account Not Found via api call account_data cookie looks like:

Account Cookie {
  idToken: '*',
  accessToken: '*',
  refreshToken: '*',
  accessTokenExpiresAt: '2025-12-15T10:02:08.703Z',
  scope: 'openid,email,profile,offline_access',
  iat: 1765789329,
  exp: 1766394129,
  jti: '4bf25a9f-cf1a-4bf0-bb8b-0001a1f6ddf7'
}

So it is missing providerId, accountId and userId. But when I wait like 10 mins clean all cookies and do login again using getSession call I am getting full info which not throwing Account Not Found issue:

Account Cookie {
  accountId: '*',
  providerId: 'fusionauth',
  userId: '*',
  accessToken: '*',
  refreshToken: '*',
  idToken: '*',
  accessTokenExpiresAt: '2025-12-15T10:24:58.516Z',
  scope: 'openid,email,profile,offline_access',
  createdAt: '2025-12-15T09:24:59.519Z',
  updatedAt: '2025-12-15T09:24:59.519Z',
  id: 'opPa34mz0kiIaYszSzrkIrizZurNg3Dx',
  iat: 1765790699,
  exp: 1766395499,
  jti: '6703da8c-35af-4d38-8a43-23ebf650fca7'
}

Versions that I am using are:

"better-auth": "^1.4.7",
"next": "^16.0.10",

I am verifying cookies using code:

const getTokenPayload = (token: string) =>
  JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString())

export const getAccessToken = async (): Promise<string | undefined> => {
  const cookieStore = await cookies()
  const accountCookie =
    cookieStore.getAll().find((c) => c.name.includes('better-auth.account_data'))?.value ?? ''
  if (!accountCookie) {
    return ''
  }

  const account = await symmetricDecodeJWT(
    accountCookie,
    process.env.BETTER_AUTH_SECRET,
    'better-auth-account',
  )

  console.log('Account Cookie', account)

  if (new Date(account.accessTokenExpiresAt).getTime() - Date.now() < 5_000) {
    const { accessToken: newToken } = await auth.api.refreshToken({
      body: { providerId: 'fusionauth' },
    })
    return newToken
  }

  return account.accessToken
}

After getting account cookie like this I am calling api:

  const account = await auth.api.getAccessToken({
    body: { providerId: 'fusionauth' },
    headers: await headers(),
  })

  console.log('Account API', account)

And it is throwing Account not found if missing all account data info

Maybe there is some kind of cache which blocks to populate all data for account_data cookie?

I am using stateless integration

What version of Better Auth are you using?

1.4.7

System info

{
  "system": {
    "platform": "darwin",
    "arch": "arm64",
    "version": "Darwin Kernel Version 24.6.0: Wed Oct 15 21:12:06 PDT 2025; root:xnu-11417.140.69.703.14~1/RELEASE_ARM64_T6000",
    "release": "24.6.0",
    "cpuCount": 8,
    "cpuModel": "Apple M1 Pro",
    "totalMemory": "16.00 GB",
    "freeMemory": "0.29 GB"
  },
  "node": {
    "version": "v25.2.1",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.6.2"
  },
  "frameworks": [
    {
      "name": "next",
      "version": "^16.0.10"
    },
    {
      "name": "react",
      "version": "^19.2.3"
    }
  ],
  "databases": null,
  "betterAuth": {
    "version": "^1.4.7",
    "config": null
  }
}

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

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"

export const auth = betterAuth({
  baseURL: process.env.BETTER_AUTH_URL || 'http://localhost:3000',
  trustedOrigins: [process.env.BETTER_AUTH_URL, 'http://localhost:3000'],
  debug: process.env.NODE_ENV !== 'production',
  logger: {
    disabled: false,
    level: process.env.LOG_LEVEL,
    log(level, message, ...args) {
      const logger = getLogger()
      if (logger[level]) {
        logger[level](message, ...args)
      }
    },
  },
  onAPIError: {
    onError: (error) => {
      getLogger().error({ error }, 'Better Auth Get Error')
    },
  },
  account: {
    storeStateStrategy: 'cookie',
    storeAccountCookie: true,
    updateAccountOnSignIn: true,
  },
  session: {
    cookieCache: {
      enabled: true,
      maxAge: 7 * 24 * 60 * 60,
      refreshCache: true,
      version: '1',
    },
  },
  plugins: [
    authLoggerPlugin(getLogger()),
    genericOAuth({
      config: [
        {
          providerId: 'fusionauth',
          clientId: process.env.FUSIONAUTH_CLIENT_ID,
          clientSecret: process.env.FUSIONAUTH_CLIENT_SECRET,
          discoveryUrl: `${process.env.FUSIONAUTH_URL}/.well-known/openid-configuration/${process.env.FUSIONAUTH_TENANT_ID}`,
          scopes: ['openid', 'email', 'profile', 'offline_access'],
          accessType: 'offline',
          mapProfileToUser: (profile) => ({
            email: profile.email || 'undefined',
            name: profile.name || profile.email,
          }),
        },
      ],
    }),
    nextCookies(),
  ],
})

Additional context

No response

Originally created by @dikiigr on GitHub (Dec 15, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/6770 ### Is this suited for github? - [ ] Yes, this is suited for github ### To Reproduce Hi, I am doing integration with Fusionauth provider using Nextjs 16 but having problems with access access token via `auth.api.getAccessToken` on the page.tsx receiving `Account Not Found` Steps: 1. Login using `getSession` call 2. Works as expected 3. Logout at the same time using `await authClient.signOut()` 4. Getting Account not found error and account_data token missing required params 5. Wait 10 minutes 6. Clear cache 7. Login as usual 8. Works as expected ### Current vs. Expected behavior When I am receireceiving `Account Not Found` via api call account_data cookie looks like: ``` Account Cookie { idToken: '*', accessToken: '*', refreshToken: '*', accessTokenExpiresAt: '2025-12-15T10:02:08.703Z', scope: 'openid,email,profile,offline_access', iat: 1765789329, exp: 1766394129, jti: '4bf25a9f-cf1a-4bf0-bb8b-0001a1f6ddf7' } ``` So it is missing `providerId`, `accountId` and `userId`. But when I wait like 10 mins clean all cookies and do login again using `getSession` call I am getting full info which not throwing Account Not Found issue: ``` Account Cookie { accountId: '*', providerId: 'fusionauth', userId: '*', accessToken: '*', refreshToken: '*', idToken: '*', accessTokenExpiresAt: '2025-12-15T10:24:58.516Z', scope: 'openid,email,profile,offline_access', createdAt: '2025-12-15T09:24:59.519Z', updatedAt: '2025-12-15T09:24:59.519Z', id: 'opPa34mz0kiIaYszSzrkIrizZurNg3Dx', iat: 1765790699, exp: 1766395499, jti: '6703da8c-35af-4d38-8a43-23ebf650fca7' } ``` Versions that I am using are: ``` "better-auth": "^1.4.7", "next": "^16.0.10", ``` I am verifying cookies using code: ```typescript const getTokenPayload = (token: string) => JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()) export const getAccessToken = async (): Promise<string | undefined> => { const cookieStore = await cookies() const accountCookie = cookieStore.getAll().find((c) => c.name.includes('better-auth.account_data'))?.value ?? '' if (!accountCookie) { return '' } const account = await symmetricDecodeJWT( accountCookie, process.env.BETTER_AUTH_SECRET, 'better-auth-account', ) console.log('Account Cookie', account) if (new Date(account.accessTokenExpiresAt).getTime() - Date.now() < 5_000) { const { accessToken: newToken } = await auth.api.refreshToken({ body: { providerId: 'fusionauth' }, }) return newToken } return account.accessToken } ``` After getting account cookie like this I am calling api: ```typescript const account = await auth.api.getAccessToken({ body: { providerId: 'fusionauth' }, headers: await headers(), }) console.log('Account API', account) ``` And it is throwing Account not found if missing all account data info Maybe there is some kind of cache which blocks to populate all data for account_data cookie? I am using stateless integration ### What version of Better Auth are you using? 1.4.7 ### System info ```bash { "system": { "platform": "darwin", "arch": "arm64", "version": "Darwin Kernel Version 24.6.0: Wed Oct 15 21:12:06 PDT 2025; root:xnu-11417.140.69.703.14~1/RELEASE_ARM64_T6000", "release": "24.6.0", "cpuCount": 8, "cpuModel": "Apple M1 Pro", "totalMemory": "16.00 GB", "freeMemory": "0.29 GB" }, "node": { "version": "v25.2.1", "env": "development" }, "packageManager": { "name": "npm", "version": "11.6.2" }, "frameworks": [ { "name": "next", "version": "^16.0.10" }, { "name": "react", "version": "^19.2.3" } ], "databases": null, "betterAuth": { "version": "^1.4.7", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ baseURL: process.env.BETTER_AUTH_URL || 'http://localhost:3000', trustedOrigins: [process.env.BETTER_AUTH_URL, 'http://localhost:3000'], debug: process.env.NODE_ENV !== 'production', logger: { disabled: false, level: process.env.LOG_LEVEL, log(level, message, ...args) { const logger = getLogger() if (logger[level]) { logger[level](message, ...args) } }, }, onAPIError: { onError: (error) => { getLogger().error({ error }, 'Better Auth Get Error') }, }, account: { storeStateStrategy: 'cookie', storeAccountCookie: true, updateAccountOnSignIn: true, }, session: { cookieCache: { enabled: true, maxAge: 7 * 24 * 60 * 60, refreshCache: true, version: '1', }, }, plugins: [ authLoggerPlugin(getLogger()), genericOAuth({ config: [ { providerId: 'fusionauth', clientId: process.env.FUSIONAUTH_CLIENT_ID, clientSecret: process.env.FUSIONAUTH_CLIENT_SECRET, discoveryUrl: `${process.env.FUSIONAUTH_URL}/.well-known/openid-configuration/${process.env.FUSIONAUTH_TENANT_ID}`, scopes: ['openid', 'email', 'profile', 'offline_access'], accessType: 'offline', mapProfileToUser: (profile) => ({ email: profile.email || 'undefined', name: profile.name || profile.email, }), }, ], }), nextCookies(), ], }) ``` ### Additional context _No response_
GiteaMirror added the locked label 2026-04-13 06:51:50 -05:00
Author
Owner

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

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

This is a known issue in stateless/cookie-cached setups with better-auth, especially when account.updateAccountOnSignIn is set to true. During a quick logout and login, the account_data cookie can be overwritten with a payload that only includes token fields, dropping essential identifiers like providerId, accountId, and userId. This leads to the "Account Not Found" error on getAccessToken calls, since the API can't match the account without those fields. The stale/incomplete cookie persists until it expires (default 5 minutes) or is cleared, which is why waiting and clearing cache resolves the problem temporarily [#6252, #6188].

Workarounds:

  • Set account.updateAccountOnSignIn to false to prevent the cookie from being overwritten with incomplete data [#6252].
  • Make sure all cookies are fully cleared on logout.
  • For a more robust solution, use persistent storage for user/session data, or ensure your client supplies all necessary identifiers if you must stay stateless [#6188].
  • Upgrading to a version with PRs like #6253 and #6016 merged may help, but this bug can still occur if your flow overwrites the cookie with a truncated payload.

Best practice: In stateless mode, always ensure the account_data cookie is fully refreshed with all required fields after sign-in, and avoid flows that might overwrite it with partial data. If you need to keep the cookie alive, proactively refresh the provider token before expiry [discussion].

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:3654710131 --> @dosubot[bot] commented on GitHub (Dec 15, 2025): <!-- Greeting --> Hi @dikiigr! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> This is a known issue in stateless/cookie-cached setups with better-auth, especially when `account.updateAccountOnSignIn` is set to `true`. During a quick logout and login, the account_data cookie can be overwritten with a payload that only includes token fields, dropping essential identifiers like `providerId`, `accountId`, and `userId`. This leads to the "Account Not Found" error on `getAccessToken` calls, since the API can't match the account without those fields. The stale/incomplete cookie persists until it expires (default 5 minutes) or is cleared, which is why waiting and clearing cache resolves the problem temporarily [[#6252](https://github.com/better-auth/better-auth/issues/6252), [#6188](https://github.com/better-auth/better-auth/issues/6188)]. Workarounds: - Set `account.updateAccountOnSignIn` to `false` to prevent the cookie from being overwritten with incomplete data [[#6252](https://github.com/better-auth/better-auth/issues/6252)]. - Make sure all cookies are fully cleared on logout. - For a more robust solution, use persistent storage for user/session data, or ensure your client supplies all necessary identifiers if you must stay stateless [[#6188](https://github.com/better-auth/better-auth/issues/6188)]. - Upgrading to a version with PRs like [#6253](https://github.com/better-auth/better-auth/pull/6253) and [#6016](https://github.com/better-auth/better-auth/pull/6016) merged may help, but this bug can still occur if your flow overwrites the cookie with a truncated payload. Best practice: In stateless mode, always ensure the account_data cookie is fully refreshed with all required fields after sign-in, and avoid flows that might overwrite it with partial data. If you need to keep the cookie alive, proactively refresh the provider token before expiry [[discussion](https://github.com/better-auth/better-auth/discussions/6715)]. <!-- 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/e771b206-937d-42a1-9868-a4692896f87c?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/e771b206-937d-42a1-9868-a4692896f87c?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/e771b206-937d-42a1-9868-a4692896f87c?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/e771b206-937d-42a1-9868-a4692896f87c?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/e771b206-937d-42a1-9868-a4692896f87c?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/e771b206-937d-42a1-9868-a4692896f87c?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/e771b206-937d-42a1-9868-a4692896f87c?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%20known%20issue%20in%20stateless/cookie-cached%20setups%20with%20better-auth%2C%20especially%20when%20%60account.updateAccountOnSignIn%60%20is%20set%20to%20%60true%60.%20During%20a%20quick%20logout%20and%20login%2C%20the%20account_data%20cookie%20can%20be%20overwritten%20with%20a%20payload%20that%20only%20includes%20token%20fields%2C%20dropping%20essential%20identifiers%20like%20%60providerId%60%2C%20%60accountId%60%2C%20and%20%60userId%60.%20This%20leads%20to%20the%20%22Account%20Not%20Found%22%20error%20on%20%60getAccessToken%60%20calls%2C%20since%20the%20API%20can%27t%20match%20the%20account%20without%20those%20fields.%20The%20stale/incomplete%20cookie%20persists%20until%20it%20expires%20%28default%205%20minutes%29%20or%20is%20cleared%2C%20which%20is%20why%20waiting%20and%20clearing%20cache%20resolves%20the%20problem%20temporarily%20%5B%5B%236252%5D%28https%3A//github.com/better-auth/better-auth/issues/6252%29%2C%20%5B%236188%5D%28https%3A//github.com/better-auth/better-auth/issues/6188%29%5D.%0A%0AWorkarounds%3A%0A-%20Set%20%60account.updateAccountOnSignIn%60%20to%20%60false%60%20to%20prevent%20the%20cookie%20from%20being%20overwritten%20with%20incomplete%20data%20%5B%5B%236252%5D%28https%3A//github.com/better-auth/better-auth/issues/6252%29%5D.%0A-%20Make%20sure%20all%20cookies%20are%20fully%20cleared%20on%20logout.%0A-%20For%20a%20more%20robust%20solution%2C%20use%20persistent%20storage%20for%20user/session%20data%2C%20or%20ensure%20your%20client%20supplies%20all%20necessary%20identifiers%20if%20you%20must%20stay%20stateless%20%5B%5B%236188%5D%28https%3A//github.com/better-auth/better-auth/issues/6188%29%5D.%0A-%20Upgrading%20to%20a%20version%20with%20PRs%20like%20%5B%236253%5D%28https%3A//github.com/better-auth/better-auth/pull/6253%29%20and%20%5B%236016%5D%28https%3A//github.com/better-auth/better-auth/pull/6016%29%20merged%20may%20help%2C%20but%20this%20bug%20can%20still%20occur%20if%20your%20flow%20overwrites%20the%20cookie%20with%20a%20truncated%20payload.%0A%0ABest%20practice%3A%20In%20stateless%20mode%2C%20always%20ensure%20the%20account_data%20cookie%20is%20fully%20refreshed%20with%20all%20required%20fields%20after%20sign-in%2C%20and%20avoid%20flows%20that%20might%20overwrite%20it%20with%20partial%20data.%20If%20you%20need%20to%20keep%20the%20cookie%20alive%2C%20proactively%20refresh%20the%20provider%20token%20before%20expiry%20%5B%5Bdiscussion%5D%28https%3A//github.com/better-auth/better-auth/discussions/6715%29%5D.)&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/6770)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10621