{"record":{"id":"4a8a3b23589424cf","repo":"mastra-ai/mastra","slug":"state-token-has-expired","errorCode":null,"errorMessage":"State token has expired","messagePattern":"State token has expired","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/auth0/src/index.ts","lineNumber":142,"sourceCode":"\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\n  // This is a simplified HMAC for state tokens (not for long-term secrets)\n  const encoder = new TextEncoder();\n  const keyBytes = encoder.encode(secret);\n  const dataBytes = encoder.encode(data);","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/auth/auth0/src/index.ts#L124-L160","documentation":"verifyStateToken parses a signed, base64-encoded state token created during SSO login and returns the original state and redirect URI. This error is thrown when the token's embedded expiry timestamp (payload.e) is in the past, i.e. the login flow took too long between generating the state token (getLoginUrl) and verifying it in the callback. The library expires these state tokens to prevent replay attacks and stale redirect URIs.","triggerScenarios":"Calling redirectUri() (which calls verifyStateToken) on a state token whose payload.e is less than Date.now(); typically when the user sits on the Auth0 login page longer than the token TTL before completing login, or when a bookmarked/stale callback URL is replayed after expiry.","commonSituations":"Users leaving the Auth0 consent screen open past the expiry window; replaying an old callback URL from browser history; long-running approval flows in enterprise SSO; clock skew between server instances if system clocks drift.","solutions":["Restart the login flow: call getLoginUrl again to generate a fresh signed state token and redirect the user to it","Handle this error in the SSO callback handler by redirecting the user to a fresh login URL instead of failing hard","Check for clock skew (NTP) on the server if expiries appear to happen prematurely","Increase the state token TTL in the auth server config only if the login flow legitimately needs longer than the current window"],"exampleFix":"// before\nconst { originalState, redirectUri } = authServer.redirectUri(state);\n// after\nlet redirect;\ntry {\n  redirect = authServer.redirectUri(state);\n} catch (e) {\n  if (e.message === 'State token has expired') {\n    return Response.redirect(authServer.getLoginUrl('/callback', newState()), 302);\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// State token content is signed+encoded; expiry cannot be checked beforehand without decoding.\n// Detect staleness by decoding payload if you control token creation:\nfunction isStateTokenLikelyExpired(signedState: string, ttlMs: number, issuedAt: number) {\n  return Date.now() - issuedAt > ttlMs;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const { originalState, redirectUri } = provider.redirectUri(state);\n} catch (e) {\n  if (e instanceof Error && e.message === 'State token has expired') {\n    // restart login flow\n    return redirectTo(provider.getLoginUrl(callbackUri, newState()));\n  }\n  throw e;\n}","preventionTips":["Always treat state-token expiry as 'restart login' rather than a fatal error","Keep the time between generating the login URL and completing the callback short","Never cache or bookmark state tokens/callback URLs","Sync server clocks with NTP to avoid premature expiry"],"tags":["auth0","sso","expired-token","state-validation"],"backgroundTag":"state-token-expired","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}