import { Effect } from "effect";
declare const OAuth2Error_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
    readonly _tag: "OAuth2Error";
} & Readonly<A>;
export declare class OAuth2Error extends OAuth2Error_base<{
    readonly message: string;
    /**
     * RFC 6749 §5.2 error code, when the token endpoint returned one
     * (`invalid_grant`, `invalid_client`, `unauthorized_client`, ...).
     * Callers use this to distinguish terminal failures (a refresh token
     * the AS no longer honours → re-auth required) from transient ones.
     */
    readonly error?: string;
    readonly cause?: unknown;
}> {
}
export type OAuth2TokenResponse = {
    readonly access_token: string;
    readonly token_type?: string;
    readonly refresh_token?: string;
    readonly expires_in?: number;
    readonly scope?: string;
};
/** Refresh tokens this many ms before expiry to avoid mid-request expiration. */
export declare const OAUTH2_REFRESH_SKEW_MS = 60000;
/** Default token-endpoint timeout. */
export declare const OAUTH2_DEFAULT_TIMEOUT_MS = 20000;
export interface OAuthEndpointUrlPolicy {
    readonly allowHttp?: boolean;
}
export declare const isSupportedOAuthEndpointUrl: (value: string, policy?: OAuthEndpointUrlPolicy) => boolean;
export declare const assertSupportedOAuthEndpointUrl: (value: string, label?: string, policy?: OAuthEndpointUrlPolicy) => string;
export declare const createPkceCodeVerifier: () => string;
export declare const createPkceCodeChallenge: (verifier: string) => Promise<string>;
export type BuildAuthorizationUrlInput = {
    readonly authorizationUrl: string;
    readonly clientId: string;
    readonly redirectUrl: string;
    readonly scopes: readonly string[];
    readonly state: string;
    /** Pre-computed base64url S256 challenge (from `createPkceCodeChallenge`). */
    readonly codeChallenge: string;
    /** Separator between scopes. RFC 6749 says space; some providers use comma. */
    readonly scopeSeparator?: string;
    /** RFC 8707 Resource Indicator. MCP Authorization 2025-06-18 §"Resource
     *  Parameter Implementation" requires clients to send this on every
     *  authorization request, regardless of AS support. */
    readonly resource?: string;
    /** Provider-specific extras (e.g. Google's `access_type=offline`). */
    readonly extraParams?: Readonly<Record<string, string>>;
    readonly endpointUrlPolicy?: OAuthEndpointUrlPolicy;
};
/** Build an RFC 6749 §4.1.1 authorization URL. Sync; pre-computed
 *  challenge lets this stay out of the Promise world. */
export declare const buildAuthorizationUrl: (input: BuildAuthorizationUrlInput) => string;
export type ClientAuthMethod = "body" | "basic";
export type ExchangeAuthorizationCodeInput = {
    readonly tokenUrl: string;
    readonly issuerUrl?: string | null;
    readonly clientId: string;
    readonly clientSecret?: string | null;
    readonly redirectUrl: string;
    readonly codeVerifier: string;
    readonly code: string;
    readonly clientAuth?: ClientAuthMethod;
    readonly idTokenSigningAlgValuesSupported?: readonly string[];
    /** RFC 8707 Resource Indicator. MCP Auth spec MUST-requires this on
     *  the token request when the client knows the resource it intends
     *  to call. */
    readonly resource?: string;
    readonly timeoutMs?: number;
    readonly endpointUrlPolicy?: OAuthEndpointUrlPolicy;
};
export declare const exchangeAuthorizationCode: (input: ExchangeAuthorizationCodeInput) => Effect.Effect<OAuth2TokenResponse, OAuth2Error>;
export type ExchangeClientCredentialsInput = {
    readonly tokenUrl: string;
    readonly clientId: string;
    readonly clientSecret: string;
    readonly scopes?: readonly string[];
    readonly scopeSeparator?: string;
    readonly clientAuth?: ClientAuthMethod;
    readonly timeoutMs?: number;
    readonly endpointUrlPolicy?: OAuthEndpointUrlPolicy;
};
export declare const exchangeClientCredentials: (input: ExchangeClientCredentialsInput) => Effect.Effect<OAuth2TokenResponse, OAuth2Error>;
export type RefreshAccessTokenInput = {
    readonly tokenUrl: string;
    readonly issuerUrl?: string | null;
    readonly clientId: string;
    readonly clientSecret?: string | null;
    readonly refreshToken: string;
    readonly scopes?: readonly string[];
    readonly scopeSeparator?: string;
    readonly clientAuth?: ClientAuthMethod;
    readonly idTokenSigningAlgValuesSupported?: readonly string[];
    /** RFC 8707 Resource Indicator — MCP spec MUST-requires this on
     *  refresh requests so the new access token's audience is bound to
     *  the same resource. */
    readonly resource?: string;
    readonly timeoutMs?: number;
    readonly endpointUrlPolicy?: OAuthEndpointUrlPolicy;
};
export declare const refreshAccessToken: (input: RefreshAccessTokenInput) => Effect.Effect<OAuth2TokenResponse, OAuth2Error>;
export declare const shouldRefreshToken: (input: {
    readonly expiresAt: number | null;
    readonly now?: number;
    readonly skewMs?: number;
}) => boolean;
export {};
//# sourceMappingURL=oauth-helpers.d.ts.map