import { Request, RequestHandler } from 'express';
import { IncomingMessage } from 'node:http';
import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
import { JWTPayload, createRemoteJWKSet, createLocalJWKSet } from 'jose';
export { CLIAuthProvider, CLIAuthProviderOptions, CLIClient, CivicAuthProvider, CivicAuthProviderOptions, DEFAULT_CALLBACK_PORT, DEFAULT_MCP_ROUTE, DEFAULT_SCOPES, DEFAULT_WELLKNOWN_URL, InMemoryTokenPersistence, PUBLIC_CIVIC_CLIENT_ID, RestartableStreamableHTTPClientTransport, TokenAuthProvider, TokenAuthProviderOptions, TokenPersistence } from './client/index.cjs';
import '@modelcontextprotocol/sdk/client/index.js';
import '@modelcontextprotocol/sdk/client/streamableHttp.js';
import '@modelcontextprotocol/sdk/client/sse.js';
import '@modelcontextprotocol/sdk/shared/auth.js';
import '@modelcontextprotocol/sdk/client/auth.js';

/**
 * OAuth state information stored between authorization and callback
 */
interface OAuthState {
    /**
     * Original redirect URI from the client
     */
    redirectUri: string;
    /**
     * Original state parameter from the client
     */
    clientState?: string;
    /**
     * PKCE code challenge from the client
     */
    codeChallenge?: string;
    /**
     * PKCE code challenge method
     */
    codeChallengeMethod?: string;
    /**
     * Timestamp when state was created
     */
    createdAt: number;
    /**
     * OAuth scopes requested
     */
    scope?: string;
    /**
     * Client ID making the request
     */
    clientId?: string;
}
/**
 * Interface for storing OAuth state between redirects
 */
interface StateStore {
    /**
     * Store state data
     */
    set(key: string, state: OAuthState): Promise<void>;
    /**
     * Retrieve state data
     */
    get(key: string): Promise<OAuthState | null>;
    /**
     * Delete state data
     */
    delete(key: string): Promise<void>;
    /**
     * Clean up expired states
     */
    cleanup?(): Promise<void>;
}

/**
 * In-memory implementation of OAuth state store
 */
declare class InMemoryStateStore implements StateStore {
    private states;
    set(key: string, state: OAuthState): Promise<void>;
    get(key: string): Promise<OAuthState | null>;
    delete(key: string): Promise<void>;
    cleanup(): Promise<void>;
}

interface CivicAuthOptions<TAuthInfo extends ExtendedAuthInfo, TRequest extends IncomingMessage = IncomingMessage> {
    /**
     * The URL to the auth server's well-known OIDC configuration
     * Defaults to https://auth.civic.com/oauth/.well-known/openid-configuration
     */
    wellKnownUrl?: string;
    /**
     * OAuth scopes to support
     * Defaults to ['openid', 'profile', 'email']
     */
    scopesSupported?: string[];
    /**
     * Header name to read the protocol from (e.g. "X-Forwarded-Proto").
     * Resolution order: forceHttps > protocolHeader > req.protocol.
     */
    protocolHeader?: string;
    /**
     * Header name to read the host from (e.g. "X-Forwarded-Host").
     * Defaults to the standard "host" header.
     */
    hostHeader?: string;
    /**
     * Base path for auth endpoints
     * Defaults to '/'
     */
    basePath?: string;
    /**
     * The MCP route to protect with authentication
     * Defaults to '/mcp'
     */
    mcpRoute?: string;
    /**
     * Optional callback to enrich the auth info with custom data
     * Called after successful token verification
     * @param authInfo The verified auth info from the token. Null if no token was provided.
     * @param request Optional request object that may contain headers or other data
     * @returns Enriched auth info with custom data
     */
    onLogin?: (authInfo: ExtendedAuthInfo | null, request?: TRequest) => Promise<TAuthInfo | null>;
    /**
     * Optional OAuth client ID / Tenant ID.
     * When set, the access token must include *either* a "client_id" field or "tid" field that matches it.
     */
    clientId?: string;
    /**
     * Whether to allow dynamic client registration by adding client ID as subdomain.
     * When true, the client ID will be added as a subdomain to the auth server URL.
     * When false (default), the auth server URL will be used as-is without subdomain prefixing.
     * Defaults to false.
     */
    allowDynamicClientRegistration?: boolean;
    /**
     * Enable legacy OAuth mode where MCP server acts as an OAuth server.
     * When true, the server will expose OAuth endpoints that proxy to the underlying auth server.
     * Defaults to true for backward compatibility.
     * @deprecated This mode is deprecated. Clients should authenticate directly with the auth server.
     */
    enableLegacyOAuth?: boolean;
    /**
     * Custom state store for managing OAuth flow state between redirects in legacy mode.
     * Only used when enableLegacyOAuth is true.
     * Defaults to in-memory store.
     */
    stateStore?: StateStore;
    /**
     * Optional JSON Web Key Set for local JWT verification.
     * When provided, these keys will be used instead of fetching from the OIDC jwks_uri.
     * Useful for testing or air-gapped environments.
     */
    jwks?: {
        keys: Array<{
            kty: string;
            kid?: string;
            use?: string;
            alg?: string;
            [key: string]: unknown;
        }>;
    };
    /**
     * Whether to disable client ID verification.
     * When true, the client_id or tid verification will be skipped.
     * Defaults to false (verification enabled).
     */
    disableClientIdVerification?: boolean;
    /**
     *  If true, forces all metadata URLs to use https even if the incoming request is http.
     *  This is useful when sitting behind a proxy that terminates SSL.
     *  Defaults to false.
     */
    forceHttps?: boolean;
}
interface OIDCWellKnownConfiguration {
    issuer: string;
    authorization_endpoint: string;
    token_endpoint: string;
    jwks_uri: string;
    scopes_supported?: string[];
    response_types_supported?: string[];
    grant_types_supported?: string[];
    token_endpoint_auth_methods_supported?: string[];
    introspection_endpoint?: string;
    revocation_endpoint?: string;
    registration_endpoint?: string;
}
interface ExtendedAuthInfo extends AuthInfo {
    /**
     * The tenant ID from the tid claim, if present
     */
    tenantId?: string;
    extra?: {
        sub?: string;
        email?: string;
        name?: string;
        picture?: string;
        [key: string]: unknown;
    };
}
/**
 * Custom error class for all authentication errors
 */
declare class AuthenticationError extends Error {
}
/**
 * Custom error class for JWT verification failures
 */
declare class JWTVerificationError extends AuthenticationError {
    originalError?: Error | undefined;
    constructor(message: string, originalError?: Error | undefined);
}
type AccessTokenPayload = JWTPayload & {
    client_id: string | undefined;
    tid: string | undefined;
};

/**
 * Core authentication functionality that can be used with any framework
 */
declare class McpServerAuth<TAuthInfo extends ExtendedAuthInfo, TRequest extends IncomingMessage = IncomingMessage> {
    protected oidcConfig: OIDCWellKnownConfiguration;
    protected jwks: ReturnType<typeof createRemoteJWKSet> | ReturnType<typeof createLocalJWKSet>;
    protected options: CivicAuthOptions<TAuthInfo, TRequest>;
    protected constructor(oidcConfig: OIDCWellKnownConfiguration, options: CivicAuthOptions<TAuthInfo, TRequest>);
    /**
     * Initialize the auth core by fetching OIDC configuration
     */
    static init<TAuthInfo extends ExtendedAuthInfo, TRequest extends IncomingMessage = IncomingMessage>(options?: CivicAuthOptions<TAuthInfo, TRequest>): Promise<McpServerAuth<TAuthInfo, TRequest>>;
    /**
     * Get the OAuth Protected Resource metadata
     * @param resourceUrl The resource URL of the protected resource (e.g., https://my-server.com/mcp)
     */
    getProtectedResourceMetadata(resourceUrl: string): {
        resource: string;
        authorization_servers: string[];
        scopes_supported: string[];
        bearer_methods_supported: string[];
    };
    /**
     * Create auth info from a token (or null) and request
     * @param token The JWT token (can be null)
     * @param payload The JWT payload if token was already verified
     * @param request Optional request object to pass to onLogin callback
     * @returns ExtendedAuthInfo if successful, null otherwise
     */
    private createAuthInfo;
    /**
     * Extract and verify bearer token from authorization header
     * @param authHeader The Authorization header value
     * @returns Object with token and payload if valid, throws if invalid token, returns null values if no token
     */
    private extractBearerToken;
    /**
     * Handle a request by extracting and verifying the bearer token
     * @param request The request object
     * @returns ExtendedAuthInfo if valid
     * @throws Error if authentication fails
     */
    handleRequest(request: TRequest): Promise<TAuthInfo>;
}

interface UrlResolutionOptions {
    /** Header to read the protocol from. Default: none (uses forceHttps or req.protocol) */
    protocolHeader?: string;
    /** Header to read the host from. Default: "host" (standard Host header) */
    hostHeader?: string;
    /** Force HTTPS regardless of headers. Default: false */
    forceHttps?: boolean;
}
/** Resolves protocol and host from request, respecting configured headers */
declare function resolveBaseUrl(req: IncomingMessage, options?: UrlResolutionOptions): string;

/**
 * Express middleware that configures an MCP server to use Civic Auth
 * as its authorization server.
 *
 * This middleware:
 * 1. Exposes /.well-known/oauth-protected-resource metadata
 * 2. Validates bearer tokens using Civic's JWKS
 * 3. Attaches user info to the request
 * 4. (Legacy) Optionally exposes OAuth server endpoints for backward compatibility
 *
 * @param options Configuration options
 * @returns Express middleware
 */
declare function auth<TAuthInfo extends ExtendedAuthInfo>(options?: CivicAuthOptions<TAuthInfo, Request>): Promise<RequestHandler>;

export { type AccessTokenPayload, AuthenticationError, type CivicAuthOptions, type ExtendedAuthInfo, InMemoryStateStore, JWTVerificationError, McpServerAuth, type OAuthState, type OIDCWellKnownConfiguration, type StateStore, type UrlResolutionOptions, auth, resolveBaseUrl };
