{"record":{"id":"6938302b68d6dc6e","repo":"mastra-ai/mastra","slug":"redirect-uri-is-required-for-sso-login","errorCode":null,"errorMessage":"Redirect URI is required for SSO login","messagePattern":"Redirect URI is required for SSO login","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/clerk/src/index.ts","lineNumber":526,"sourceCode":"  // Dynamic ISSOProvider attachment (only when OAuth is configured)\n  // ============================================================================\n\n  /**\n   * Dynamically attach ISSOProvider methods to this instance.\n   * This ensures duck-typing detection only finds these methods when SSO is configured.\n   */\n  private _attachSSOProvider() {\n    const self = this;\n\n    (this as unknown as ISSOProvider<EEUser>).getLoginUrl = async function (\n      redirectUri: string,\n      state: string,\n    ): Promise<string> {\n      // Create signed state token containing redirectUri and expiry\n      // This is stateless — works in serverless and load-balanced environments\n      const actualRedirectUri = redirectUri ?? self._redirectUri;\n      if (!actualRedirectUri) {\n        throw new Error('Redirect URI is required for SSO login');\n      }\n\n      const signedState = await createStateToken(state, actualRedirectUri, self.cookiePassword);\n\n      const params = new URLSearchParams({\n        client_id: self.oauthClientId!,\n        response_type: 'code',\n        scope: self.scopes.join(' '),\n        redirect_uri: actualRedirectUri,\n        state: signedState,\n      });\n\n      return `${self.fapiUrl}/oauth/authorize?${params.toString()}`;\n    };\n\n    (this as unknown as ISSOProvider<EEUser>).handleCallback = async function (\n      code: string,\n      stateToken: string,","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/auth/clerk/src/index.ts#L508-L544","documentation":"The SSO authorization-URL builder creates a signed state token that must embed the post-login redirect URI. It resolves the URI from the per-call `redirectUri` argument, falling back to the provider-level `self._redirectUri`; if both are absent there is nowhere to redirect the user after OAuth completes, so it throws. This is a required-argument check inside the getAuthorizationUri closure attached by _attachSSOProvider.","triggerScenarios":"Calling the SSO getAuthorizationUri/`state` handler without passing redirectUri while the provider was constructed without a redirectUri option (e.g. `new ClerkAuthProvider({ ..., oauthClientId, oauthClientSecret })` with no `redirectUri`).","commonSituations":"Forgetting the redirectUri option when enabling OAuth; calling the URL builder directly in a custom route without the redirect parameter; provider instance created in one module without options and used in another expecting defaults; renamed/renamed-away config key after a library upgrade.","solutions":["Pass redirectUri in the call: provider.getAuthorizationUri({ state, redirectUri: 'https://app.example.com/auth/callback' }).","Or configure it once: new ClerkAuthProvider({ ..., redirectUri: 'https://app.example.com/auth/callback' }).","Ensure the redirect URI is also registered as an allowed redirect URL in the Clerk dashboard.","Add a startup assertion that ssoEnabled implies a redirect URI is configured."],"exampleFix":"// before\nconst url = await provider.getAuthorizationUri(state);\n// after\nconst url = await provider.getAuthorizationUri(state, {\n  redirectUri: process.env.SSO_REDIRECT_URI ?? 'https://app.example.com/auth/callback',\n});","handlingStrategy":"validation","validationCode":"const redirectUri = options.redirectUri ?? providerRedirectUri;\nif (!redirectUri) {\n  throw new Error('redirectUri must be provided to SSO login or provider options');\n}\nconst url = await getAuthorizationUri(state, redirectUri);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always configure redirectUri in provider options when enabling OAuth credentials.","Register the same redirect URI in the Clerk dashboard allowlist.","Centralize the redirect URI in one env/config value consumed everywhere."],"tags":["auth","clerk","sso","oauth","configuration"],"backgroundTag":"missing-required-option","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}