UNPKG

@sphereon/ssi-types

Version:

SSI Common Types

774 lines • 39.4 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CredentialMapper = exports.sha256 = void 0; const types_1 = require("../types"); const utils_1 = require("../utils"); const jwt_decode_1 = require("jwt-decode"); const sha256 = (data) => { return (0, utils_1.defaultHasher)(data, 'sha256'); }; exports.sha256 = sha256; class CredentialMapper { /** * Decodes a compact SD-JWT vc to it's decoded variant. This method can be used when the hasher implementation used is Async, and therefore not suitable for usage * with the other decode methods. */ static decodeSdJwtVcAsync(compactSdJwtVc, hasher) { return (0, types_1.decodeSdJwtVcAsync)(compactSdJwtVc, hasher !== null && hasher !== void 0 ? hasher : exports.sha256); } /** * Decodes a Verifiable Presentation to a uniform format. * * When decoding SD-JWT credentials, a hasher implementation must be provided. The hasher implementation must be sync. When using * an async hasher implementation, use the decodeSdJwtVcAsync method instead and you can provide the decoded payload to methods * instead of the compact SD-JWT. * * @param presentation * @param hasher Hasher implementation to use for SD-JWT decoding. */ static decodeVerifiablePresentation(presentation, hasher) { var _a; if (CredentialMapper.isJwtEncoded(presentation)) { const payload = (0, jwt_decode_1.jwtDecode)(presentation); const header = (0, jwt_decode_1.jwtDecode)(presentation, { header: true }); payload.vp.proof = { type: types_1.IProofType.JwtProof2020, created: payload.nbf, proofPurpose: types_1.IProofPurpose.authentication, verificationMethod: (_a = header['kid']) !== null && _a !== void 0 ? _a : payload.iss, jwt: presentation, }; return payload; } else if (CredentialMapper.isJwtDecodedPresentation(presentation)) { return presentation; } else if (CredentialMapper.isSdJwtEncoded(presentation)) { return (0, types_1.decodeSdJwtVc)(presentation, hasher !== null && hasher !== void 0 ? hasher : exports.sha256); } else if (CredentialMapper.isSdJwtDecodedCredential(presentation)) { return presentation; } else if (CredentialMapper.isMsoMdocOid4VPEncoded(presentation)) { return presentation; } else if (CredentialMapper.isMsoMdocDecodedPresentation(presentation)) { return presentation; } else if (CredentialMapper.isJsonLdAsString(presentation)) { return JSON.parse(presentation); } else { return presentation; } } /** * Decodes a Verifiable Credential to a uniform format. * * When decoding SD-JWT credentials, a hasher implementation must be provided. The hasher implementation must be sync. When using * an async hasher implementation, use the decodeSdJwtVcAsync method instead and you can provide the decoded payload to methods * instead of the compact SD-JWT. * * @param hasher Hasher implementation to use for SD-JWT decoding */ static decodeVerifiableCredential(credential, hasher) { var _a; if (CredentialMapper.isJwtEncoded(credential)) { const payload = (0, jwt_decode_1.jwtDecode)(credential); const header = (0, jwt_decode_1.jwtDecode)(credential, { header: true }); payload.vc.proof = { type: types_1.IProofType.JwtProof2020, created: payload.nbf, proofPurpose: types_1.IProofPurpose.authentication, verificationMethod: (_a = header['kid']) !== null && _a !== void 0 ? _a : payload.iss, jwt: credential, }; return payload; } else if (CredentialMapper.isJwtDecodedCredential(credential)) { return credential; } else if (CredentialMapper.isJsonLdAsString(credential)) { return JSON.parse(credential); } else if (CredentialMapper.isSdJwtEncoded(credential)) { return (0, types_1.decodeSdJwtVc)(credential, hasher !== null && hasher !== void 0 ? hasher : exports.sha256); } else if (CredentialMapper.isSdJwtDecodedCredential(credential)) { return credential; } else { return credential; } } /** * Converts a presentation to a wrapped presentation. * * When decoding SD-JWT credentials, a hasher implementation must be provided. The hasher implementation must be sync. When using * an async hasher implementation, use the decodeSdJwtVcAsync method instead and you can provide the decoded payload to methods * instead of the compact SD-JWT. * * @param hasher Hasher implementation to use for SD-JWT decoding */ static toWrappedVerifiablePresentation(originalPresentation, opts) { var _a, _b, _c; // MSO_MDOC if (CredentialMapper.isMsoMdocDecodedPresentation(originalPresentation) || CredentialMapper.isMsoMdocOid4VPEncoded(originalPresentation)) { let deviceResponse; let originalType; if (CredentialMapper.isMsoMdocOid4VPEncoded(originalPresentation)) { deviceResponse = (0, types_1.decodeMdocDeviceResponse)(originalPresentation); originalType = types_1.OriginalType.MSO_MDOC_ENCODED; } else { deviceResponse = originalPresentation; originalType = types_1.OriginalType.MSO_MDOC_DECODED; } const mdocCredentials = (_a = deviceResponse.documents) === null || _a === void 0 ? void 0 : _a.map((doc) => CredentialMapper.toWrappedVerifiableCredential(doc, opts)); if (!mdocCredentials || mdocCredentials.length === 0) { throw new Error('could not extract any mdoc credentials from mdoc device response'); } return { type: originalType, format: 'mso_mdoc', original: originalPresentation, presentation: deviceResponse, decoded: deviceResponse, vcs: mdocCredentials, }; } // SD-JWT if (CredentialMapper.isSdJwtDecodedCredential(originalPresentation) || CredentialMapper.isSdJwtEncoded(originalPresentation)) { let decodedPresentation; if (CredentialMapper.isSdJwtEncoded(originalPresentation)) { decodedPresentation = (0, types_1.decodeSdJwtVc)(originalPresentation, (_b = opts === null || opts === void 0 ? void 0 : opts.hasher) !== null && _b !== void 0 ? _b : exports.sha256); } else { decodedPresentation = originalPresentation; } return { type: CredentialMapper.isSdJwtDecodedCredential(originalPresentation) ? types_1.OriginalType.SD_JWT_VC_DECODED : types_1.OriginalType.SD_JWT_VC_ENCODED, format: 'vc+sd-jwt', original: originalPresentation, presentation: decodedPresentation, decoded: decodedPresentation.decodedPayload, // NOTE: we also include the SD-JWT VC as the VC, as the SD-JWT acts as both the VC and the VP vcs: [CredentialMapper.toWrappedVerifiableCredential(originalPresentation, opts)], }; } // If the VP is not an encoded/decoded SD-JWT, we assume it will be a W3C VC const proof = CredentialMapper.getFirstProof(originalPresentation); const original = typeof originalPresentation !== 'string' && CredentialMapper.hasJWTProofType(originalPresentation) ? proof === null || proof === void 0 ? void 0 : proof.jwt : originalPresentation; if (!original) { throw Error('Could not determine original presentation, probably it was a converted JWT presentation, that is now missing the JWT value in the proof'); } const decoded = CredentialMapper.decodeVerifiablePresentation(original); const isJwtEncoded = CredentialMapper.isJwtEncoded(original); const isJwtDecoded = CredentialMapper.isJwtDecodedPresentation(original); const type = isJwtEncoded ? types_1.OriginalType.JWT_ENCODED : isJwtDecoded ? types_1.OriginalType.JWT_DECODED : types_1.OriginalType.JSONLD; const format = isJwtDecoded || isJwtEncoded ? 'jwt_vp' : 'ldp_vp'; let vp; if (isJwtEncoded || isJwtDecoded) { vp = CredentialMapper.jwtDecodedPresentationToUniformPresentation(decoded, false, opts); } else { vp = decoded; } if (!vp) { throw Error(`VP key not found`); } const noVCs = !('verifiableCredential' in vp) || !vp.verifiableCredential || vp.verifiableCredential.length === 0; if (noVCs) { console.warn(`Presentation without verifiable credentials. That is rare! `); // throw Error(`VP needs to have at least one verifiable credential at this point`) } const vcs = noVCs ? [] : CredentialMapper.toWrappedVerifiableCredentials((_c = vp.verifiableCredential) !== null && _c !== void 0 ? _c : [] /*.map(value => value.original)*/, opts); const presentation = Object.assign(Object.assign({}, vp), { verifiableCredential: vcs }); return { type, format, original, decoded, presentation, vcs, }; } /** * Converts a list of credentials to a list of wrapped credentials. * * When decoding SD-JWT credentials, a hasher implementation must be provided. The hasher implementation must be sync. When using * an async hasher implementation, use the decodeSdJwtVcAsync method instead and you can provide the decoded payload to methods * instead of the compact SD-JWT. * * @param hasher Hasher implementation to use for SD-JWT decoding */ static toWrappedVerifiableCredentials(verifiableCredentials, opts) { return verifiableCredentials.map((vc) => CredentialMapper.toWrappedVerifiableCredential(vc, opts)); } /** * Converts a credential to a wrapped credential. * * When decoding SD-JWT credentials, a hasher implementation must be provided. The hasher implementation must be sync. When using * an async hasher implementation, use the decodeSdJwtVcAsync method instead and you can provide the decoded payload to methods * instead of the compact SD-JWT. * * @param hasher Hasher implementation to use for SD-JWT decoding */ static toWrappedVerifiableCredential(verifiableCredential, opts) { var _a, _b; // MSO_MDOC if (CredentialMapper.isMsoMdocDecodedCredential(verifiableCredential) || CredentialMapper.isMsoMdocOid4VPEncoded(verifiableCredential)) { let mdoc; if (CredentialMapper.isMsoMdocOid4VPEncoded(verifiableCredential)) { mdoc = (0, types_1.decodeMdocIssuerSigned)(verifiableCredential); } else { mdoc = verifiableCredential; } return { type: CredentialMapper.isMsoMdocDecodedCredential(verifiableCredential) ? types_1.OriginalType.MSO_MDOC_DECODED : types_1.OriginalType.MSO_MDOC_ENCODED, format: 'mso_mdoc', original: verifiableCredential, credential: mdoc, decoded: (0, types_1.getMdocDecodedPayload)(mdoc), }; } // SD-JWT if (CredentialMapper.isSdJwtDecodedCredential(verifiableCredential) || CredentialMapper.isSdJwtEncoded(verifiableCredential)) { let decodedCredential; if (CredentialMapper.isSdJwtEncoded(verifiableCredential)) { const hasher = (_a = opts === null || opts === void 0 ? void 0 : opts.hasher) !== null && _a !== void 0 ? _a : exports.sha256; decodedCredential = (0, types_1.decodeSdJwtVc)(verifiableCredential, hasher); } else { decodedCredential = verifiableCredential; } return { type: CredentialMapper.isSdJwtDecodedCredential(verifiableCredential) ? types_1.OriginalType.SD_JWT_VC_DECODED : types_1.OriginalType.SD_JWT_VC_ENCODED, format: 'vc+sd-jwt', original: verifiableCredential, credential: decodedCredential, decoded: decodedCredential.decodedPayload, }; } // If the VC is not an encoded/decoded SD-JWT, we assume it will be a W3C VC const proof = CredentialMapper.getFirstProof(verifiableCredential); const original = CredentialMapper.hasJWTProofType(verifiableCredential) && proof ? ((_b = proof.jwt) !== null && _b !== void 0 ? _b : verifiableCredential) : verifiableCredential; if (!original) { throw Error('Could not determine original credential, probably it was a converted JWT credential, that is now missing the JWT value in the proof'); } const decoded = CredentialMapper.decodeVerifiableCredential(original); const isJwtEncoded = CredentialMapper.isJwtEncoded(original); const isJwtDecoded = CredentialMapper.isJwtDecodedCredential(original); const type = isJwtEncoded ? types_1.OriginalType.JWT_ENCODED : isJwtDecoded ? types_1.OriginalType.JWT_DECODED : types_1.OriginalType.JSONLD; const credential = isJwtEncoded || isJwtDecoded ? CredentialMapper.jwtDecodedCredentialToUniformCredential(decoded, opts) : decoded; const format = isJwtEncoded || isJwtDecoded ? 'jwt_vc' : 'ldp_vc'; return { original, decoded, format, type, credential, }; } static isJwtEncoded(original) { return utils_1.ObjectUtils.isString(original) && original.startsWith('ey') && !original.includes('~'); } static isSdJwtEncoded(original) { return utils_1.ObjectUtils.isString(original) && original.startsWith('ey') && original.includes('~'); } static isMsoMdocOid4VPEncoded(original) { return utils_1.ObjectUtils.isString(original) && !original.startsWith('ey') && utils_1.ObjectUtils.isBase64(original); } static isW3cCredential(credential) { var _a; return typeof credential === 'object' && '@context' in credential && (((_a = credential.type) === null || _a === void 0 ? void 0 : _a.includes('VerifiableCredential')) || false); } static isCredential(original) { try { if (CredentialMapper.isJwtEncoded(original)) { const vc = CredentialMapper.toUniformCredential(original); return CredentialMapper.isW3cCredential(vc); } else if (CredentialMapper.isSdJwtEncoded(original)) { return true; } else if (CredentialMapper.isMsoMdocDecodedCredential(original)) { return true; } else if (CredentialMapper.isMsoMdocOid4VPEncoded(original)) { return true; } return (CredentialMapper.isW3cCredential(original) || CredentialMapper.isSdJwtDecodedCredentialPayload(original) || CredentialMapper.isJwtDecodedCredential(original) || CredentialMapper.isSdJwtDecodedCredential(original)); } catch (e) { return false; } } static isPresentation(original) { try { if (CredentialMapper.isJwtEncoded(original)) { const vp = CredentialMapper.toUniformPresentation(original); return CredentialMapper.isW3cPresentation(vp); } else if (CredentialMapper.isSdJwtEncoded(original)) { return false; // @ts-expect-error } else if (CredentialMapper.isMsoMdocDecodedPresentation(original)) { return true; } else if (CredentialMapper.isMsoMdocOid4VPEncoded(original)) { return true; } return (CredentialMapper.isW3cPresentation(original) || CredentialMapper.isSdJwtDecodedCredentialPayload(original) || CredentialMapper.isJwtDecodedPresentation(original) || CredentialMapper.isSdJwtDecodedCredential(original)); } catch (e) { return false; } } static hasProof(original) { try { if (CredentialMapper.isMsoMdocOid4VPEncoded(original)) { return false; // @ts-ignore } else if (CredentialMapper.isMsoMdocDecodedCredential(original) || CredentialMapper.isMsoMdocDecodedPresentation(original)) { return true; } else if (CredentialMapper.isJwtEncoded(original) || CredentialMapper.isJwtDecodedCredential(original)) { return true; } else if (CredentialMapper.isSdJwtEncoded(original) || CredentialMapper.isSdJwtDecodedCredential(original)) { //todo: we might want to revisit this return true; } if (typeof original !== 'object') { return false; } if ('vc' in original && original.vc.proof) { return true; } if ('vp' in original && original.vp.proof) { return true; } return !!original.proof; } catch (e) { return false; } } static isW3cPresentation(presentation) { var _a; return (typeof presentation === 'object' && '@context' in presentation && (((_a = presentation.type) === null || _a === void 0 ? void 0 : _a.includes('VerifiablePresentation')) || false)); } static isSdJwtDecodedCredentialPayload(credential) { return typeof credential === 'object' && 'vct' in credential; } static areOriginalVerifiableCredentialsEqual(firstOriginal, secondOriginal) { // String (e.g. encoded jwt or SD-JWT) if (typeof firstOriginal === 'string' || typeof secondOriginal === 'string') { return firstOriginal === secondOriginal; } else if (CredentialMapper.isMsoMdocDecodedCredential(firstOriginal) || CredentialMapper.isMsoMdocDecodedCredential(secondOriginal)) { if (!CredentialMapper.isMsoMdocDecodedCredential(firstOriginal) || !CredentialMapper.isMsoMdocDecodedCredential(secondOriginal)) { // We are doing this over here, as the rest of the logic around it would otherwise need to be adjusted substantially return false; } // FIXME: mdoc library fails on parsing the device signed, so for now we just check whether the issuerSigned // is equal, then we have a good chance it is the same credential. Once device signed parsing is fixed in mdl // library we can move the .equals() to the top-level object. return firstOriginal.issuerSigned.equals(secondOriginal.issuerSigned); } else if (CredentialMapper.isSdJwtDecodedCredential(firstOriginal) || CredentialMapper.isSdJwtDecodedCredential(secondOriginal)) { return firstOriginal.compactSdJwtVc === secondOriginal.compactSdJwtVc; } else { // JSON-LD or decoded JWT. (should we compare the signatures instead?) return JSON.stringify(secondOriginal.proof) === JSON.stringify(firstOriginal.proof); } } static isJsonLdAsString(original) { return utils_1.ObjectUtils.isString(original) && original.includes('@context'); } static isSdJwtDecodedCredential(original) { return (typeof original === 'object' && (original.compactSdJwtVc !== undefined || original.kbJwt !== undefined)); } static isMsoMdocDecodedCredential(original) { return typeof original === 'object' && 'issuerSigned' in original && original.issuerSigned !== undefined; } static isMsoMdocDecodedPresentation(original) { return typeof original === 'object' && 'version' in original && original.version !== undefined; } static isJwtDecodedCredential(original) { return (typeof original === 'object' && original.vc !== undefined && original.iss !== undefined); } static isJwtDecodedPresentation(original) { return (typeof original === 'object' && original.vp !== undefined && original.iss !== undefined); } static jwtEncodedPresentationToUniformPresentation(jwt, makeCredentialsUniform = true, opts) { return CredentialMapper.jwtDecodedPresentationToUniformPresentation((0, jwt_decode_1.jwtDecode)(jwt), makeCredentialsUniform, opts); } static jwtDecodedPresentationToUniformPresentation(decoded, makeCredentialsUniform = true, opts) { const { iss, aud, jti, vp } = decoded, rest = __rest(decoded, ["iss", "aud", "jti", "vp"]); const presentation = Object.assign(Object.assign({}, rest), vp); if (makeCredentialsUniform) { if (!vp.verifiableCredential) { throw Error('Verifiable Presentation should have a verifiable credential at this point'); } presentation.verifiableCredential = vp.verifiableCredential.map((vc) => CredentialMapper.toUniformCredential(vc, opts)); } if (iss) { const holder = presentation.holder; if (holder) { if (holder !== iss) { throw new Error(`Inconsistent holders between JWT claim (${iss}) and VC value (${holder})`); } } presentation.holder = iss; } if (aud) { const verifier = presentation.verifier; if (verifier) { if (verifier !== aud) { throw new Error(`Inconsistent holders between JWT claim (${aud}) and VC value (${verifier})`); } } presentation.verifier = aud; } if (jti) { const id = presentation.id; if (id && id !== jti) { throw new Error(`Inconsistent VP ids between JWT claim (${jti}) and VP value (${id})`); } presentation.id = jti; } return presentation; } static toUniformCredential(verifiableCredential, opts) { var _a, _b; if (CredentialMapper.isMsoMdocDecodedCredential(verifiableCredential)) { return (0, types_1.mdocDecodedCredentialToUniformCredential)(verifiableCredential); } if (CredentialMapper.isSdJwtDecodedCredential(verifiableCredential)) { return (0, types_1.sdJwtDecodedCredentialToUniformCredential)(verifiableCredential, opts); } const original = typeof verifiableCredential !== 'string' && CredentialMapper.hasJWTProofType(verifiableCredential) ? (_a = CredentialMapper.getFirstProof(verifiableCredential)) === null || _a === void 0 ? void 0 : _a.jwt : verifiableCredential; if (!original) { throw Error('Could not determine original credential from passed in credential. Probably because a JWT proof type was present, but now is not available anymore'); } const decoded = CredentialMapper.decodeVerifiableCredential(original, (_b = opts === null || opts === void 0 ? void 0 : opts.hasher) !== null && _b !== void 0 ? _b : exports.sha256); const isJwtEncoded = CredentialMapper.isJwtEncoded(original); const isJwtDecoded = CredentialMapper.isJwtDecodedCredential(original); const isSdJwtEncoded = CredentialMapper.isSdJwtEncoded(original); const isMdocEncoded = CredentialMapper.isMsoMdocOid4VPEncoded(original); if (isSdJwtEncoded) { return (0, types_1.sdJwtDecodedCredentialToUniformCredential)(decoded, opts); } else if (isMdocEncoded) { return (0, types_1.mdocDecodedCredentialToUniformCredential)((0, types_1.decodeMdocIssuerSigned)(original)); } else if (isJwtDecoded || isJwtEncoded) { return CredentialMapper.jwtDecodedCredentialToUniformCredential(decoded, opts); } else { return decoded; } } static toUniformPresentation(presentation, opts) { var _a, _b; if (CredentialMapper.isSdJwtDecodedCredential(presentation)) { throw new Error('Converting SD-JWT VC to uniform VP is not supported.'); } else if (CredentialMapper.isMsoMdocDecodedPresentation(presentation)) { throw new Error('Converting MSO_MDOC to uniform VP is not supported yet.'); } const proof = CredentialMapper.getFirstProof(presentation); const original = typeof presentation !== 'string' && CredentialMapper.hasJWTProofType(presentation) ? proof === null || proof === void 0 ? void 0 : proof.jwt : presentation; if (!original) { throw Error('Could not determine original presentation, probably it was a converted JWT presentation, that is now missing the JWT value in the proof'); } const decoded = CredentialMapper.decodeVerifiablePresentation(original, (_a = opts === null || opts === void 0 ? void 0 : opts.hasher) !== null && _a !== void 0 ? _a : exports.sha256); const isJwtEncoded = CredentialMapper.isJwtEncoded(original); const isJwtDecoded = CredentialMapper.isJwtDecodedPresentation(original); const uniformPresentation = isJwtEncoded || isJwtDecoded ? CredentialMapper.jwtDecodedPresentationToUniformPresentation(decoded, false) : decoded; // At time of writing Velocity Networks does not conform to specification. Adding bare minimum @context section to stop parsers from crashing and whatnot if ((opts === null || opts === void 0 ? void 0 : opts.addContextIfMissing) && !uniformPresentation['@context']) { uniformPresentation['@context'] = ['https://www.w3.org/2018/credentials/v1']; } uniformPresentation.verifiableCredential = (_b = uniformPresentation.verifiableCredential) === null || _b === void 0 ? void 0 : _b.map((vc) => CredentialMapper.toUniformCredential(vc, opts)); // We cast it because we IPresentation needs a VC. The internal Credential doesn't have the required Proof anymore (that is intended) return uniformPresentation; } static jwtEncodedCredentialToUniformCredential(jwt, opts) { return CredentialMapper.jwtDecodedCredentialToUniformCredential((0, jwt_decode_1.jwtDecode)(jwt), opts); } static jwtDecodedCredentialToUniformCredential(decoded, opts) { var _a; const { exp, nbf, iss, vc, sub, jti } = decoded, rest = __rest(decoded, ["exp", "nbf", "iss", "vc", "sub", "jti"]); const credential = Object.assign(Object.assign({}, rest), vc); const maxSkewInMS = (_a = opts === null || opts === void 0 ? void 0 : opts.maxTimeSkewInMS) !== null && _a !== void 0 ? _a : 1500; if (exp) { const expDate = credential.expirationDate; const jwtExp = parseInt(exp.toString()); // fix seconds to millisecond for the date const expDateAsStr = jwtExp < 9999999999 ? new Date(jwtExp * 1000).toISOString().replace(/\.000Z/, 'Z') : new Date(jwtExp).toISOString(); if (expDate && expDate !== expDateAsStr) { const diff = Math.abs(new Date(expDateAsStr).getTime() - new Date(expDate).getTime()); if (!maxSkewInMS || diff > maxSkewInMS) { throw new Error(`Inconsistent expiration dates between JWT claim (${expDateAsStr}) and VC value (${expDate})`); } } credential.expirationDate = expDateAsStr; } if (nbf) { const issuanceDate = credential.issuanceDate; const jwtNbf = parseInt(nbf.toString()); // fix seconds to millisecs for the date const nbfDateAsStr = jwtNbf < 9999999999 ? new Date(jwtNbf * 1000).toISOString().replace(/\.000Z/, 'Z') : new Date(jwtNbf).toISOString(); if (issuanceDate && issuanceDate !== nbfDateAsStr) { const diff = Math.abs(new Date(nbfDateAsStr).getTime() - new Date(issuanceDate).getTime()); if (!maxSkewInMS || diff > maxSkewInMS) { throw new Error(`Inconsistent issuance dates between JWT claim (${nbfDateAsStr}) and VC value (${issuanceDate})`); } } credential.issuanceDate = nbfDateAsStr; } if (iss) { const issuer = credential.issuer; if (issuer) { if (typeof issuer === 'string') { if (issuer !== iss) { throw new Error(`Inconsistent issuers between JWT claim (${iss}) and VC value (${issuer})`); } } else { if (!issuer.id && Object.keys(issuer).length > 0) { // We have an issuer object with more than 1 property but without an issuer id. Set it, // because the default behaviour of did-jwt-vc is to remove the id value when creating JWTs issuer.id = iss; } if (issuer.id !== iss) { throw new Error(`Inconsistent issuers between JWT claim (${iss}) and VC value (${issuer.id})`); } } } else { credential.issuer = iss; } } if (sub) { const subjects = Array.isArray(credential.credentialSubject) ? credential.credentialSubject : [credential.credentialSubject]; for (let i = 0; i < subjects.length; i++) { const csId = subjects[i].id; if (csId && csId !== sub) { throw new Error(`Inconsistent credential subject ids between JWT claim (${sub}) and VC value (${csId})`); } Array.isArray(credential.credentialSubject) ? (credential.credentialSubject[i].id = sub) : (credential.credentialSubject.id = sub); } } if (jti) { const id = credential.id; if (id && id !== jti) { throw new Error(`Inconsistent credential ids between JWT claim (${jti}) and VC value (${id})`); } credential.id = jti; } return credential; } static toExternalVerifiableCredential(verifiableCredential) { let proof; if (verifiableCredential.proof) { if (!verifiableCredential.proof.type) { throw new Error('Verifiable credential proof is missing a type'); } if (!verifiableCredential.proof.created) { throw new Error('Verifiable credential proof is missing a created date'); } if (!verifiableCredential.proof.proofPurpose) { throw new Error('Verifiable credential proof is missing a proof purpose'); } if (!verifiableCredential.proof.verificationMethod) { throw new Error('Verifiable credential proof is missing a verification method'); } proof = Object.assign(Object.assign({}, verifiableCredential.proof), { type: verifiableCredential.proof.type, created: verifiableCredential.proof.created, proofPurpose: verifiableCredential.proof.proofPurpose, verificationMethod: verifiableCredential.proof.verificationMethod }); } return Object.assign(Object.assign({}, verifiableCredential), { type: verifiableCredential.type ? typeof verifiableCredential.type === 'string' ? [verifiableCredential.type] : verifiableCredential.type : ['VerifiableCredential'], proof }); } static storedCredentialToOriginalFormat(credential) { const type = CredentialMapper.detectDocumentType(credential); if (typeof credential === 'string') { if (type === 0 /* DocumentFormat.JWT */) { return CredentialMapper.toCompactJWT(credential); } else if (type === 1 /* DocumentFormat.JSONLD */) { return JSON.parse(credential); } else if (type === 2 /* DocumentFormat.SD_JWT_VC */) { return credential; } } else if (type === 0 /* DocumentFormat.JWT */ && utils_1.ObjectUtils.isObject(credential) && 'vc' in credential) { return CredentialMapper.toCompactJWT(credential); } else if (utils_1.ObjectUtils.isObject(credential) && 'proof' in credential && credential.proof.type === 'JwtProof2020' && credential.proof.jwt) { return credential.proof.jwt; } else if (utils_1.ObjectUtils.isObject(credential) && 'proof' in credential && credential.proof.type === types_1.IProofType.SdJwtProof2024 && credential.proof.jwt) { return credential.proof.jwt; } else if (type === 2 /* DocumentFormat.SD_JWT_VC */ && this.isSdJwtDecodedCredential(credential)) { return credential.compactSdJwtVc; } return credential; } static storedPresentationToOriginalFormat(presentation) { const type = CredentialMapper.detectDocumentType(presentation); if (typeof presentation === 'string') { if (type === 0 /* DocumentFormat.JWT */) { return CredentialMapper.toCompactJWT(presentation); } else if (type === 1 /* DocumentFormat.JSONLD */) { return JSON.parse(presentation); } } else if (type === 0 /* DocumentFormat.JWT */ && utils_1.ObjectUtils.isObject(presentation) && 'vp' in presentation) { return CredentialMapper.toCompactJWT(presentation); } else if (utils_1.ObjectUtils.isObject(presentation) && 'proof' in presentation && presentation.proof.type === 'JwtProof2020' && presentation.proof.jwt) { return presentation.proof.jwt; } return presentation; } static toCompactJWT(jwtDocument) { if (!jwtDocument || CredentialMapper.detectDocumentType(jwtDocument) !== 0 /* DocumentFormat.JWT */) { throw Error('Cannot convert non JWT credential to JWT'); } if (typeof jwtDocument === 'string') { return jwtDocument; } let proof; if (utils_1.ObjectUtils.isObject(jwtDocument) && 'vp' in jwtDocument) { proof = 'jwt' in jwtDocument.vp.proof ? jwtDocument.vp.proof.jwt : jwtDocument.vp.proof; } else if (utils_1.ObjectUtils.isObject(jwtDocument) && 'vc' in jwtDocument) { proof = 'jwt' in jwtDocument.vc.proof ? jwtDocument.vc.proof.jwt : jwtDocument.vc.proof; } else { proof = Array.isArray(jwtDocument.proof) ? jwtDocument.proof[0].jwt : jwtDocument.proof.jwt; } if (!proof) { throw Error(`Could not get JWT from supplied document`); } return proof; } static detectDocumentType(document) { if (this.isMsoMdocOid4VPEncoded(document) || this.isMsoMdocDecodedCredential(document)) { return 4 /* DocumentFormat.MSO_MDOC */; } else if (this.isMsoMdocDecodedPresentation(document) || this.isMsoMdocDecodedPresentation(document)) { return 4 /* DocumentFormat.MSO_MDOC */; } else if (this.isJsonLdAsString(document)) { return 1 /* DocumentFormat.JSONLD */; } else if (this.isJwtEncoded(document)) { return 0 /* DocumentFormat.JWT */; } else if (this.isSdJwtEncoded(document) || this.isSdJwtDecodedCredential(document)) { return 2 /* DocumentFormat.SD_JWT_VC */; } const proofs = typeof document !== 'string' && ('vc' in document ? document.vc.proof : 'vp' in document ? document.vp.proof : document.proof); const proof = Array.isArray(proofs) ? proofs[0] : proofs; if (proof === null || proof === void 0 ? void 0 : proof.jwt) { return 0 /* DocumentFormat.JWT */; } else if ((proof === null || proof === void 0 ? void 0 : proof.type) === 'EthereumEip712Signature2021') { return 3 /* DocumentFormat.EIP712 */; } return 1 /* DocumentFormat.JSONLD */; } static hasJWTProofType(document) { var _a; if (typeof document === 'string') { return false; } return !!((_a = CredentialMapper.getFirstProof(document)) === null || _a === void 0 ? void 0 : _a.jwt); } static getFirstProof(document) { if (!document || typeof document === 'string') { return undefined; } const proofs = 'vc' in document ? document.vc.proof : 'vp' in document ? document.vp.proof : document.proof; return Array.isArray(proofs) ? proofs[0] : proofs; } static issuerCorrelationIdFromIssuerType(issuer) { if (issuer === undefined) { throw new Error('Issuer type us undefined'); } else if (typeof issuer === 'string') { return issuer; } else if (typeof issuer === 'object') { if ('id' in issuer) { return issuer.id; } else { throw new Error('Encountered an invalid issuer object: missing id property'); } } else { throw new Error('Invalid issuer type'); } } } exports.CredentialMapper = CredentialMapper; CredentialMapper.isWrappedSdJwtVerifiableCredential = types_1.isWrappedSdJwtVerifiableCredential; CredentialMapper.isWrappedSdJwtVerifiablePresentation = types_1.isWrappedSdJwtVerifiablePresentation; CredentialMapper.isWrappedW3CVerifiableCredential = types_1.isWrappedW3CVerifiableCredential; CredentialMapper.isWrappedW3CVerifiablePresentation = types_1.isWrappedW3CVerifiablePresentation; CredentialMapper.isWrappedMdocCredential = types_1.isWrappedMdocCredential; CredentialMapper.isWrappedMdocPresentation = types_1.isWrappedMdocPresentation; //# sourceMappingURL=credential-mapper.js.map