"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateAndSignRequest = void 0;
const client_kms_1 = require("@aws-sdk/client-kms");
const envs_1 = require("../envs");
const errors_1 = require("../errors");
const utils_1 = require("../utils");
const base64url_1 = require("../utils/base64url");
const hash_1 = require("../utils/hash");
const uuid_1 = require("../utils/uuid");
const getAuthServiceCredentials = async () => {
    const envVars = await (0, utils_1.loadEnvVars)({
        AUTH_SERVICE_CREDENTIALS: 'AUTH_SERVICE_CREDENTIALS'
    });
    return JSON.parse(envVars.AUTH_SERVICE_CREDENTIALS);
};
const generateNonce = () => {
    return (0, base64url_1.base64url)(JSON.stringify({
        date: new Date().toISOString(),
        uuid: (0, uuid_1.uuid)(),
    }));
};
const generateAndSignRequest = async (originalRequest, originatingIP) => {
    const creds = await getAuthServiceCredentials();
    const target = creds.domain;
    const req = {
        headers: {
            Accept: 'application/json',
            'Content-Length': Buffer.byteLength(originalRequest),
            'Content-Type': 'application/json',
            Host: target,
            'User-Agent': 'DFNS Authorizer Lambda',
            'X-DFNS-APPID': creds.appId,
            'X-DFNS-APPSECRET': creds.appSecret,
            'X-DFNS-NONCE': generateNonce(),
            'X-DFNS-APISIGNATURE': '',
            'X-DFNS-ORIGINATINGIP': originatingIP,
        },
        body: originalRequest,
        http: {
            method: 'POST',
            scheme: 'HTTPS',
            path: creds.url,
            authority: target,
        },
    };
    const requestSigningPayload = {
        'h-accept': req.headers['Accept'],
        'h-accept-encoding': '',
        'h-authorization': '',
        'h-connection': '',
        'h-content-length': req.headers['Content-Length'].toString(),
        'h-content-type': req.headers['Content-Type'],
        'h-host': req.headers['Host'],
        'h-user-agent': req.headers['User-Agent'],
        'h-x-dfns-appid': req.headers['X-DFNS-APPID'],
        'h-x-dfns-appsecret': req.headers['X-DFNS-APPSECRET'],
        'h-x-dfns-nonce': req.headers['X-DFNS-NONCE'],
        'h-x-dfns-useraction': '',
        'r-authority': req.http.authority,
        'r-body': (0, base64url_1.base64url)(originalRequest),
        'r-method': req.http.method.toLowerCase(),
        'r-path': req.http.path,
        'r-scheme': req.http.scheme.toLowerCase(),
    };
    const requestSigningHeader = {
        alg: 'RS256',
        typ: 'JWT',
    };
    const requestToSign = (0, base64url_1.base64url)(JSON.stringify(requestSigningHeader)) + '.' +
        (0, base64url_1.base64url)(JSON.stringify(requestSigningPayload));
    const kmsClient = new client_kms_1.KMSClient({
        region: (0, envs_1.maybeGetEnvParam)('AWS_REGION')
    });
    const getKeyCommand = new client_kms_1.GetPublicKeyCommand({
        KeyId: `alias/${(0, envs_1.maybeGetEnvParam)('ENVIRONMENT')}-security-auth-management-request-signature-key`
    });
    const key = await kmsClient.send(getKeyCommand);
    if (!key.KeyId || !key.PublicKey) {
        const message = 'Signing key is not accessible: ' + getKeyCommand.input.KeyId;
        throw errors_1.TechnicalError.authorizerRequestSigningKeyNotAccessible(message);
    }
    const signCommand = new client_kms_1.SignCommand({
        Message: Buffer.from((0, hash_1.sha256)(requestToSign), 'hex'),
        KeyId: key.KeyId,
        SigningAlgorithm: 'RSASSA_PKCS1_V1_5_SHA_256',
        MessageType: 'DIGEST',
    });
    const signingResult = await kmsClient.send(signCommand);
    if (!signingResult.Signature) {
        const message = 'Unable to sign content with key: ' + getKeyCommand.input.KeyId;
        throw errors_1.TechnicalError.authorizerRequestSigningKeyNotAccessible(message);
    }
    req.headers['X-DFNS-APISIGNATURE'] = base64url_1.base64url.fromArrayBuffer(signingResult.Signature);
    return req;
};
exports.generateAndSignRequest = generateAndSignRequest;
//# sourceMappingURL=generateAndSignRequest.js.map