var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { Cid } from '../utils/cid.js';
import { GeneralJwsVerifier } from '../jose/jws/general/verifier.js';
import { Jws } from '../utils/jws.js';
import { DwnError, DwnErrorCode } from './dwn-error.js';
export class Authenticate {
    /**
     * Validates the signature(s) of the given JWS.
     * @throws {Error} if fails authentication
     */
    static authenticate(jws, didResolver) {
        return __awaiter(this, void 0, void 0, function* () {
            if (jws === undefined) {
                throw new DwnError(DwnErrorCode.AuthenticateJwsMissing, 'Missing JWS.');
            }
            const verifier = new GeneralJwsVerifier(jws);
            return yield verifier.verify(didResolver);
        });
    }
}
;
/**
 * Authenticates then authorizes the given message using the "canonical" auth flow.
 * Some message auth require special handling such as `RecordsWrite` and `RecordsQuery`,
 * which would be incompatible with this auth flow.
 * @throws {Error} if auth fails
 */
export function canonicalAuth(tenant, incomingMessage, didResolver) {
    return __awaiter(this, void 0, void 0, function* () {
        yield authenticate(incomingMessage.message.authorization, didResolver);
        yield authorize(tenant, incomingMessage);
    });
}
/**
 * Validates the structural integrity of the `authorization` property.
 * NOTE: signature is not verified.
 * @returns the parsed JSON payload object if validation succeeds.
 */
export function validateAuthorizationIntegrity(message, authorizationPayloadConstraints) {
    var _a;
    return __awaiter(this, void 0, void 0, function* () {
        if (message.authorization === undefined) {
            throw new DwnError(DwnErrorCode.AuthorizationMissing, 'Property `authorization` is missing.');
        }
        if (message.authorization.signatures.length !== 1) {
            throw new Error('expected no more than 1 signature for authorization');
        }
        const payloadJson = Jws.decodePlainObjectPayload(message.authorization);
        const { descriptorCid } = payloadJson;
        // `descriptorCid` validation - ensure that the provided descriptorCid matches the CID of the actual message
        const expectedDescriptorCid = yield Cid.computeCid(message.descriptor);
        if (descriptorCid !== expectedDescriptorCid) {
            throw new Error(`provided descriptorCid ${descriptorCid} does not match expected CID ${expectedDescriptorCid}`);
        }
        // check to ensure that no other unexpected properties exist in payload.
        const allowedProperties = (_a = authorizationPayloadConstraints === null || authorizationPayloadConstraints === void 0 ? void 0 : authorizationPayloadConstraints.allowedProperties) !== null && _a !== void 0 ? _a : new Set();
        const customProperties = Object.assign({}, payloadJson);
        delete customProperties.descriptorCid;
        for (const propertyName in customProperties) {
            {
                if (!allowedProperties.has(propertyName)) {
                    throw new Error(`${propertyName} not allowed in auth payload.`);
                }
            }
            try {
                Cid.parseCid(payloadJson[propertyName]);
            }
            catch (e) {
                throw new Error(`${propertyName} must be a valid CID`);
            }
        }
        return payloadJson;
    });
}
/**
 * Validates the signature(s) of the given JWS.
 * @throws {Error} if fails authentication
 */
export function authenticate(jws, didResolver) {
    return __awaiter(this, void 0, void 0, function* () {
        if (jws === undefined) {
            throw new DwnError(DwnErrorCode.AuthenticateJwsMissing, 'Missing JWS.');
        }
        const verifier = new GeneralJwsVerifier(jws);
        return yield verifier.verify(didResolver);
    });
}
/**
 * Authorizes the incoming message.
 * @throws {Error} if fails authentication
 */
export function authorize(tenant, incomingMessage) {
    return __awaiter(this, void 0, void 0, function* () {
        // if author is the same as the target tenant, we can directly grant access
        if (incomingMessage.author === tenant) {
            return;
        }
        else {
            throw new Error('message failed authorization, permission grant check not yet implemented');
        }
    });
}
//# sourceMappingURL=auth.js.map