@sphereon/ssi-sdk.presentation-exchange
Version:
148 lines • 9.9 kB
JavaScript
;
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPEXPresentationSignCallback = createPEXPresentationSignCallback;
const ssi_sdk_ext_identifier_resolution_1 = require("@sphereon/ssi-sdk-ext.identifier-resolution");
const ssi_types_1 = require("@sphereon/ssi-types");
function createPEXPresentationSignCallback(args, context) {
return __awaiter(this, void 0, void 0, function* () {
function determineProofFormat(determineArgs) {
var _a;
const { format, presentationDefinition, presentation } = determineArgs;
var formatOptions = (_a = format !== null && format !== void 0 ? format : presentationDefinition.format) !== null && _a !== void 0 ? _a : args.format;
// TODO Refactor so it takes into account the Input Descriptors and we can lookup from there. Now we only do that if there is 1 descriptor
if (!formatOptions && presentationDefinition.input_descriptors.length == 1 && 'format' in presentationDefinition.input_descriptors[0]) {
formatOptions = presentationDefinition.input_descriptors[0].format;
}
// All format arguments are optional. So if no format has been given we go for the most supported 'jwt'
if (!formatOptions) {
if (ssi_types_1.CredentialMapper.isSdJwtDecodedCredentialPayload(presentation.decodedPayload)) {
return 'vc+sd-jwt';
}
else if (ssi_types_1.CredentialMapper.isMsoMdocDecodedPresentation(presentation.decodedPayload)) {
return 'mso_mdoc';
}
else if (ssi_types_1.CredentialMapper.isW3cPresentation(presentation.decodedPayload)) {
if (typeof presentation.signedPayload === 'string') {
return 'jwt';
}
return 'lds';
}
return 'jwt';
}
else if (typeof formatOptions === 'string') {
// if formatOptions is a singular string we can return that as the format
return formatOptions;
}
// here we transform all format options to either lds or jwt. but we also want to support sd-jwt, so we need to specifically check for this one. which is ['vc+sd-jwt']
const formats = new Set(Object.keys(formatOptions).map((form) => (form.includes('ldp') ? 'lds' : form.includes('vc+sd-jwt') ? 'vc+sd-jwt' : 'jwt')));
// if we only have 1 format type we can return that
if (formats.size === 1) {
return formats.values().next().value;
}
formats.keys().next();
// if we can go for sd-jwt, we go for sd-jwt
if (formats.has('vc+sd-jwt')) {
return 'vc+sd-jwt';
}
// if it is not sd-jwt we would like to go for jwt
else if (formats.has('jwt')) {
return 'jwt';
}
// else we go for lds
return 'lds';
}
return (_a) => __awaiter(this, [_a], void 0, function* ({ presentation, domain, presentationDefinition, format, challenge, }) {
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
const proofFormat = determineProofFormat({ format, presentationDefinition, presentation });
const { idOpts } = args;
const CLOCK_SKEW = 120;
if (args.skipDidResolution && (0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierDidOpts)(idOpts)) {
idOpts.offlineWhenNoDIDRegistered = true;
}
if ('compactSdJwtVc' in presentation) {
if (proofFormat !== 'vc+sd-jwt') {
return Promise.reject(Error(`presentation payload does not match proof format ${proofFormat}`));
}
const presentationResult = yield context.agent.createSdJwtPresentation(Object.assign(Object.assign({}, ((idOpts === null || idOpts === void 0 ? void 0 : idOpts.method) === 'oid4vci-issuer' && { holder: idOpts === null || idOpts === void 0 ? void 0 : idOpts.issuer })), { presentation: presentation.compactSdJwtVc, kb: {
payload: Object.assign(Object.assign({}, (_b = presentation.kbJwt) === null || _b === void 0 ? void 0 : _b.payload), { iat: (_e = (_d = (_c = presentation.kbJwt) === null || _c === void 0 ? void 0 : _c.payload) === null || _d === void 0 ? void 0 : _d.iat) !== null && _e !== void 0 ? _e : Math.floor(Date.now() / 1000 - CLOCK_SKEW), nonce: challenge !== null && challenge !== void 0 ? challenge : (_g = (_f = presentation.kbJwt) === null || _f === void 0 ? void 0 : _f.payload) === null || _g === void 0 ? void 0 : _g.nonce, aud: (_l = (_k = (_j = (_h = presentation.kbJwt) === null || _h === void 0 ? void 0 : _h.payload) === null || _j === void 0 ? void 0 : _j.aud) !== null && _k !== void 0 ? _k : domain) !== null && _l !== void 0 ? _l : args.domain }),
} }));
return ssi_types_1.CredentialMapper.storedPresentationToOriginalFormat(presentationResult.presentation);
}
else {
const resolution = yield context.agent.identifierManagedGet(idOpts);
if (proofFormat === 'vc+sd-jwt') {
return Promise.reject(Error(`presentation payload does not match proof format ${proofFormat}`));
}
let header;
if (!presentation.holder) {
presentation.holder = resolution.issuer;
}
if (proofFormat === 'jwt') {
header = Object.assign(Object.assign({}, (((0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierDidResult)(resolution) || (0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierX5cResult)(resolution)) && resolution.kid && { kid: resolution.kid })), ((0, ssi_sdk_ext_identifier_resolution_1.isManagedIdentifierX5cResult)(resolution) && { jwk: resolution.jwk }));
if (presentation.verifier || !presentation.aud) {
presentation.aud = Array.isArray(presentation.verifier) ? presentation.verifier : ((_o = (_m = presentation.verifier) !== null && _m !== void 0 ? _m : domain) !== null && _o !== void 0 ? _o : args.domain);
delete presentation.verifier;
}
if (!presentation.nbf) {
if (presentation.issuanceDate) {
const converted = Date.parse(presentation.issuanceDate);
if (!isNaN(converted)) {
presentation.nbf = Math.floor(converted / 1000); // no skew here, as an explicit value was given
}
}
else {
presentation.nbf = Math.floor(Date.now() / 1000 - CLOCK_SKEW);
}
}
if (!presentation.iat) {
presentation.iat = presentation.nbf;
}
if (!presentation.exp) {
if (presentation.expirationDate) {
const converted = Date.parse(presentation.expirationDate);
if (!isNaN(converted)) {
presentation.exp = Math.floor(converted / 1000); // no skew here as an explicit value w as given
}
}
else {
presentation.exp = presentation.nbf + 600 + CLOCK_SKEW;
}
}
if (!presentation.vp) {
presentation.vp = {};
}
/*if (!presentation.sub) {
presentation.sub = id.did
}*/
if (!presentation.vp.holder) {
presentation.vp.holder = presentation.holder;
}
}
// we ignore the alg / proof_format for now, as we already have the kid anyway at this point
// todo: look for jwt_vc_json and remove types and @context
const vp = yield context.agent.createVerifiablePresentation({
presentation: presentation,
removeOriginalFields: false,
keyRef: resolution.kmsKeyRef,
// domain: domain ?? args.domain, // handled above, and did-jwt-vc creates an array even for 1 entry
challenge: challenge !== null && challenge !== void 0 ? challenge : args.challenge,
fetchRemoteContexts: args.fetchRemoteContexts !== false,
proofFormat: proofFormat,
header,
});
// makes sure we extract an actual JWT from the internal representation in case it is a JWT
return ssi_types_1.CredentialMapper.storedPresentationToOriginalFormat(vp);
}
});
});
}
//# sourceMappingURL=functions.js.map