import { RemoteGraphQLDataSource, GraphQLDataSourceProcessOptions } from '@apollo/gateway';
import { GatewayGraphQLResponse } from '@apollo/server-gateway-interface';
import { Response, Request, CookieOptions } from 'express';
import * as jose from 'jose';
import { BaseContext, ApolloServerPlugin, GraphQLRequestListener, GraphQLRequestContext } from '@apollo/server';

type TokenSignerOptions = {
    encryptKeys: KeyManagerInterface;
    signKeys: KeyManagerInterface;
    audience: string;
    issuer: string;
};
declare class TokenSigner {
    private config;
    private _encryptKeys;
    private _signKeys;
    constructor(config: TokenSignerOptions);
    encryptObject(value: Record<string, any>): Promise<string>;
    decryptObject(value: string): Promise<any>;
    signJWT(payload: any, exp: number): Promise<string>;
    verifyJWT(value: string): Promise<jose.JWTVerifyResult & jose.ResolvedKey<jose.KeyLike>>;
    encryptJWT(payload: any, exp: number): Promise<string>;
    decryptJWT(jwt: string): Promise<jose.JWTDecryptResult & jose.ResolvedKey<jose.KeyLike>>;
}
type Key = {
    id: string;
    key: jose.KeyLike;
};
interface KeyManagerInterface {
    getActiveKey(): Promise<Key>;
    getKeyFunction(header: jose.JWTHeaderParameters | jose.CompactJWEHeaderParameters, input: jose.FlattenedJWSInput | jose.FlattenedJWE): Uint8Array | jose.KeyLike | Promise<Uint8Array | jose.KeyLike>;
}
declare class KeyManager implements KeyManagerInterface {
    private keys;
    constructor(keys: Key[]);
    getActiveKey(): Promise<Key>;
    getKeyFunction(header: jose.JWTHeaderParameters | jose.CompactJWEHeaderParameters, input: jose.FlattenedJWSInput | jose.FlattenedJWE): Uint8Array | jose.KeyLike | Promise<Uint8Array | jose.KeyLike>;
}

type FederatedTokenContext = {
    federatedToken?: FederatedToken;
};
interface AccessToken {
    token: string;
    exp: number;
}
declare class FederatedToken {
    tokens: Record<string, AccessToken>;
    refreshTokens: Record<string, string>;
    values: Record<string, any>;
    private _accessTokenModified;
    private _refreshTokenModified;
    constructor();
    setAccessToken(name: string, token: AccessToken): void;
    setRefreshToken(name: string, token: string): void;
    isAccessTokenModified(): boolean;
    isRefreshTokenModified(): boolean;
    loadAccessToken(at: string, trackModified?: boolean): void;
    dumpAccessToken(): string | undefined;
    loadRefreshToken(value: string, trackModified?: boolean): void;
    dumpRefreshToken(): string | undefined;
}

type PublicFederatedTokenContext = {
    federatedToken?: PublicFederatedToken;
    res: Response;
    req: Request;
} & BaseContext;
declare class PublicFederatedToken extends FederatedToken {
    createAccessJWT(signer: TokenSigner): Promise<{
        accessToken: string;
        fingerprint: string;
    }>;
    loadAccessJWT(signer: TokenSigner, value: string, fingerprint?: string): Promise<void>;
    createRefreshJWT(signer: TokenSigner): Promise<string>;
    loadRefreshJWT(signer: TokenSigner, value: string): Promise<void>;
}

declare class FederatedGraphQLDataSource extends RemoteGraphQLDataSource<PublicFederatedTokenContext> {
    private name;
    constructor({ name, url }: {
        name: string;
        url: string;
    });
    willSendRequest(options: GraphQLDataSourceProcessOptions): void | Promise<void>;
    didReceiveResponse({ response, context, }: {
        response: GatewayGraphQLResponse;
        context: PublicFederatedTokenContext;
    }): Promise<GatewayGraphQLResponse>;
}

interface TokenSource {
    getAccessToken(request: Request): string;
    getRefreshToken(request: Request): string;
    getFingerprint(request: Request): string;
    setAccessToken(response: Response, token: string): void;
    setRefreshToken(response: Response, token: string): void;
    setFingerprint(response: Response, fingerprint: string): void;
}

type GatewayOptions = {
    signer: TokenSigner;
    source: TokenSource;
};
declare class GatewayAuthPlugin<TContext extends PublicFederatedTokenContext> implements ApolloServerPlugin, GraphQLRequestListener<TContext> {
    private signer;
    private tokenSource;
    constructor(options: GatewayOptions);
    requestDidStart(requestContext: GraphQLRequestContext<TContext>): Promise<void | GraphQLRequestListener<TContext>>;
    didResolveOperation(requestContext: GraphQLRequestContext<TContext>): Promise<void>;
    willSendResponse(requestContext: GraphQLRequestContext<TContext>): Promise<void>;
}

declare class FederatedAuthPlugin<TContext extends FederatedTokenContext> implements ApolloServerPlugin, GraphQLRequestListener<TContext> {
    requestDidStart(requestContext: GraphQLRequestContext<TContext>): Promise<void | GraphQLRequestListener<TContext>>;
    willSendResponse(requestContext: GraphQLRequestContext<TContext>): Promise<void>;
}

declare class CompositeTokenSource implements TokenSource {
    private sources;
    constructor(sources: TokenSource[]);
    getAccessToken(request: Request): string;
    getRefreshToken(request: Request): string;
    getFingerprint(request: Request): string;
    setAccessToken(response: Response, token: string): void;
    setRefreshToken(response: Response, token: string): void;
    setFingerprint(response: Response, fingerprint: string): void;
}

type CookieSourceOptions = {
    secure: boolean;
    sameSite: CookieOptions["sameSite"];
    refreshTokenPath: string;
};
declare class CookieTokenSource implements TokenSource {
    private options;
    constructor(options: CookieSourceOptions);
    cookieNames: {
        accessToken: string;
        accessTokenHash: string;
        refreshToken: string;
        refreshTokenExist: string;
    };
    _getCookieName(name: string): string;
    _getCookie(request: Request, name: string): any;
    _setCookie(response: Response, name: string, value: string, options: CookieOptions): void;
    getAccessToken(request: Request): string;
    getRefreshToken(request: Request): string;
    getFingerprint(request: Request): string;
    setAccessToken(response: Response, token: string): void;
    setRefreshToken(response: Response, token: string): void;
    setFingerprint(response: Response, fingerprint: string): void;
}

declare class HeaderTokenSource implements TokenSource {
    headerNames: {
        accessToken: string;
        refreshToken: string;
    };
    getAccessToken(request: Request): string;
    getRefreshToken(request: Request): string;
    getFingerprint(request: Request): string;
    setAccessToken(response: Response, token: string): void;
    setRefreshToken(response: Response, token: string): void;
    setFingerprint(response: Response, fingerprint: string): void;
}

export { CompositeTokenSource, CookieTokenSource, FederatedAuthPlugin, FederatedGraphQLDataSource, FederatedToken, GatewayAuthPlugin, HeaderTokenSource, KeyManager, KeyManagerInterface, PublicFederatedToken, PublicFederatedTokenContext, TokenSigner, TokenSource };
