{"record":{"id":"3297e36e023f1d35","repo":"mastra-ai/mastra","slug":"invalid-state-token-payload","errorCode":null,"errorMessage":"Invalid state token payload","messagePattern":"Invalid state token payload","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/auth0/src/index.ts","lineNumber":138,"sourceCode":"  const parts = stateToken.split('.');\n  if (parts.length !== 2) {\n    throw new Error('Invalid state token format');\n  }\n\n  const [payloadB64, signature] = parts as [string, string];\n\n  // Verify signature\n  const expectedSig = hmacSign(payloadB64, secret);\n  if (!timingSafeEqual(signature, expectedSig)) {\n    throw new Error('Invalid or tampered state token');\n  }\n\n  // Decode and check expiry\n  let payload: StatePayload;\n  try {\n    payload = JSON.parse(atob(payloadB64)) as StatePayload;\n  } catch {\n    throw new Error('Invalid state token payload');\n  }\n\n  if (payload.e < Date.now()) {\n    throw new Error('State token has expired');\n  }\n\n  return {\n    originalState: payload.s,\n    redirectUri: payload.r,\n  };\n}\n\n/**\n * Simple HMAC-SHA256 using Web Crypto (sync wrapper for predictable use).\n * Returns base64url-encoded signature.\n */\nfunction hmacSign(data: string, secret: string): string {\n  // Use a simple hash-based approach that works synchronously","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/auth/auth0/src/index.ts#L120-L156","documentation":"Once the state token's signature verifies, the base64 payload is JSON-parsed into a StatePayload ({s, r, e}). If the payload is not valid base64-encoded JSON (or atob/JSON.parse throws), verifyStateToken throws 'Invalid state token payload'. This is distinct from the format and signature errors: the token looks structurally fine and authentic, but its content is unreadable.","triggerScenarios":"A token signed correctly but whose payload decodes to non-JSON (hand-rolled token signing someone else's payload string with hmacSign), a payload encoded with base64url or UTF-8-safe encodings incompatible with atob, or corrupted payload characters introduced in transit.","commonSituations":"Custom tooling or tests that sign arbitrary strings instead of using createStateToken; an intermediary that mangles the state parameter; a future/other version of the library changed the payload schema while old tokens still pass signature checks with the same secret.","solutions":["Generate state tokens only via createStateToken — don't hand-assemble base64 payloads and sign them yourself.","Ensure the state value survives the HTTP round trip unchanged (proper URL encoding of '.' and '+', no proxy rewriting).","Handle the error as a failed login: reject the callback with a 4xx and restart the OAuth flow; the payload is unrecoverable by design.","If you upgraded the library, invalidate in-flight sessions/tokens created by the old payload format.","Distinguish this catch from expiry: this error means undecodable payload, while 'State token has expired' (payload.e < Date.now()) means a valid but stale token — both resolve by restarting login."],"exampleFix":"// before\nconst { originalState, redirectUri } = verifyStateToken(state, secret); // throws 'Invalid state token payload'\n// after\ntry {\n  var { originalState, redirectUri } = verifyStateToken(state, secret);\n} catch {\n  return Response.redirect('/login'); // restart OAuth flow\n}","handlingStrategy":"try-catch","validationCode":"function statePayloadLooksValid(v) {\n  if (!isStateToken(v)) return false;\n  try {\n    const [b64] = v.split('.');\n    const payload = JSON.parse(atob(b64));\n    return typeof payload.e === 'number' && typeof payload.s === 'string' && typeof payload.r === 'string';\n  } catch {\n    return false;\n  }\n}","typeGuard":"function isStatePayload(p: unknown): p is { s: string; r: string; e: number } {\n  return typeof p === 'object' && p !== null &&\n    typeof (p as any).s === 'string' &&\n    typeof (p as any).r === 'string' &&\n    typeof (p as any).e === 'number';\n}","tryCatchPattern":"try {\n  const { originalState, redirectUri } = verifyStateToken(state, secret);\n} catch (err) {\n  // covers 'Invalid state token payload' and 'State token has expired'\n  return Response.redirect(new URL('/login', req.url));\n}","preventionTips":["Always mint state tokens with createStateToken; never sign custom payloads.","Check token age client-side is unnecessary — treat any payload/parse/expiry error identically by restarting login.","Invalidate tokens from old library versions after upgrades that touch the payload schema.","Return the user to the login flow on any state verification failure rather than surfacing a raw 500."],"tags":["auth0","oauth","state-token","base64","json-parsing"],"backgroundTag":"invalid-oauth-state-payload","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}