Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

did-jwt-vc

Package Overview
Dependencies
Maintainers
4
Versions
66
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

did-jwt-vc - npm Package Compare versions

Comparing version 3.1.4 to 3.2.0

2

lib/index.d.ts

@@ -23,3 +23,3 @@ import { Resolvable } from 'did-resolver';

*/
export declare function createVerifiableCredentialJwt(payload: JwtCredentialPayload | CredentialPayload, issuer: Issuer, options?: CreateCredentialOptions): Promise<JWT>;
export declare function createVerifiableCredentialJwt(payload: JwtCredentialPayload | CredentialPayload, issuer: Issuer | Issuer[], options?: CreateCredentialOptions): Promise<JWT>;
/**

@@ -26,0 +26,0 @@ * Creates a VerifiablePresentation JWT given a `PresentationPayload` or `JwtPresentationPayload` and an `Issuer`.

@@ -1,2 +0,2 @@

import { decodeJWT, JWT_ERROR, createJWT, verifyJWT } from 'did-jwt';
import { decodeJWT, JWT_ERROR, createJWT, createMultisignatureJWT, verifyJWT } from 'did-jwt';

@@ -7,3 +7,2 @@ function _extends() {

var source = arguments[i];
for (var key in source) {

@@ -15,3 +14,2 @@ if (Object.prototype.hasOwnProperty.call(source, key)) {

}
return target;

@@ -21,3 +19,2 @@ };

}
function _objectWithoutPropertiesLoose(source, excluded) {

@@ -28,3 +25,2 @@ if (source == null) return {};

var key, i;
for (i = 0; i < sourceKeys.length; i++) {

@@ -35,3 +31,2 @@ key = sourceKeys[i];

}
return target;

@@ -54,9 +49,7 @@ }

*/
const additionalPropNames = ['evidence', 'termsOfUse', 'refreshService', 'credentialSchema', 'credentialStatus']; // eslint-disable-next-line @typescript-eslint/no-explicit-any
const additionalPropNames = ['evidence', 'termsOfUse', 'refreshService', 'credentialSchema', 'credentialStatus'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function asArray(arg) {
return Array.isArray(arg) ? arg : [arg];
}
function deepCopy(source) {

@@ -69,7 +62,5 @@ return Array.isArray(source) ? source.map(item => deepCopy(item)) : source instanceof Date ? new Date(source.getTime()) : source && typeof source === 'object' ? Object.getOwnPropertyNames(source).reduce((o, prop) => {

}
function notEmpty(value) {
return value !== null && value !== undefined;
}
function cleanUndefined(input) {

@@ -79,24 +70,20 @@ if (typeof input !== 'object') {

}
const obj = _extends({}, input);
Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key]);
return obj;
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isLegacyAttestationFormat(payload) {
// payload is an object and has all the required fields of old attestation format
return typeof payload === 'object' && payload.sub && payload.iss && payload.claim && payload.iat;
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function attestationToVcFormat(payload) {
const {
iat,
nbf,
claim,
vc
} = payload,
rest = _objectWithoutPropertiesLoose(payload, _excluded);
iat,
nbf,
claim,
vc
} = payload,
rest = _objectWithoutPropertiesLoose(payload, _excluded);
const result = _extends({}, rest, {

@@ -110,22 +97,15 @@ nbf: nbf ? nbf : iat,

});
if (vc) payload.issVc = vc;
return result;
}
function normalizeJwtCredentialPayload(input, removeOriginalFields = true) {
var _input$vc, _input$credentialSubj, _result$vc2, _input$vc2;
let result = deepCopy(input);
if (isLegacyAttestationFormat(input)) {
result = attestationToVcFormat(input);
} // FIXME: handle case when credentialSubject(s) are not object types
}
// FIXME: handle case when credentialSubject(s) are not object types
result.credentialSubject = _extends({}, input.credentialSubject, (_input$vc = input.vc) == null ? void 0 : _input$vc.credentialSubject);
if (input.sub && !((_input$credentialSubj = input.credentialSubject) != null && _input$credentialSubj.id) && result.credentialSubject) {
result.credentialSubject.id = input.sub;
if (removeOriginalFields) {

@@ -135,16 +115,11 @@ delete result.sub;

}
if (removeOriginalFields) {
var _result$vc;
(_result$vc = result.vc) == null ? true : delete _result$vc.credentialSubject;
}
if (typeof input.issuer === 'undefined' || typeof input.issuer === 'object') {
var _input$issuer;
result.issuer = cleanUndefined(_extends({
id: input.iss
}, input.issuer));
if (removeOriginalFields && !((_input$issuer = input.issuer) != null && _input$issuer.id)) {

@@ -154,6 +129,4 @@ delete result.iss;

}
if (!input.id && input.jti) {
result.id = result.id || result.jti;
if (removeOriginalFields) {

@@ -163,12 +136,8 @@ delete result.jti;

}
const types = [...asArray(result.type), ...asArray((_result$vc2 = result.vc) == null ? void 0 : _result$vc2.type)].filter(notEmpty);
result.type = [...new Set(types)];
if (removeOriginalFields) {
var _result$vc3;
(_result$vc3 = result.vc) == null ? true : delete _result$vc3.type;
}
for (const prop of additionalPropNames) {

@@ -179,3 +148,2 @@ if (input.vc && input.vc[prop]) {

}
if (removeOriginalFields) {

@@ -186,16 +154,11 @@ delete result.vc[prop];

}
const contextArray = [...asArray(input.context), ...asArray(input['@context']), ...asArray((_input$vc2 = input.vc) == null ? void 0 : _input$vc2['@context'])].filter(notEmpty);
result['@context'] = [...new Set(contextArray)];
if (removeOriginalFields) {
var _result$vc4;
delete result.context;
(_result$vc4 = result.vc) == null ? true : delete _result$vc4['@context'];
}
if (!input.issuanceDate && (input.iat || input.nbf)) {
result.issuanceDate = new Date((input.nbf || input.iat) * 1000).toISOString();
if (removeOriginalFields) {

@@ -209,6 +172,4 @@ if (input.nbf) {

}
if (!input.expirationDate && input.exp) {
result.expirationDate = new Date(input.exp * 1000).toISOString();
if (removeOriginalFields) {

@@ -218,3 +179,2 @@ delete result.exp;

}
if (removeOriginalFields) {

@@ -224,11 +184,8 @@ if (result.vc && Object.keys(result.vc).length === 0) {

}
} // FIXME: interpret `aud` property as `verifier`
}
// FIXME: interpret `aud` property as `verifier`
return result;
}
function normalizeJwtCredential(input, removeOriginalFields = true) {
let decoded;
try {

@@ -239,3 +196,2 @@ decoded = decodeJWT(input);

}
return _extends({}, normalizeJwtCredentialPayload(decoded.payload, removeOriginalFields), {

@@ -254,7 +210,4 @@ proof: {

*/
function normalizeCredential(input, removeOriginalFields = true) {
var _input$proof;
if (typeof input === 'string') {

@@ -265,3 +218,2 @@ if (JWT_FORMAT.test(input)) {

let parsed;
try {

@@ -272,3 +224,2 @@ parsed = JSON.parse(input);

}
return normalizeCredential(parsed, removeOriginalFields);

@@ -295,6 +246,4 @@ }

*/
function transformCredentialInput(input, removeOriginalFields = true) {
var _input$vc3, _input$vc4, _input$vc5;
if (Array.isArray(input.credentialSubject)) throw Error('credentialSubject of type array not supported');

@@ -305,10 +254,6 @@ const result = deepCopy(_extends({

result.vc = result.vc;
const credentialSubject = _extends({}, input.credentialSubject, (_input$vc3 = input.vc) == null ? void 0 : _input$vc3.credentialSubject);
if (!input.sub) {
var _input$credentialSubj2;
result.sub = (_input$credentialSubj2 = input.credentialSubject) == null ? void 0 : _input$credentialSubj2.id;
if (removeOriginalFields) {

@@ -318,6 +263,4 @@ delete credentialSubject.id;

}
const contextEntries = [...asArray(input.context), ...asArray(input['@context']), ...asArray((_input$vc4 = input.vc) == null ? void 0 : _input$vc4['@context'])].filter(notEmpty);
result.vc['@context'] = [...new Set(contextEntries)];
if (removeOriginalFields) {

@@ -327,13 +270,9 @@ delete result.context;

}
const types = [...asArray(input.type), ...asArray((_input$vc5 = input.vc) == null ? void 0 : _input$vc5.type)].filter(notEmpty);
result.vc.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.type;
}
if (input.id && Object.getOwnPropertyNames(input).indexOf('jti') === -1) {
result.jti = input.id;
if (removeOriginalFields) {

@@ -343,9 +282,6 @@ delete result.id;

}
if (input.issuanceDate && Object.getOwnPropertyNames(input).indexOf('nbf') === -1) {
const converted = Date.parse(input.issuanceDate);
if (!isNaN(converted)) {
result.nbf = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -356,9 +292,6 @@ delete result.issuanceDate;

}
if (input.expirationDate && Object.getOwnPropertyNames(input).indexOf('exp') === -1) {
const converted = Date.parse(input.expirationDate);
if (!isNaN(converted)) {
result.exp = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -369,12 +302,8 @@ delete result.expirationDate;

}
if (input.issuer && Object.getOwnPropertyNames(input).indexOf('iss') === -1) {
if (typeof input.issuer === 'object') {
var _input$issuer2;
result.iss = (_input$issuer2 = input.issuer) == null ? void 0 : _input$issuer2.id;
if (removeOriginalFields) {
delete result.issuer.id;
if (Object.keys(result.issuer).length === 0) {

@@ -386,3 +315,2 @@ delete result.issuer;

result.iss = input.iss || '' + input.issuer;
if (removeOriginalFields) {

@@ -393,9 +321,6 @@ delete result.issuer;

}
result.vc.credentialSubject = credentialSubject;
if (removeOriginalFields) {
delete result.credentialSubject;
}
for (const prop of additionalPropNames) {

@@ -406,3 +331,2 @@ if (input[prop]) {

}
if (removeOriginalFields) {

@@ -413,9 +337,6 @@ delete result[prop];

}
return result;
}
function normalizeJwtPresentationPayload(input, removeOriginalFields = true) {
var _input$vp, _input$vp2, _input$vp3;
const result = deepCopy(input);

@@ -426,12 +347,8 @@ result.verifiableCredential = [...asArray(input.verifiableCredential), ...asArray((_input$vp = input.vp) == null ? void 0 : _input$vp.verifiableCredential)].filter(notEmpty);

});
if (removeOriginalFields) {
var _result$vp;
(_result$vp = result.vp) == null ? true : delete _result$vp.verifiableCredential;
}
if (input.iss && !input.holder) {
result.holder = input.iss;
if (removeOriginalFields) {

@@ -441,7 +358,5 @@ delete result.iss;

}
if (input.aud) {
result.verifier = [...asArray(input.verifier), ...asArray(input.aud)].filter(notEmpty);
result.verifier = [...new Set(result.verifier)];
if (removeOriginalFields) {

@@ -451,6 +366,4 @@ delete result.aud;

}
if (input.jti && Object.getOwnPropertyNames(input).indexOf('id') === -1) {
result.id = input.id || input.jti;
if (removeOriginalFields) {

@@ -460,25 +373,17 @@ delete result.jti;

}
const types = [...asArray(input.type), ...asArray((_input$vp2 = input.vp) == null ? void 0 : _input$vp2.type)].filter(notEmpty);
result.type = [...new Set(types)];
if (removeOriginalFields) {
var _result$vp2;
(_result$vp2 = result.vp) == null ? true : delete _result$vp2.type;
}
const contexts = [...asArray(input.context), ...asArray(input['@context']), ...asArray((_input$vp3 = input.vp) == null ? void 0 : _input$vp3['@context'])].filter(notEmpty);
result['@context'] = [...new Set(contexts)];
if (removeOriginalFields) {
var _result$vp3;
delete result.context;
(_result$vp3 = result.vp) == null ? true : delete _result$vp3['@context'];
}
if (!input.issuanceDate && (input.iat || input.nbf)) {
result.issuanceDate = new Date((input.nbf || input.iat) * 1000).toISOString();
if (removeOriginalFields) {

@@ -492,6 +397,4 @@ if (input.nbf) {

}
if (!input.expirationDate && input.exp) {
result.expirationDate = new Date(input.exp * 1000).toISOString();
if (removeOriginalFields) {

@@ -501,3 +404,2 @@ delete result.exp;

}
if (result.vp && Object.keys(result.vp).length === 0) {

@@ -508,9 +410,6 @@ if (removeOriginalFields) {

}
return result;
}
function normalizeJwtPresentation(input, removeOriginalFields = true) {
let decoded;
try {

@@ -521,3 +420,2 @@ decoded = decodeJWT(input);

}
return _extends({}, normalizeJwtPresentationPayload(decoded.payload, removeOriginalFields), {

@@ -534,7 +432,4 @@ proof: {

*/
function normalizePresentation(input, removeOriginalFields = true) {
var _input$proof2;
if (typeof input === 'string') {

@@ -545,3 +440,2 @@ if (JWT_FORMAT.test(input)) {

let parsed;
try {

@@ -552,3 +446,2 @@ parsed = JSON.parse(input);

}
return normalizePresentation(parsed, removeOriginalFields);

@@ -575,6 +468,4 @@ }

*/
function transformPresentationInput(input, removeOriginalFields = true) {
var _input$vp4, _input$vp5, _result$vp4;
const result = deepCopy(_extends({

@@ -586,3 +477,2 @@ vp: _extends({}, input.vp)

result.vp['@context'] = [...new Set(contextEntries)];
if (removeOriginalFields) {

@@ -592,13 +482,9 @@ delete result.context;

}
const types = [...asArray(input.type), ...asArray((_input$vp5 = input.vp) == null ? void 0 : _input$vp5.type)].filter(notEmpty);
result.vp.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.type;
}
if (input.id && Object.getOwnPropertyNames(input).indexOf('jti') === -1) {
result.jti = input.id;
if (removeOriginalFields) {

@@ -608,9 +494,6 @@ delete result.id;

}
if (input.issuanceDate && Object.getOwnPropertyNames(input).indexOf('nbf') === -1) {
const converted = Date.parse(input.issuanceDate);
if (!isNaN(converted)) {
result.nbf = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -621,9 +504,6 @@ delete result.issuanceDate;

}
if (input.expirationDate && Object.getOwnPropertyNames(input).indexOf('exp') === -1) {
const converted = Date.parse(input.expirationDate);
if (!isNaN(converted)) {
result.exp = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -634,9 +514,6 @@ delete result.expirationDate;

}
if (result.verifiableCredential || (_result$vp4 = result.vp) != null && _result$vp4.verifiableCredential) {
var _result$vp5;
result.vp.verifiableCredential = [...asArray(result.verifiableCredential), ...asArray((_result$vp5 = result.vp) == null ? void 0 : _result$vp5.verifiableCredential)].filter(notEmpty).map(credential => {
var _credential$proof;
if (typeof credential === 'object' && (_credential$proof = credential.proof) != null && _credential$proof.jwt) {

@@ -649,11 +526,8 @@ return credential.proof.jwt;

}
if (removeOriginalFields) {
delete result.verifiableCredential;
}
if (input.holder && Object.getOwnPropertyNames(input).indexOf('iss') === -1) {
if (typeof input.holder === 'string') {
result.iss = input.holder;
if (removeOriginalFields) {

@@ -664,7 +538,5 @@ delete result.holder;

}
if (input.verifier) {
const audience = [...asArray(input.verifier), ...asArray(input.aud)].filter(notEmpty);
result.aud = [...new Set(audience)];
if (removeOriginalFields) {

@@ -674,3 +546,2 @@ delete result.verifier;

}
return result;

@@ -683,3 +554,2 @@ }

*/
const VC_ERROR = {

@@ -691,3 +561,2 @@ /**

SCHEMA_ERROR: 'schema_error',
/**

@@ -697,3 +566,2 @@ * Thrown when the input is not a JWT string

FORMAT_ERROR: 'format_error',
/**

@@ -707,9 +575,7 @@ * Thrown when verifying a presentation where `challenge` and/or `domain` don't match the expected values.

*/
const VC_JWT_ERROR = _extends({}, VC_ERROR, JWT_ERROR); // eslint-disable-next-line @typescript-eslint/no-explicit-any
const VC_JWT_ERROR = _extends({}, VC_ERROR, JWT_ERROR);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isDateObject(input) {
return input && !isNaN(input) && Object.prototype.toString.call(input) === '[object Date]';
}
function validateJwtFormat(value) {

@@ -719,3 +585,4 @@ if (typeof value === 'string' && !value.match(JWT_FORMAT)) {

}
} // The main scenario we want to guard against is having a timestamp in milliseconds
}
// The main scenario we want to guard against is having a timestamp in milliseconds
// instead of seconds (ex: from new Date().getTime()).

@@ -727,3 +594,2 @@ // We will check the number of digits and assume that any number with 12 or more

// 12 digits max is 999999999999 -> 09/27/33658 @ 1:46am (UTC)
function validateTimestamp(value) {

@@ -742,3 +608,2 @@ if (typeof value === 'number') {

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_CONTEXT) === -1) {

@@ -750,3 +615,2 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: @context is missing default context "${DEFAULT_CONTEXT}"`);

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_VC_TYPE) === -1) {

@@ -758,3 +622,2 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: type is missing default "${DEFAULT_VC_TYPE}"`);

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_VP_TYPE) === -1) {

@@ -786,17 +649,31 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: type is missing default "${DEFAULT_VP_TYPE}"`);

*/
async function createVerifiableCredentialJwt(payload, issuer, options = {}) {
var _options$header;
const parsedPayload = _extends({
iat: undefined
}, transformCredentialInput(payload, options.removeOriginalFields));
validateJwtCredentialPayload(parsedPayload);
return createJWT(parsedPayload, _extends({}, options, {
issuer: issuer.did || parsedPayload.iss || '',
signer: issuer.signer
}), _extends({}, options.header, {
alg: issuer.alg || ((_options$header = options.header) == null ? void 0 : _options$header.alg) || JWT_ALG
}));
if (!Array.isArray(issuer)) {
var _options$header;
return createJWT(parsedPayload, _extends({}, options, {
issuer: issuer.did || parsedPayload.iss || '',
signer: issuer.signer
}), _extends({}, options.header, {
alg: issuer.alg || ((_options$header = options.header) == null ? void 0 : _options$header.alg) || JWT_ALG
}));
} else {
const did = issuer[0].did;
const issuers = [];
for (const iss of issuer) {
var _options$header2;
if (iss.did !== did) {
throw new Error('All issuers must be the same did to comply with the Verifiable Conditions spec');
}
issuers.push({
issuer: iss.did || parsedPayload.iss || '',
signer: iss.signer,
alg: iss.alg || ((_options$header2 = options.header) == null ? void 0 : _options$header2.alg) || JWT_ALG
});
}
return createMultisignatureJWT(parsedPayload, _extends({}, options), issuers);
}
}

@@ -820,16 +697,12 @@ /**

*/
async function createVerifiablePresentationJwt(payload, holder, options = {}) {
var _options$header2;
var _options$header3;
const parsedPayload = _extends({
iat: undefined
}, transformPresentationInput(payload, options == null ? void 0 : options.removeOriginalFields)); // add challenge to nonce
}, transformPresentationInput(payload, options == null ? void 0 : options.removeOriginalFields));
// add challenge to nonce
if (options.challenge && Object.getOwnPropertyNames(parsedPayload).indexOf('nonce') === -1) {
parsedPayload.nonce = options.challenge;
} // add domain to audience.
}
// add domain to audience.
if (options.domain) {

@@ -839,3 +712,2 @@ const audience = [...asArray(options.domain), ...asArray(parsedPayload.aud)].filter(notEmpty);

}
validateJwtPresentationPayload(parsedPayload);

@@ -846,3 +718,3 @@ return createJWT(parsedPayload, _extends({}, options, {

}), _extends({}, options.header, {
alg: holder.alg || ((_options$header2 = options.header) == null ? void 0 : _options$header2.alg) || JWT_ALG
alg: holder.alg || ((_options$header3 = options.header) == null ? void 0 : _options$header3.alg) || JWT_ALG
}));

@@ -866,4 +738,4 @@ }

validateContext(payload.vp['@context']);
validateVpType(payload.vp.type); // empty credential array is allowed
validateVpType(payload.vp.type);
// empty credential array is allowed
if (payload.vp.verifiableCredential && payload.vp.verifiableCredential.length >= 1) {

@@ -878,3 +750,2 @@ for (const vc of asArray(payload.vp.verifiableCredential)) {

}
if (payload.exp) validateTimestamp(payload.exp);

@@ -884,4 +755,4 @@ }

validateContext(payload['@context']);
validateVpType(payload.type); // empty credential array is allowed
validateVpType(payload.type);
// empty credential array is allowed
if (payload.verifiableCredential && payload.verifiableCredential.length >= 1) {

@@ -896,3 +767,2 @@ for (const vc of payload.verifiableCredential) {

}
if (payload.expirationDate) validateTimestamp(payload.expirationDate);

@@ -910,6 +780,4 @@ }

*/
async function verifyCredential(vc, resolver, options = {}) {
var _options, _options$policies, _options2, _options2$policies, _options3, _options4, _options5, _options5$policies;
const nbf = ((_options = options) == null ? void 0 : (_options$policies = _options.policies) == null ? void 0 : _options$policies.issuanceDate) === false ? false : undefined;

@@ -928,7 +796,5 @@ const exp = ((_options2 = options) == null ? void 0 : (_options2$policies = _options2.policies) == null ? void 0 : _options2$policies.expirationDate) === false ? false : undefined;

verified.verifiableCredential = normalizeCredential(verified.jwt, (_options4 = options) == null ? void 0 : _options4.removeOriginalFields);
if (((_options5 = options) == null ? void 0 : (_options5$policies = _options5.policies) == null ? void 0 : _options5$policies.format) !== false) {
validateCredentialPayload(verified.verifiableCredential);
}
return verified;

@@ -943,3 +809,2 @@ }

*/
function verifyPresentationPayloadOptions(payload, options) {

@@ -949,7 +814,5 @@ if (options.challenge && options.challenge !== payload.nonce) {

}
if (options.domain) {
// aud might be an array
let matchedAudience;
if (payload.aud) {

@@ -959,3 +822,2 @@ const audArray = Array.isArray(payload.aud) ? payload.aud : [payload.aud];

}
if (typeof matchedAudience === 'undefined') {

@@ -976,6 +838,4 @@ throw new Error(`${VC_ERROR.AUTH_ERROR}: Presentation does not contain the mandatory domain (JWT: aud) for : ${options.domain}`);

*/
async function verifyPresentation(presentation, resolver, options = {}) {
var _options6, _options6$policies, _options7, _options7$policies, _options8, _options9, _options10, _options10$policies;
const nbf = ((_options6 = options) == null ? void 0 : (_options6$policies = _options6.policies) == null ? void 0 : _options6$policies.issuanceDate) === false ? false : undefined;

@@ -997,7 +857,5 @@ const exp = ((_options7 = options) == null ? void 0 : (_options7$policies = _options7.policies) == null ? void 0 : _options7$policies.expirationDate) === false ? false : undefined;

verified.verifiablePresentation = normalizePresentation(verified.jwt, (_options9 = options) == null ? void 0 : _options9.removeOriginalFields);
if (((_options10 = options) == null ? void 0 : (_options10$policies = _options10.policies) == null ? void 0 : _options10$policies.format) !== false) {
validatePresentationPayload(verified.verifiablePresentation);
}
return verified;

@@ -1004,0 +862,0 @@ }

@@ -1,2 +0,2 @@

import { decodeJWT, JWT_ERROR, verifyJWT, createJWT } from 'did-jwt';
import { decodeJWT, JWT_ERROR, verifyJWT, createJWT, createMultisignatureJWT } from 'did-jwt';

@@ -16,9 +16,7 @@ const JWT_ALG = 'ES256K';

*/
const additionalPropNames = ['evidence', 'termsOfUse', 'refreshService', 'credentialSchema', 'credentialStatus']; // eslint-disable-next-line @typescript-eslint/no-explicit-any
const additionalPropNames = ['evidence', 'termsOfUse', 'refreshService', 'credentialSchema', 'credentialStatus'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function asArray(arg) {
return Array.isArray(arg) ? arg : [arg];
}
function deepCopy(source) {

@@ -31,7 +29,5 @@ return Array.isArray(source) ? source.map(item => deepCopy(item)) : source instanceof Date ? new Date(source.getTime()) : source && typeof source === 'object' ? Object.getOwnPropertyNames(source).reduce((o, prop) => {

}
function notEmpty(value) {
return value !== null && value !== undefined;
}
function cleanUndefined(input) {

@@ -41,15 +37,14 @@ if (typeof input !== 'object') {

}
const obj = { ...input
const obj = {
...input
};
Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key]);
return obj;
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isLegacyAttestationFormat(payload) {
// payload is an object and has all the required fields of old attestation format
return typeof payload === 'object' && payload.sub && payload.iss && payload.claim && payload.iat;
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function attestationToVcFormat(payload) {

@@ -63,3 +58,4 @@ const {

} = payload;
const result = { ...rest,
const result = {
...rest,
nbf: nbf ? nbf : iat,

@@ -75,18 +71,14 @@ vc: {

}
function normalizeJwtCredentialPayload(input, removeOriginalFields = true) {
let result = deepCopy(input);
if (isLegacyAttestationFormat(input)) {
result = attestationToVcFormat(input);
} // FIXME: handle case when credentialSubject(s) are not object types
result.credentialSubject = { ...input.credentialSubject,
}
// FIXME: handle case when credentialSubject(s) are not object types
result.credentialSubject = {
...input.credentialSubject,
...input.vc?.credentialSubject
};
if (input.sub && !input.credentialSubject?.id && result.credentialSubject) {
result.credentialSubject.id = input.sub;
if (removeOriginalFields) {

@@ -96,7 +88,5 @@ delete result.sub;

}
if (removeOriginalFields) {
delete result.vc?.credentialSubject;
}
if (typeof input.issuer === 'undefined' || typeof input.issuer === 'object') {

@@ -107,3 +97,2 @@ result.issuer = cleanUndefined({

});
if (removeOriginalFields && !input.issuer?.id) {

@@ -113,6 +102,4 @@ delete result.iss;

}
if (!input.id && input.jti) {
result.id = result.id || result.jti;
if (removeOriginalFields) {

@@ -122,10 +109,7 @@ delete result.jti;

}
const types = [...asArray(result.type), ...asArray(result.vc?.type)].filter(notEmpty);
result.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.vc?.type;
}
for (const prop of additionalPropNames) {

@@ -136,3 +120,2 @@ if (input.vc && input.vc[prop]) {

}
if (removeOriginalFields) {

@@ -143,6 +126,4 @@ delete result.vc[prop];

}
const contextArray = [...asArray(input.context), ...asArray(input['@context']), ...asArray(input.vc?.['@context'])].filter(notEmpty);
result['@context'] = [...new Set(contextArray)];
if (removeOriginalFields) {

@@ -152,6 +133,4 @@ delete result.context;

}
if (!input.issuanceDate && (input.iat || input.nbf)) {
result.issuanceDate = new Date((input.nbf || input.iat) * 1000).toISOString();
if (removeOriginalFields) {

@@ -165,6 +144,4 @@ if (input.nbf) {

}
if (!input.expirationDate && input.exp) {
result.expirationDate = new Date(input.exp * 1000).toISOString();
if (removeOriginalFields) {

@@ -174,3 +151,2 @@ delete result.exp;

}
if (removeOriginalFields) {

@@ -180,11 +156,8 @@ if (result.vc && Object.keys(result.vc).length === 0) {

}
} // FIXME: interpret `aud` property as `verifier`
}
// FIXME: interpret `aud` property as `verifier`
return result;
}
function normalizeJwtCredential(input, removeOriginalFields = true) {
let decoded;
try {

@@ -195,4 +168,4 @@ decoded = decodeJWT(input);

}
return { ...normalizeJwtCredentialPayload(decoded.payload, removeOriginalFields),
return {
...normalizeJwtCredentialPayload(decoded.payload, removeOriginalFields),
proof: {

@@ -210,4 +183,2 @@ type: DEFAULT_JWT_PROOF_TYPE,

*/
function normalizeCredential(input, removeOriginalFields = true) {

@@ -219,3 +190,2 @@ if (typeof input === 'string') {

let parsed;
try {

@@ -226,3 +196,2 @@ parsed = JSON.parse(input);

}
return normalizeCredential(parsed, removeOriginalFields);

@@ -232,3 +201,4 @@ }

// TODO: test that it correctly propagates app specific proof properties
return deepCopy({ ...normalizeJwtCredential(input.proof.jwt, removeOriginalFields),
return deepCopy({
...normalizeJwtCredential(input.proof.jwt, removeOriginalFields),
proof: input.proof

@@ -251,7 +221,7 @@ });

*/
function transformCredentialInput(input, removeOriginalFields = true) {
if (Array.isArray(input.credentialSubject)) throw Error('credentialSubject of type array not supported');
const result = deepCopy({
vc: { ...input.vc
vc: {
...input.vc
},

@@ -261,9 +231,8 @@ ...input

result.vc = result.vc;
const credentialSubject = { ...input.credentialSubject,
const credentialSubject = {
...input.credentialSubject,
...input.vc?.credentialSubject
};
if (!input.sub) {
result.sub = input.credentialSubject?.id;
if (removeOriginalFields) {

@@ -273,6 +242,4 @@ delete credentialSubject.id;

}
const contextEntries = [...asArray(input.context), ...asArray(input['@context']), ...asArray(input.vc?.['@context'])].filter(notEmpty);
result.vc['@context'] = [...new Set(contextEntries)];
if (removeOriginalFields) {

@@ -282,13 +249,9 @@ delete result.context;

}
const types = [...asArray(input.type), ...asArray(input.vc?.type)].filter(notEmpty);
result.vc.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.type;
}
if (input.id && Object.getOwnPropertyNames(input).indexOf('jti') === -1) {
result.jti = input.id;
if (removeOriginalFields) {

@@ -298,9 +261,6 @@ delete result.id;

}
if (input.issuanceDate && Object.getOwnPropertyNames(input).indexOf('nbf') === -1) {
const converted = Date.parse(input.issuanceDate);
if (!isNaN(converted)) {
result.nbf = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -311,9 +271,6 @@ delete result.issuanceDate;

}
if (input.expirationDate && Object.getOwnPropertyNames(input).indexOf('exp') === -1) {
const converted = Date.parse(input.expirationDate);
if (!isNaN(converted)) {
result.exp = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -324,10 +281,7 @@ delete result.expirationDate;

}
if (input.issuer && Object.getOwnPropertyNames(input).indexOf('iss') === -1) {
if (typeof input.issuer === 'object') {
result.iss = input.issuer?.id;
if (removeOriginalFields) {
delete result.issuer.id;
if (Object.keys(result.issuer).length === 0) {

@@ -339,3 +293,2 @@ delete result.issuer;

result.iss = input.iss || '' + input.issuer;
if (removeOriginalFields) {

@@ -346,9 +299,6 @@ delete result.issuer;

}
result.vc.credentialSubject = credentialSubject;
if (removeOriginalFields) {
delete result.credentialSubject;
}
for (const prop of additionalPropNames) {

@@ -359,3 +309,2 @@ if (input[prop]) {

}
if (removeOriginalFields) {

@@ -366,6 +315,4 @@ delete result[prop];

}
return result;
}
function normalizeJwtPresentationPayload(input, removeOriginalFields = true) {

@@ -377,10 +324,7 @@ const result = deepCopy(input);

});
if (removeOriginalFields) {
delete result.vp?.verifiableCredential;
}
if (input.iss && !input.holder) {
result.holder = input.iss;
if (removeOriginalFields) {

@@ -390,7 +334,5 @@ delete result.iss;

}
if (input.aud) {
result.verifier = [...asArray(input.verifier), ...asArray(input.aud)].filter(notEmpty);
result.verifier = [...new Set(result.verifier)];
if (removeOriginalFields) {

@@ -400,6 +342,4 @@ delete result.aud;

}
if (input.jti && Object.getOwnPropertyNames(input).indexOf('id') === -1) {
result.id = input.id || input.jti;
if (removeOriginalFields) {

@@ -409,13 +349,9 @@ delete result.jti;

}
const types = [...asArray(input.type), ...asArray(input.vp?.type)].filter(notEmpty);
result.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.vp?.type;
}
const contexts = [...asArray(input.context), ...asArray(input['@context']), ...asArray(input.vp?.['@context'])].filter(notEmpty);
result['@context'] = [...new Set(contexts)];
if (removeOriginalFields) {

@@ -425,6 +361,4 @@ delete result.context;

}
if (!input.issuanceDate && (input.iat || input.nbf)) {
result.issuanceDate = new Date((input.nbf || input.iat) * 1000).toISOString();
if (removeOriginalFields) {

@@ -438,6 +372,4 @@ if (input.nbf) {

}
if (!input.expirationDate && input.exp) {
result.expirationDate = new Date(input.exp * 1000).toISOString();
if (removeOriginalFields) {

@@ -447,3 +379,2 @@ delete result.exp;

}
if (result.vp && Object.keys(result.vp).length === 0) {

@@ -454,9 +385,6 @@ if (removeOriginalFields) {

}
return result;
}
function normalizeJwtPresentation(input, removeOriginalFields = true) {
let decoded;
try {

@@ -467,4 +395,4 @@ decoded = decodeJWT(input);

}
return { ...normalizeJwtPresentationPayload(decoded.payload, removeOriginalFields),
return {
...normalizeJwtPresentationPayload(decoded.payload, removeOriginalFields),
proof: {

@@ -480,4 +408,2 @@ type: DEFAULT_JWT_PROOF_TYPE,

*/
function normalizePresentation(input, removeOriginalFields = true) {

@@ -489,3 +415,2 @@ if (typeof input === 'string') {

let parsed;
try {

@@ -496,3 +421,2 @@ parsed = JSON.parse(input);

}
return normalizePresentation(parsed, removeOriginalFields);

@@ -502,3 +426,4 @@ }

// TODO: test that it correctly propagates app specific proof properties
return { ...normalizeJwtPresentation(input.proof.jwt, removeOriginalFields),
return {
...normalizeJwtPresentation(input.proof.jwt, removeOriginalFields),
proof: input.proof

@@ -521,6 +446,6 @@ };

*/
function transformPresentationInput(input, removeOriginalFields = true) {
const result = deepCopy({
vp: { ...input.vp
vp: {
...input.vp
},

@@ -532,3 +457,2 @@ ...input

result.vp['@context'] = [...new Set(contextEntries)];
if (removeOriginalFields) {

@@ -538,13 +462,9 @@ delete result.context;

}
const types = [...asArray(input.type), ...asArray(input.vp?.type)].filter(notEmpty);
result.vp.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.type;
}
if (input.id && Object.getOwnPropertyNames(input).indexOf('jti') === -1) {
result.jti = input.id;
if (removeOriginalFields) {

@@ -554,9 +474,6 @@ delete result.id;

}
if (input.issuanceDate && Object.getOwnPropertyNames(input).indexOf('nbf') === -1) {
const converted = Date.parse(input.issuanceDate);
if (!isNaN(converted)) {
result.nbf = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -567,9 +484,6 @@ delete result.issuanceDate;

}
if (input.expirationDate && Object.getOwnPropertyNames(input).indexOf('exp') === -1) {
const converted = Date.parse(input.expirationDate);
if (!isNaN(converted)) {
result.exp = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -580,3 +494,2 @@ delete result.expirationDate;

}
if (result.verifiableCredential || result.vp?.verifiableCredential) {

@@ -591,11 +504,8 @@ result.vp.verifiableCredential = [...asArray(result.verifiableCredential), ...asArray(result.vp?.verifiableCredential)].filter(notEmpty).map(credential => {

}
if (removeOriginalFields) {
delete result.verifiableCredential;
}
if (input.holder && Object.getOwnPropertyNames(input).indexOf('iss') === -1) {
if (typeof input.holder === 'string') {
result.iss = input.holder;
if (removeOriginalFields) {

@@ -606,7 +516,5 @@ delete result.holder;

}
if (input.verifier) {
const audience = [...asArray(input.verifier), ...asArray(input.aud)].filter(notEmpty);
result.aud = [...new Set(audience)];
if (removeOriginalFields) {

@@ -616,3 +524,2 @@ delete result.verifier;

}
return result;

@@ -625,3 +532,2 @@ }

*/
const VC_ERROR = {

@@ -633,3 +539,2 @@ /**

SCHEMA_ERROR: 'schema_error',
/**

@@ -639,3 +544,2 @@ * Thrown when the input is not a JWT string

FORMAT_ERROR: 'format_error',
/**

@@ -649,11 +553,10 @@ * Thrown when verifying a presentation where `challenge` and/or `domain` don't match the expected values.

*/
const VC_JWT_ERROR = { ...VC_ERROR,
const VC_JWT_ERROR = {
...VC_ERROR,
...JWT_ERROR
}; // eslint-disable-next-line @typescript-eslint/no-explicit-any
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isDateObject(input) {
return input && !isNaN(input) && Object.prototype.toString.call(input) === '[object Date]';
}
function validateJwtFormat(value) {

@@ -663,3 +566,4 @@ if (typeof value === 'string' && !value.match(JWT_FORMAT)) {

}
} // The main scenario we want to guard against is having a timestamp in milliseconds
}
// The main scenario we want to guard against is having a timestamp in milliseconds
// instead of seconds (ex: from new Date().getTime()).

@@ -671,3 +575,2 @@ // We will check the number of digits and assume that any number with 12 or more

// 12 digits max is 999999999999 -> 09/27/33658 @ 1:46am (UTC)
function validateTimestamp(value) {

@@ -686,3 +589,2 @@ if (typeof value === 'number') {

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_CONTEXT) === -1) {

@@ -694,3 +596,2 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: @context is missing default context "${DEFAULT_CONTEXT}"`);

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_VC_TYPE) === -1) {

@@ -702,3 +603,2 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: type is missing default "${DEFAULT_VC_TYPE}"`);

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_VP_TYPE) === -1) {

@@ -731,3 +631,4 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: type is missing default "${DEFAULT_VP_TYPE}"`);

...options,
policies: { ...options?.policies,
policies: {
...options?.policies,
nbf,

@@ -744,7 +645,5 @@ exp,

verified.verifiablePresentation = normalizePresentation(verified.jwt, options?.removeOriginalFields);
if (options?.policies?.format !== false) {
validatePresentationPayload(verified.verifiablePresentation);
}
return verified;

@@ -756,3 +655,2 @@ });

};
/**

@@ -772,4 +670,6 @@ * Verifies and validates a VerifiableCredential that is encoded as a JWT according to the W3C spec.

const exp = options?.policies?.expirationDate === false ? false : undefined;
options = { ...options,
policies: { ...options?.policies,
options = {
...options,
policies: {
...options?.policies,
nbf,

@@ -785,7 +685,5 @@ exp,

verified.verifiableCredential = normalizeCredential(verified.jwt, options?.removeOriginalFields);
if (options?.policies?.format !== false) {
validateCredentialPayload(verified.verifiableCredential);
}
return verified;

@@ -804,3 +702,2 @@ });

*/
/**

@@ -828,9 +725,8 @@ * Creates a VerifiablePresentation JWT given a `PresentationPayload` or `JwtPresentationPayload` and an `Issuer`.

...transformPresentationInput(payload, options?.removeOriginalFields)
}; // add challenge to nonce
};
// add challenge to nonce
if (options.challenge && Object.getOwnPropertyNames(parsedPayload).indexOf('nonce') === -1) {
parsedPayload.nonce = options.challenge;
} // add domain to audience.
}
// add domain to audience.
if (options.domain) {

@@ -840,8 +736,9 @@ const audience = [...asArray(options.domain), ...asArray(parsedPayload.aud)].filter(notEmpty);

}
validateJwtPresentationPayload(parsedPayload);
return Promise.resolve(createJWT(parsedPayload, { ...options,
return Promise.resolve(createJWT(parsedPayload, {
...options,
issuer: holder.did || parsedPayload.iss || '',
signer: holder.signer
}, { ...options.header,
}, {
...options.header,
alg: holder.alg || options.header?.alg || JWT_ALG

@@ -853,3 +750,2 @@ }));

};
/**

@@ -878,8 +774,28 @@ * Creates a VerifiableCredential given a `CredentialPayload` or `JwtCredentialPayload` and an `Issuer`.

validateJwtCredentialPayload(parsedPayload);
return Promise.resolve(createJWT(parsedPayload, { ...options,
issuer: issuer.did || parsedPayload.iss || '',
signer: issuer.signer
}, { ...options.header,
alg: issuer.alg || options.header?.alg || JWT_ALG
}));
if (!Array.isArray(issuer)) {
return Promise.resolve(createJWT(parsedPayload, {
...options,
issuer: issuer.did || parsedPayload.iss || '',
signer: issuer.signer
}, {
...options.header,
alg: issuer.alg || options.header?.alg || JWT_ALG
}));
} else {
const did = issuer[0].did;
const issuers = [];
for (const iss of issuer) {
if (iss.did !== did) {
throw new Error('All issuers must be the same did to comply with the Verifiable Conditions spec');
}
issuers.push({
issuer: iss.did || parsedPayload.iss || '',
signer: iss.signer,
alg: iss.alg || options.header?.alg || JWT_ALG
});
}
return Promise.resolve(createMultisignatureJWT(parsedPayload, {
...options
}, issuers));
}
} catch (e) {

@@ -905,4 +821,4 @@ return Promise.reject(e);

validateContext(payload.vp['@context']);
validateVpType(payload.vp.type); // empty credential array is allowed
validateVpType(payload.vp.type);
// empty credential array is allowed
if (payload.vp.verifiableCredential && payload.vp.verifiableCredential.length >= 1) {

@@ -917,3 +833,2 @@ for (const vc of asArray(payload.vp.verifiableCredential)) {

}
if (payload.exp) validateTimestamp(payload.exp);

@@ -923,4 +838,4 @@ }

validateContext(payload['@context']);
validateVpType(payload.type); // empty credential array is allowed
validateVpType(payload.type);
// empty credential array is allowed
if (payload.verifiableCredential && payload.verifiableCredential.length >= 1) {

@@ -935,3 +850,2 @@ for (const vc of payload.verifiableCredential) {

}
if (payload.expirationDate) validateTimestamp(payload.expirationDate);

@@ -943,7 +857,5 @@ }

}
if (options.domain) {
// aud might be an array
let matchedAudience;
if (payload.aud) {

@@ -953,3 +865,2 @@ const audArray = Array.isArray(payload.aud) ? payload.aud : [payload.aud];

}
if (typeof matchedAudience === 'undefined') {

@@ -956,0 +867,0 @@ throw new Error(`${VC_ERROR.AUTH_ERROR}: Presentation does not contain the mandatory domain (JWT: aud) for : ${options.domain}`);

@@ -19,9 +19,7 @@ (function (global, factory) {

*/
const additionalPropNames = ['evidence', 'termsOfUse', 'refreshService', 'credentialSchema', 'credentialStatus']; // eslint-disable-next-line @typescript-eslint/no-explicit-any
const additionalPropNames = ['evidence', 'termsOfUse', 'refreshService', 'credentialSchema', 'credentialStatus'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function asArray(arg) {
return Array.isArray(arg) ? arg : [arg];
}
function deepCopy(source) {

@@ -34,7 +32,5 @@ return Array.isArray(source) ? source.map(item => deepCopy(item)) : source instanceof Date ? new Date(source.getTime()) : source && typeof source === 'object' ? Object.getOwnPropertyNames(source).reduce((o, prop) => {

}
function notEmpty(value) {
return value !== null && value !== undefined;
}
function cleanUndefined(input) {

@@ -44,15 +40,14 @@ if (typeof input !== 'object') {

}
const obj = { ...input
const obj = {
...input
};
Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key]);
return obj;
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isLegacyAttestationFormat(payload) {
// payload is an object and has all the required fields of old attestation format
return typeof payload === 'object' && payload.sub && payload.iss && payload.claim && payload.iat;
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function attestationToVcFormat(payload) {

@@ -66,3 +61,4 @@ const {

} = payload;
const result = { ...rest,
const result = {
...rest,
nbf: nbf ? nbf : iat,

@@ -78,18 +74,14 @@ vc: {

}
function normalizeJwtCredentialPayload(input, removeOriginalFields = true) {
let result = deepCopy(input);
if (isLegacyAttestationFormat(input)) {
result = attestationToVcFormat(input);
} // FIXME: handle case when credentialSubject(s) are not object types
result.credentialSubject = { ...input.credentialSubject,
}
// FIXME: handle case when credentialSubject(s) are not object types
result.credentialSubject = {
...input.credentialSubject,
...input.vc?.credentialSubject
};
if (input.sub && !input.credentialSubject?.id && result.credentialSubject) {
result.credentialSubject.id = input.sub;
if (removeOriginalFields) {

@@ -99,7 +91,5 @@ delete result.sub;

}
if (removeOriginalFields) {
delete result.vc?.credentialSubject;
}
if (typeof input.issuer === 'undefined' || typeof input.issuer === 'object') {

@@ -110,3 +100,2 @@ result.issuer = cleanUndefined({

});
if (removeOriginalFields && !input.issuer?.id) {

@@ -116,6 +105,4 @@ delete result.iss;

}
if (!input.id && input.jti) {
result.id = result.id || result.jti;
if (removeOriginalFields) {

@@ -125,10 +112,7 @@ delete result.jti;

}
const types = [...asArray(result.type), ...asArray(result.vc?.type)].filter(notEmpty);
result.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.vc?.type;
}
for (const prop of additionalPropNames) {

@@ -139,3 +123,2 @@ if (input.vc && input.vc[prop]) {

}
if (removeOriginalFields) {

@@ -146,6 +129,4 @@ delete result.vc[prop];

}
const contextArray = [...asArray(input.context), ...asArray(input['@context']), ...asArray(input.vc?.['@context'])].filter(notEmpty);
result['@context'] = [...new Set(contextArray)];
if (removeOriginalFields) {

@@ -155,6 +136,4 @@ delete result.context;

}
if (!input.issuanceDate && (input.iat || input.nbf)) {
result.issuanceDate = new Date((input.nbf || input.iat) * 1000).toISOString();
if (removeOriginalFields) {

@@ -168,6 +147,4 @@ if (input.nbf) {

}
if (!input.expirationDate && input.exp) {
result.expirationDate = new Date(input.exp * 1000).toISOString();
if (removeOriginalFields) {

@@ -177,3 +154,2 @@ delete result.exp;

}
if (removeOriginalFields) {

@@ -183,11 +159,8 @@ if (result.vc && Object.keys(result.vc).length === 0) {

}
} // FIXME: interpret `aud` property as `verifier`
}
// FIXME: interpret `aud` property as `verifier`
return result;
}
function normalizeJwtCredential(input, removeOriginalFields = true) {
let decoded;
try {

@@ -198,4 +171,4 @@ decoded = didJwt.decodeJWT(input);

}
return { ...normalizeJwtCredentialPayload(decoded.payload, removeOriginalFields),
return {
...normalizeJwtCredentialPayload(decoded.payload, removeOriginalFields),
proof: {

@@ -213,4 +186,2 @@ type: DEFAULT_JWT_PROOF_TYPE,

*/
function normalizeCredential(input, removeOriginalFields = true) {

@@ -222,3 +193,2 @@ if (typeof input === 'string') {

let parsed;
try {

@@ -229,3 +199,2 @@ parsed = JSON.parse(input);

}
return normalizeCredential(parsed, removeOriginalFields);

@@ -235,3 +204,4 @@ }

// TODO: test that it correctly propagates app specific proof properties
return deepCopy({ ...normalizeJwtCredential(input.proof.jwt, removeOriginalFields),
return deepCopy({
...normalizeJwtCredential(input.proof.jwt, removeOriginalFields),
proof: input.proof

@@ -254,7 +224,7 @@ });

*/
function transformCredentialInput(input, removeOriginalFields = true) {
if (Array.isArray(input.credentialSubject)) throw Error('credentialSubject of type array not supported');
const result = deepCopy({
vc: { ...input.vc
vc: {
...input.vc
},

@@ -264,9 +234,8 @@ ...input

result.vc = result.vc;
const credentialSubject = { ...input.credentialSubject,
const credentialSubject = {
...input.credentialSubject,
...input.vc?.credentialSubject
};
if (!input.sub) {
result.sub = input.credentialSubject?.id;
if (removeOriginalFields) {

@@ -276,6 +245,4 @@ delete credentialSubject.id;

}
const contextEntries = [...asArray(input.context), ...asArray(input['@context']), ...asArray(input.vc?.['@context'])].filter(notEmpty);
result.vc['@context'] = [...new Set(contextEntries)];
if (removeOriginalFields) {

@@ -285,13 +252,9 @@ delete result.context;

}
const types = [...asArray(input.type), ...asArray(input.vc?.type)].filter(notEmpty);
result.vc.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.type;
}
if (input.id && Object.getOwnPropertyNames(input).indexOf('jti') === -1) {
result.jti = input.id;
if (removeOriginalFields) {

@@ -301,9 +264,6 @@ delete result.id;

}
if (input.issuanceDate && Object.getOwnPropertyNames(input).indexOf('nbf') === -1) {
const converted = Date.parse(input.issuanceDate);
if (!isNaN(converted)) {
result.nbf = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -314,9 +274,6 @@ delete result.issuanceDate;

}
if (input.expirationDate && Object.getOwnPropertyNames(input).indexOf('exp') === -1) {
const converted = Date.parse(input.expirationDate);
if (!isNaN(converted)) {
result.exp = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -327,10 +284,7 @@ delete result.expirationDate;

}
if (input.issuer && Object.getOwnPropertyNames(input).indexOf('iss') === -1) {
if (typeof input.issuer === 'object') {
result.iss = input.issuer?.id;
if (removeOriginalFields) {
delete result.issuer.id;
if (Object.keys(result.issuer).length === 0) {

@@ -342,3 +296,2 @@ delete result.issuer;

result.iss = input.iss || '' + input.issuer;
if (removeOriginalFields) {

@@ -349,9 +302,6 @@ delete result.issuer;

}
result.vc.credentialSubject = credentialSubject;
if (removeOriginalFields) {
delete result.credentialSubject;
}
for (const prop of additionalPropNames) {

@@ -362,3 +312,2 @@ if (input[prop]) {

}
if (removeOriginalFields) {

@@ -369,6 +318,4 @@ delete result[prop];

}
return result;
}
function normalizeJwtPresentationPayload(input, removeOriginalFields = true) {

@@ -380,10 +327,7 @@ const result = deepCopy(input);

});
if (removeOriginalFields) {
delete result.vp?.verifiableCredential;
}
if (input.iss && !input.holder) {
result.holder = input.iss;
if (removeOriginalFields) {

@@ -393,7 +337,5 @@ delete result.iss;

}
if (input.aud) {
result.verifier = [...asArray(input.verifier), ...asArray(input.aud)].filter(notEmpty);
result.verifier = [...new Set(result.verifier)];
if (removeOriginalFields) {

@@ -403,6 +345,4 @@ delete result.aud;

}
if (input.jti && Object.getOwnPropertyNames(input).indexOf('id') === -1) {
result.id = input.id || input.jti;
if (removeOriginalFields) {

@@ -412,13 +352,9 @@ delete result.jti;

}
const types = [...asArray(input.type), ...asArray(input.vp?.type)].filter(notEmpty);
result.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.vp?.type;
}
const contexts = [...asArray(input.context), ...asArray(input['@context']), ...asArray(input.vp?.['@context'])].filter(notEmpty);
result['@context'] = [...new Set(contexts)];
if (removeOriginalFields) {

@@ -428,6 +364,4 @@ delete result.context;

}
if (!input.issuanceDate && (input.iat || input.nbf)) {
result.issuanceDate = new Date((input.nbf || input.iat) * 1000).toISOString();
if (removeOriginalFields) {

@@ -441,6 +375,4 @@ if (input.nbf) {

}
if (!input.expirationDate && input.exp) {
result.expirationDate = new Date(input.exp * 1000).toISOString();
if (removeOriginalFields) {

@@ -450,3 +382,2 @@ delete result.exp;

}
if (result.vp && Object.keys(result.vp).length === 0) {

@@ -457,9 +388,6 @@ if (removeOriginalFields) {

}
return result;
}
function normalizeJwtPresentation(input, removeOriginalFields = true) {
let decoded;
try {

@@ -470,4 +398,4 @@ decoded = didJwt.decodeJWT(input);

}
return { ...normalizeJwtPresentationPayload(decoded.payload, removeOriginalFields),
return {
...normalizeJwtPresentationPayload(decoded.payload, removeOriginalFields),
proof: {

@@ -483,4 +411,2 @@ type: DEFAULT_JWT_PROOF_TYPE,

*/
function normalizePresentation(input, removeOriginalFields = true) {

@@ -492,3 +418,2 @@ if (typeof input === 'string') {

let parsed;
try {

@@ -499,3 +424,2 @@ parsed = JSON.parse(input);

}
return normalizePresentation(parsed, removeOriginalFields);

@@ -505,3 +429,4 @@ }

// TODO: test that it correctly propagates app specific proof properties
return { ...normalizeJwtPresentation(input.proof.jwt, removeOriginalFields),
return {
...normalizeJwtPresentation(input.proof.jwt, removeOriginalFields),
proof: input.proof

@@ -524,6 +449,6 @@ };

*/
function transformPresentationInput(input, removeOriginalFields = true) {
const result = deepCopy({
vp: { ...input.vp
vp: {
...input.vp
},

@@ -535,3 +460,2 @@ ...input

result.vp['@context'] = [...new Set(contextEntries)];
if (removeOriginalFields) {

@@ -541,13 +465,9 @@ delete result.context;

}
const types = [...asArray(input.type), ...asArray(input.vp?.type)].filter(notEmpty);
result.vp.type = [...new Set(types)];
if (removeOriginalFields) {
delete result.type;
}
if (input.id && Object.getOwnPropertyNames(input).indexOf('jti') === -1) {
result.jti = input.id;
if (removeOriginalFields) {

@@ -557,9 +477,6 @@ delete result.id;

}
if (input.issuanceDate && Object.getOwnPropertyNames(input).indexOf('nbf') === -1) {
const converted = Date.parse(input.issuanceDate);
if (!isNaN(converted)) {
result.nbf = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -570,9 +487,6 @@ delete result.issuanceDate;

}
if (input.expirationDate && Object.getOwnPropertyNames(input).indexOf('exp') === -1) {
const converted = Date.parse(input.expirationDate);
if (!isNaN(converted)) {
result.exp = Math.floor(converted / 1000);
if (removeOriginalFields) {

@@ -583,3 +497,2 @@ delete result.expirationDate;

}
if (result.verifiableCredential || result.vp?.verifiableCredential) {

@@ -594,11 +507,8 @@ result.vp.verifiableCredential = [...asArray(result.verifiableCredential), ...asArray(result.vp?.verifiableCredential)].filter(notEmpty).map(credential => {

}
if (removeOriginalFields) {
delete result.verifiableCredential;
}
if (input.holder && Object.getOwnPropertyNames(input).indexOf('iss') === -1) {
if (typeof input.holder === 'string') {
result.iss = input.holder;
if (removeOriginalFields) {

@@ -609,7 +519,5 @@ delete result.holder;

}
if (input.verifier) {
const audience = [...asArray(input.verifier), ...asArray(input.aud)].filter(notEmpty);
result.aud = [...new Set(audience)];
if (removeOriginalFields) {

@@ -619,3 +527,2 @@ delete result.verifier;

}
return result;

@@ -628,3 +535,2 @@ }

*/
const VC_ERROR = {

@@ -636,3 +542,2 @@ /**

SCHEMA_ERROR: 'schema_error',
/**

@@ -642,3 +547,2 @@ * Thrown when the input is not a JWT string

FORMAT_ERROR: 'format_error',
/**

@@ -652,11 +556,10 @@ * Thrown when verifying a presentation where `challenge` and/or `domain` don't match the expected values.

*/
const VC_JWT_ERROR = { ...VC_ERROR,
const VC_JWT_ERROR = {
...VC_ERROR,
...didJwt.JWT_ERROR
}; // eslint-disable-next-line @typescript-eslint/no-explicit-any
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isDateObject(input) {
return input && !isNaN(input) && Object.prototype.toString.call(input) === '[object Date]';
}
function validateJwtFormat(value) {

@@ -666,3 +569,4 @@ if (typeof value === 'string' && !value.match(JWT_FORMAT)) {

}
} // The main scenario we want to guard against is having a timestamp in milliseconds
}
// The main scenario we want to guard against is having a timestamp in milliseconds
// instead of seconds (ex: from new Date().getTime()).

@@ -674,3 +578,2 @@ // We will check the number of digits and assume that any number with 12 or more

// 12 digits max is 999999999999 -> 09/27/33658 @ 1:46am (UTC)
function validateTimestamp(value) {

@@ -689,3 +592,2 @@ if (typeof value === 'number') {

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_CONTEXT) === -1) {

@@ -697,3 +599,2 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: @context is missing default context "${DEFAULT_CONTEXT}"`);

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_VC_TYPE) === -1) {

@@ -705,3 +606,2 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: type is missing default "${DEFAULT_VC_TYPE}"`);

const input = asArray(value);
if (input.length < 1 || input.indexOf(DEFAULT_VP_TYPE) === -1) {

@@ -734,3 +634,4 @@ throw new TypeError(`${VC_ERROR.SCHEMA_ERROR}: type is missing default "${DEFAULT_VP_TYPE}"`);

...options,
policies: { ...options?.policies,
policies: {
...options?.policies,
nbf,

@@ -747,7 +648,5 @@ exp,

verified.verifiablePresentation = normalizePresentation(verified.jwt, options?.removeOriginalFields);
if (options?.policies?.format !== false) {
validatePresentationPayload(verified.verifiablePresentation);
}
return verified;

@@ -759,3 +658,2 @@ });

};
/**

@@ -775,4 +673,6 @@ * Verifies and validates a VerifiableCredential that is encoded as a JWT according to the W3C spec.

const exp = options?.policies?.expirationDate === false ? false : undefined;
options = { ...options,
policies: { ...options?.policies,
options = {
...options,
policies: {
...options?.policies,
nbf,

@@ -788,7 +688,5 @@ exp,

verified.verifiableCredential = normalizeCredential(verified.jwt, options?.removeOriginalFields);
if (options?.policies?.format !== false) {
validateCredentialPayload(verified.verifiableCredential);
}
return verified;

@@ -807,3 +705,2 @@ });

*/
/**

@@ -831,9 +728,8 @@ * Creates a VerifiablePresentation JWT given a `PresentationPayload` or `JwtPresentationPayload` and an `Issuer`.

...transformPresentationInput(payload, options?.removeOriginalFields)
}; // add challenge to nonce
};
// add challenge to nonce
if (options.challenge && Object.getOwnPropertyNames(parsedPayload).indexOf('nonce') === -1) {
parsedPayload.nonce = options.challenge;
} // add domain to audience.
}
// add domain to audience.
if (options.domain) {

@@ -843,8 +739,9 @@ const audience = [...asArray(options.domain), ...asArray(parsedPayload.aud)].filter(notEmpty);

}
validateJwtPresentationPayload(parsedPayload);
return Promise.resolve(didJwt.createJWT(parsedPayload, { ...options,
return Promise.resolve(didJwt.createJWT(parsedPayload, {
...options,
issuer: holder.did || parsedPayload.iss || '',
signer: holder.signer
}, { ...options.header,
}, {
...options.header,
alg: holder.alg || options.header?.alg || JWT_ALG

@@ -856,3 +753,2 @@ }));

};
/**

@@ -881,8 +777,28 @@ * Creates a VerifiableCredential given a `CredentialPayload` or `JwtCredentialPayload` and an `Issuer`.

validateJwtCredentialPayload(parsedPayload);
return Promise.resolve(didJwt.createJWT(parsedPayload, { ...options,
issuer: issuer.did || parsedPayload.iss || '',
signer: issuer.signer
}, { ...options.header,
alg: issuer.alg || options.header?.alg || JWT_ALG
}));
if (!Array.isArray(issuer)) {
return Promise.resolve(didJwt.createJWT(parsedPayload, {
...options,
issuer: issuer.did || parsedPayload.iss || '',
signer: issuer.signer
}, {
...options.header,
alg: issuer.alg || options.header?.alg || JWT_ALG
}));
} else {
const did = issuer[0].did;
const issuers = [];
for (const iss of issuer) {
if (iss.did !== did) {
throw new Error('All issuers must be the same did to comply with the Verifiable Conditions spec');
}
issuers.push({
issuer: iss.did || parsedPayload.iss || '',
signer: iss.signer,
alg: iss.alg || options.header?.alg || JWT_ALG
});
}
return Promise.resolve(didJwt.createMultisignatureJWT(parsedPayload, {
...options
}, issuers));
}
} catch (e) {

@@ -908,4 +824,4 @@ return Promise.reject(e);

validateContext(payload.vp['@context']);
validateVpType(payload.vp.type); // empty credential array is allowed
validateVpType(payload.vp.type);
// empty credential array is allowed
if (payload.vp.verifiableCredential && payload.vp.verifiableCredential.length >= 1) {

@@ -920,3 +836,2 @@ for (const vc of asArray(payload.vp.verifiableCredential)) {

}
if (payload.exp) validateTimestamp(payload.exp);

@@ -926,4 +841,4 @@ }

validateContext(payload['@context']);
validateVpType(payload.type); // empty credential array is allowed
validateVpType(payload.type);
// empty credential array is allowed
if (payload.verifiableCredential && payload.verifiableCredential.length >= 1) {

@@ -938,3 +853,2 @@ for (const vc of payload.verifiableCredential) {

}
if (payload.expirationDate) validateTimestamp(payload.expirationDate);

@@ -946,7 +860,5 @@ }

}
if (options.domain) {
// aud might be an array
let matchedAudience;
if (payload.aud) {

@@ -956,3 +868,2 @@ const audArray = Array.isArray(payload.aud) ? payload.aud : [payload.aud];

}
if (typeof matchedAudience === 'undefined') {

@@ -959,0 +870,0 @@ throw new Error(`${VC_ERROR.AUTH_ERROR}: Presentation does not contain the mandatory domain (JWT: aud) for : ${options.domain}`);

{
"name": "did-jwt-vc",
"version": "3.1.4",
"version": "3.2.0",
"description": "Create and verify W3C Verifiable Credentials and Presentations in JWT format",

@@ -39,4 +39,4 @@ "type": "module",

"dependencies": {
"did-jwt": "^7.0.0",
"did-resolver": "^4.0.0"
"did-jwt": "^7.1.0",
"did-resolver": "^4.1.0"
},

@@ -43,0 +43,0 @@ "repository": {

@@ -1,2 +0,2 @@

import { createJWT, verifyJWT } from 'did-jwt'
import { createJWT, createMultisignatureJWT, verifyJWT } from 'did-jwt'
import { Resolvable } from 'did-resolver'

@@ -82,3 +82,3 @@ import * as validators from './validators'

payload: JwtCredentialPayload | CredentialPayload,
issuer: Issuer,
issuer: Issuer | Issuer[],
options: CreateCredentialOptions = {}

@@ -91,14 +91,32 @@ ): Promise<JWT> {

validateJwtCredentialPayload(parsedPayload)
return createJWT(
parsedPayload,
{
...options,
issuer: issuer.did || parsedPayload.iss || '',
signer: issuer.signer,
},
{
...options.header,
alg: issuer.alg || options.header?.alg || JWT_ALG,
if (!Array.isArray(issuer)) {
return createJWT(
parsedPayload,
{
...options,
issuer: issuer.did || parsedPayload.iss || '',
signer: issuer.signer,
},
{
...options.header,
alg: issuer.alg || options.header?.alg || JWT_ALG,
}
)
} else {
const did = issuer[0].did
const issuers = []
for (const iss of issuer) {
if (iss.did !== did) {
throw new Error('All issuers must be the same did to comply with the Verifiable Conditions spec')
}
issuers.push({
issuer: iss.did || parsedPayload.iss || '',
signer: iss.signer,
alg: iss.alg || options.header?.alg || JWT_ALG,
})
}
)
return createMultisignatureJWT(parsedPayload, { ...options }, issuers)
}
}

@@ -105,0 +123,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc