/** * OAuth Provider Callback Endpoint — GET /oauth/provider/:providerId/callback * * Who calls: Browser after user completes OAuth with an upstream provider * * When: During multi-provider (federated) authentication flow * * Purpose: Exchange upstream provider's authorization code for tokens, * store tokens securely, then redirect to next provider or complete auth * * Flow: * 1. User selects providers on federated login page * 2. System redirects to first provider's /authorize * 3. User completes auth with provider * 4. Provider redirects here with authorization code * 5. We exchange code for tokens, store them * 6. If more providers in queue, redirect to next * 7. If all providers done, issue FrontMCP JWT */ import { z } from '@frontmcp/lazy-zod'; import { FlowBase, type FlowRunOptions } from '../../common'; declare const inputSchema: import("@frontmcp/lazy-zod").ZodObject<{ request: import("@frontmcp/lazy-zod").ZodObject<{}, import("zod/v4/core").$loose>; response: import("@frontmcp/lazy-zod").ZodObject<{}, import("zod/v4/core").$loose>; next: import("@frontmcp/lazy-zod").ZodOptional>; }, import("zod/v4/core").$strip>; declare const stateSchema: import("@frontmcp/lazy-zod").ZodObject<{ providerId: import("@frontmcp/lazy-zod").ZodOptional; code: import("@frontmcp/lazy-zod").ZodOptional; error: import("@frontmcp/lazy-zod").ZodOptional; errorDescription: import("@frontmcp/lazy-zod").ZodOptional; providerState: import("@frontmcp/lazy-zod").ZodOptional; federatedSessionId: import("@frontmcp/lazy-zod").ZodOptional; federatedSession: import("@frontmcp/lazy-zod").ZodOptional; providerTokens: import("@frontmcp/lazy-zod").ZodOptional; providerUserInfo: import("@frontmcp/lazy-zod").ZodOptional; consentSessionId: import("@frontmcp/lazy-zod").ZodOptional; consentSubmitted: import("@frontmcp/lazy-zod").ZodDefault; selectedTools: import("@frontmcp/lazy-zod").ZodOptional>; }, import("zod/v4/core").$strip>; declare const outputSchema: import("@frontmcp/lazy-zod").ZodUnion; status: import("@frontmcp/lazy-zod").ZodDefault>; location: import("@frontmcp/lazy-zod").ZodString; headers: import("@frontmcp/lazy-zod").ZodOptional]>]>>>>; cookies: import("@frontmcp/lazy-zod").ZodOptional; domain: import("@frontmcp/lazy-zod").ZodOptional; httpOnly: import("@frontmcp/lazy-zod").ZodDefault; secure: import("@frontmcp/lazy-zod").ZodOptional; sameSite: import("@frontmcp/lazy-zod").ZodOptional>; maxAge: import("@frontmcp/lazy-zod").ZodOptional; expires: import("@frontmcp/lazy-zod").ZodOptional; }, import("zod/v4/core").$strip>>>>; }, import("zod/v4/core").$strip>, import("@frontmcp/lazy-zod").ZodObject<{ status: import("@frontmcp/lazy-zod").ZodNumber; body: import("@frontmcp/lazy-zod").ZodString; headers: import("@frontmcp/lazy-zod").ZodOptional]>]>>>>; cookies: import("@frontmcp/lazy-zod").ZodOptional; domain: import("@frontmcp/lazy-zod").ZodOptional; httpOnly: import("@frontmcp/lazy-zod").ZodDefault; secure: import("@frontmcp/lazy-zod").ZodOptional; sameSite: import("@frontmcp/lazy-zod").ZodOptional>; maxAge: import("@frontmcp/lazy-zod").ZodOptional; expires: import("@frontmcp/lazy-zod").ZodOptional; }, import("zod/v4/core").$strip>>>>; kind: import("@frontmcp/lazy-zod").ZodLiteral<"html">; contentType: import("@frontmcp/lazy-zod").ZodDefault>; }, import("zod/v4/core").$strip>]>; declare const plan: { readonly pre: ["parseInput", "handleConsentSubmission", "loadFederatedSession", "validateProviderCallback"]; readonly execute: ["exchangeProviderCode", "storeProviderTokens", "handleNextProviderOrComplete"]; }; declare global { interface ExtendFlows { 'oauth:provider-callback': FlowRunOptions; } } declare const name: "oauth:provider-callback"; export default class OauthProviderCallbackFlow extends FlowBase { private logger; /** * Get LocalPrimaryAuth instance with type safety * @throws Error if auth is not LocalPrimaryAuth */ private getLocalAuth; parseInput(): Promise; /** * Handle a consent-screen submission for a federated login. * * Federated logins complete (mint the code) here, AFTER all providers are * linked. When consent mode is enabled, {@link completeFederatedAuth} first * renders the consent screen, which GETs back to this endpoint with * `consent_session=` + `tools=`. This stage loads that still alive * session, applies the selection (validating + `requireSelection`), and * completes the mint — short-circuiting the provider-code path entirely. */ handleConsentSubmission(): Promise; loadFederatedSession(): Promise; validateProviderCallback(): Promise; exchangeProviderCode(): Promise; storeProviderTokens(): Promise; handleNextProviderOrComplete(): Promise; /** * Complete the federated auth flow and issue FrontMCP JWT. * * When consent mode is enabled this runs in two passes: * 1. First reach (no `consent.consentSubmitted`): render the consent screen, * which GETs back to this endpoint with `consent_session` + `tools=`. The * federated session is kept ALIVE for the round-trip. * 2. Resubmit (`consent.consentSubmitted` true): validate the selection * (honoring `requireSelection`) and mint the code with the consented set. * * With consent disabled, it mints immediately (historical behavior). */ private completeFederatedAuth; /** * Render the federated consent screen. The form GETs back to this provider * callback endpoint with `consent_session=` + the chosen `tools=` * (and `consent_submitted=1`), so {@link handleConsentSubmission} completes * the mint. Honors the same `auth.consent` flags as the non-federated path. */ private renderConsentScreen; /** * Generate a deterministic user sub from email */ private generateUserSub; /** * Render an error page */ private renderErrorPage; private getStateValidation; } export {}; //# sourceMappingURL=oauth.provider-callback.flow.d.ts.map