{"record":{"id":"110a05ccacdbca0e","repo":"mastra-ai/mastra","slug":"invalid-state-token-signature","errorCode":null,"errorMessage":"Invalid state token signature","messagePattern":"Invalid state token signature","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"auth/clerk/src/index.ts","lineNumber":162,"sourceCode":"}\n\n/**\n * Verify and decode a state token.\n * Returns the original state and redirectUri if valid and not expired.\n */\nasync function verifyStateToken(\n  stateToken: string,\n  secret: string,\n): Promise<{ 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;\n  const expectedSig = await hmacSign(payloadB64!, secret);\n  if (!timingSafeEqual(signature!, expectedSig)) {\n    throw new Error('Invalid state token signature');\n  }\n\n  const payload = JSON.parse(atob(payloadB64!)) as StatePayload;\n  if (payload.e < Date.now()) {\n    throw new Error('State token has expired');\n  }\n\n  return { originalState: payload.s, redirectUri: payload.r };\n}\n\n/**\n * Escape special regex characters in a string.\n */\nfunction escapeRegex(str: string): string {\n  return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/auth/clerk/src/index.ts#L144-L180","documentation":"After confirming the two-part format, verifyStateToken recomputes the HMAC-SHA256 signature of the base64 payload with the provider secret and compares it with timingSafeEqual. A mismatch means the state token was forged or altered (or was signed with a different secret), so the provider rejects the OAuth callback to prevent CSRF.","triggerScenarios":"verifyStateToken(stateToken, secret) where timingSafeEqual(signature, expectedSig) is false — state payload/signature tampered with, provider secret changed between flow start and callback (multi-instance deploy with different secrets/env configs), or a state minted by another environment (staging token validated in prod).","commonSituations":"Rotating or mismatching the Clerk provider secret across server replicas so tokens signed by instance A fail on instance B; staging-to-prod URL reuse; attackers modifying the base64 payload; expired flows replayed after the signature is recomputed with a rotated key.","solutions":["Ensure all server instances use the identical provider secret (same env var value) so signatures validate cluster-wide.","Restart the OAuth flow to obtain a fresh state token signed with the current secret.","Confirm the callback hit the same environment/tenant that initiated the flow (no cross-environment state reuse).","If this fires for legitimate users, check for intermediaries rewriting the state query parameter."],"exampleFix":"// before: secret differs between the instance that issued state and the one validating it\n// instance A: new MastraAuthClerk({ secretKey: 'old-secret' })\n// instance B: new MastraAuthClerk({ secretKey: 'new-secret' })\n\n// after: share one secret via env across all replicas\nconst auth = new MastraAuthClerk({ secretKey: process.env.CLERK_AUTH_SECRET });","handlingStrategy":"try-catch","validationCode":"if (process.env.CLERK_AUTH_SECRET === undefined || process.env.CLERK_AUTH_SECRET.length < 32) {\n  throw new Error('CLERK_AUTH_SECRET must be set identically on all instances before handling OAuth callbacks');\n}","typeGuard":"function isStateSignatureError(e: unknown): e is Error {\n  return e instanceof Error && e.message === 'Invalid state token signature';\n}","tryCatchPattern":"try {\n  const { redirectUri } = await verifyStateToken(state, secret);\n} catch (e) {\n  if (isStateSignatureError(e)) {\n    // likely forged or secret mismatch across replicas; do not proceed with OAuth\n    return respondBadRequest('state signature mismatch — restart OAuth sign-in');\n  }\n  throw e;\n}","preventionTips":["Deploy the identical provider secret to every replica (managed secrets, no per-instance values).","Rotate secrets in a coordinated rollout and invalidate in-flight OAuth flows.","Never accept state tokens across environments; treat signature failure as a potential CSRF attempt and log it."],"tags":["oauth","csrf","clerk","hmac","signature-verification"],"backgroundTag":"invalid-csrf-state-token","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}