mastra-ai/mastra · error

Redirect URI is required for SSO login

Error message

Redirect URI is required for SSO login

What it means

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.

Source

Thrown at auth/clerk/src/index.ts:526

  // Dynamic ISSOProvider attachment (only when OAuth is configured)
  // ============================================================================

  /**
   * Dynamically attach ISSOProvider methods to this instance.
   * This ensures duck-typing detection only finds these methods when SSO is configured.
   */
  private _attachSSOProvider() {
    const self = this;

    (this as unknown as ISSOProvider<EEUser>).getLoginUrl = async function (
      redirectUri: string,
      state: string,
    ): Promise<string> {
      // Create signed state token containing redirectUri and expiry
      // This is stateless — works in serverless and load-balanced environments
      const actualRedirectUri = redirectUri ?? self._redirectUri;
      if (!actualRedirectUri) {
        throw new Error('Redirect URI is required for SSO login');
      }

      const signedState = await createStateToken(state, actualRedirectUri, self.cookiePassword);

      const params = new URLSearchParams({
        client_id: self.oauthClientId!,
        response_type: 'code',
        scope: self.scopes.join(' '),
        redirect_uri: actualRedirectUri,
        state: signedState,
      });

      return `${self.fapiUrl}/oauth/authorize?${params.toString()}`;
    };

    (this as unknown as ISSOProvider<EEUser>).handleCallback = async function (
      code: string,
      stateToken: string,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass redirectUri in the call: provider.getAuthorizationUri({ state, redirectUri: 'https://app.example.com/auth/callback' }).
  2. Or configure it once: new ClerkAuthProvider({ ..., redirectUri: 'https://app.example.com/auth/callback' }).
  3. Ensure the redirect URI is also registered as an allowed redirect URL in the Clerk dashboard.
  4. Add a startup assertion that ssoEnabled implies a redirect URI is configured.

Example fix

// before
const url = await provider.getAuthorizationUri(state);
// after
const url = await provider.getAuthorizationUri(state, {
  redirectUri: process.env.SSO_REDIRECT_URI ?? 'https://app.example.com/auth/callback',
});
Defensive patterns

Strategy: validation

Validate before calling

const redirectUri = options.redirectUri ?? providerRedirectUri;
if (!redirectUri) {
  throw new Error('redirectUri must be provided to SSO login or provider options');
}
const url = await getAuthorizationUri(state, redirectUri);

Prevention

When it happens

Trigger: 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`).

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/6938302b68d6dc6e. Report an issue: GitHub.