{"record":{"id":"bb63fd67f13a5322","repo":"mastra-ai/mastra","slug":"state-parameter-has-expired","errorCode":null,"errorMessage":"State parameter has expired","messagePattern":"State parameter has expired","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/okta/src/auth-provider.ts","lineNumber":419,"sourceCode":"    });\n\n    return `${this.endpointBase}/v1/authorize?${params.toString()}`;\n  }\n\n  /**\n   * Handle the OAuth callback from Okta.\n   * Note: The server passes only the stateId (UUID part), not the full state.\n   */\n  async handleCallback(code: string, stateId: string): Promise<SSOCallbackResult<OktaUser>> {\n    // Validate state parameter (server passes only the UUID part)\n    const stored = stateStore.get(stateId);\n    if (!stored) {\n      throw new Error('Invalid or expired state parameter');\n    }\n    stateStore.delete(stateId);\n\n    if (stored.expiresAt < Date.now()) {\n      throw new Error('State parameter has expired');\n    }\n\n    // Exchange code for tokens using client_secret (confidential client)\n    const tokenResponse = await fetch(`${this.endpointBase}/v1/token`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/x-www-form-urlencoded',\n        Authorization: `Basic ${btoa(`${this.clientId}:${this.clientSecret}`)}`,\n      },\n      body: new URLSearchParams({\n        grant_type: 'authorization_code',\n        code,\n        redirect_uri: stored.redirectUri,\n      }),\n    });\n\n    if (!tokenResponse.ok) {\n      const error = await tokenResponse.text();","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/auth/okta/src/auth-provider.ts#L401-L437","documentation":"Thrown by handleCallback when the stored state entry exists but its expiresAt timestamp has passed. The state parameter carries a TTL to prevent replay of stale authorization redirects; expired states are rejected even if still present in the store.","triggerScenarios":"Calling handleCallback(code, stateId) after the state TTL elapsed — e.g. the user sat on the IdP login page too long, the callback was delayed by network issues, or a saved bookmarked callback URL is opened much later.","commonSituations":"User leaves the Okta login tab open for a long time before completing sign-in; slow email-link based flows; clock skew between servers in unusual setups; user resumes an abandoned login session.","solutions":["Redirect the user to restart the SSO flow to mint a fresh state.","Increase the state TTL if legitimate slow logins are common (library configuration/defaults permitting).","Prompt users to complete login promptly after being redirected to Okta.","Check server clock correctness (NTP) if expiration seems premature."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await provider.handleCallback(code, stateId);\n} catch (e) {\n  if (e instanceof Error && e.message === 'State parameter has expired') {\n    // redirect to a 'session expired, please sign in again' page / re-run authorize\n  } else throw e;\n}","preventionTips":["Encourage users to complete the IdP login promptly after redirect.","Increase the state TTL configuration if your users routinely take long logins.","Sync server clocks with NTP to avoid premature expiry checks."],"tags":["okta","sso","oauth-state","expiration"],"backgroundTag":"invalid-oauth-state","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}