import jwksClient from 'jwks-rsa';
import https from 'https';
import http from 'http';
export class BaseAuthProvider {
    name;
    issuer;
    audience;
    jwksUri;
    config;
    jwksClient;
    constructor(config) {
        this.config = config;
        this.name = config.name;
        this.issuer = config.issuer;
        this.audience = config.audience;
        this.jwksUri = config.jwksUri;
        const agent = this.jwksUri.startsWith('https')
            ? new https.Agent({
                keepAlive: true,
                keepAliveMsecs: 30000,
                maxSockets: 50,
                maxFreeSockets: 10,
                timeout: 60000
            })
            : new http.Agent({
                keepAlive: true,
                keepAliveMsecs: 30000,
                maxSockets: 50,
                maxFreeSockets: 10,
                timeout: 60000
            });
        this.jwksClient = jwksClient({
            jwksUri: this.jwksUri,
            cache: true,
            cacheMaxEntries: 5,
            cacheMaxAge: 600000,
            timeout: 60000,
            requestAgent: agent
        });
    }
    validateConfig() {
        return !!(this.name && this.issuer && this.audience && this.jwksUri);
    }
    getSigningKey(header, callback) {
        this.getSigningKeyWithRetry(header, 3, 1000)
            .then((key) => {
            const signingKey = 'publicKey' in key ? key.publicKey : key.rsaPublicKey;
            callback(null, signingKey);
        })
            .catch((err) => {
            console.error(`Error getting signing key for provider ${this.name} after retries:`, err);
            callback(err);
        });
    }
    async getSigningKeyWithRetry(header, maxRetries, initialDelayMs) {
        let lastError;
        for (let attempt = 0; attempt <= maxRetries; attempt++) {
            try {
                return await this.jwksClient.getSigningKey(header.kid);
            }
            catch (err) {
                lastError = err instanceof Error ? err : new Error(String(err));
                const isRetryableError = lastError.message.includes('socket hang up') ||
                    lastError.message.includes('ECONNRESET') ||
                    lastError.message.includes('ETIMEDOUT') ||
                    lastError.message.includes('ENOTFOUND') ||
                    lastError.message.includes('EAI_AGAIN');
                if (!isRetryableError || attempt === maxRetries) {
                    throw lastError;
                }
                const delayMs = initialDelayMs * Math.pow(2, attempt);
                console.warn(`Attempt ${attempt + 1}/${maxRetries + 1} failed for provider ${this.name}. ` +
                    `Retrying in ${delayMs}ms... Error: ${lastError.message}`);
                await new Promise(resolve => setTimeout(resolve, delayMs));
            }
        }
        throw lastError || new Error('Failed to retrieve signing key');
    }
    matchesIssuer(issuer) {
        const normalizedIssuer = issuer.toLowerCase().replace(/\/$/, '');
        const normalizedProviderIssuer = this.issuer.toLowerCase().replace(/\/$/, '');
        return normalizedIssuer === normalizedProviderIssuer;
    }
}
//# sourceMappingURL=BaseAuthProvider.js.map