{"record":{"id":"483d8a6a34842a84","repo":"mastra-ai/mastra","slug":"invalid-state-token-format","errorCode":null,"errorMessage":"Invalid state token format","messagePattern":"Invalid state token format","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/auth0/src/index.ts","lineNumber":122,"sourceCode":"function createStateToken(originalState: string, redirectUri: string, secret: string): string {\n  const payload: StatePayload = {\n    s: originalState,\n    r: redirectUri,\n    e: Date.now() + STATE_TOKEN_EXPIRY_MS,\n  };\n  const payloadB64 = btoa(JSON.stringify(payload));\n  const signature = hmacSign(payloadB64, secret);\n  return `${payloadB64}.${signature}`;\n}\n\n/**\n * Verify and decode a state token.\n * Returns the original state and redirectUri if valid and not expired.\n */\nfunction verifyStateToken(stateToken: string, secret: string): { originalState: string; redirectUri: string } {\n  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","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/auth/auth0/src/index.ts#L104-L140","documentation":"OAuth state tokens are stateless HMAC-signed strings of the form 'base64(payload).base64(signature)'. verifyStateToken splits on '.' and requires exactly two parts; anything else cannot be a well-formed signed token, so it throws 'Invalid state token format' before any signature check.","triggerScenarios":"Passing a state value to verifyStateToken that contains zero or more than one '.' — e.g. an OAuth state generated by another library (JWTs contain dots), a raw random string without a signature, a double-encoded or re-URL-encoded token where '.' was mangled, or an empty string.","commonSituations":"Mixing CSRF state from a different auth library or a previous implementation; the round-tripped state was URL-decoded/transformed by a framework or callback handler before verification; user bookmarks an old login URL and the expired/mangled state is replayed; hand-crafting state in tests.","solutions":["Only verify state tokens produced by createStateToken of this library — raw state values and JWTs will never have the payload.signature shape.","Ensure the state parameter is passed through the OAuth round trip verbatim (no extra encode/decode) between the login redirect and the callback handler.","Check your callback route reads the 'state' query param, not another parameter or a merged value.","Clear stale bookmarks/links with old state and start a fresh login flow.","Wrap verification in try/catch and reject the callback (400) without leaking which check failed."],"exampleFix":"// before\nconst { redirectUri } = verifyStateToken(searchParams.get('state') ?? '', secret);\n// after\nconst state = searchParams.get('state');\nif (!state || state.split('.').length !== 2) {\n  return new Response('Bad state', { status: 400 });\n}\nconst { redirectUri } = verifyStateToken(state, secret);","handlingStrategy":"validation","validationCode":"function isSignedStateToken(v) {\n  return typeof v === 'string' && v.length > 0 && v.split('.').length === 2;\n}\nconst state = url.searchParams.get('state');\nif (!isSignedStateToken(state)) return new Response('Bad Request', { status: 400 });","typeGuard":"function isStateToken(v: unknown): v is string {\n  return typeof v === 'string' && /^[A-Za-z0-9+/=]+\\.[A-Za-z0-9+/=]+$/.test(v);\n}","tryCatchPattern":"try {\n  const { originalState, redirectUri } = verifyStateToken(state, secret);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Invalid state token format') {\n    return new Response('Invalid OAuth state', { status: 400 });\n  }\n  throw err;\n}","preventionTips":["Only feed tokens created by createStateToken into verifyStateToken.","Pass the OAuth state param through the redirect/callback verbatim — no extra decoding.","Never mix state formats from other auth libraries in the same flow.","Reject malformed state early with a 400 before hitting the crypto path."],"tags":["auth0","oauth","csrf","state-token","validation"],"backgroundTag":"invalid-oauth-state-token","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}