@sphereon/ssi-types
Advanced tools
Comparing version 0.8.1-next.194 to 0.8.1-next.272
@@ -1,6 +0,6 @@ | ||
import { ICredential, IPresentation, IVerifiableCredential, IVerifiablePresentation, JwtDecodedVerifiableCredential, JwtDecodedVerifiablePresentation, OriginalVerifiableCredential, OriginalVerifiablePresentation, WrappedVerifiableCredential, WrappedVerifiablePresentation } from '../types'; | ||
import { DocumentFormat, IPresentation, IVerifiableCredential, IVerifiablePresentation, JwtDecodedVerifiableCredential, JwtDecodedVerifiablePresentation, OriginalVerifiableCredential, OriginalVerifiablePresentation, W3CVerifiableCredential, W3CVerifiablePresentation, WrappedVerifiableCredential, WrappedVerifiablePresentation } from '../types'; | ||
export declare class CredentialMapper { | ||
static decodeVerifiablePresentation(presentation: OriginalVerifiablePresentation): JwtDecodedVerifiablePresentation | IVerifiablePresentation; | ||
static decodeVerifiableCredential(credential: OriginalVerifiableCredential): JwtDecodedVerifiableCredential | IVerifiableCredential; | ||
static toWrappedVerifiablePresentation(presentation: OriginalVerifiablePresentation, opts?: { | ||
static toWrappedVerifiablePresentation(originalPresentation: OriginalVerifiablePresentation, opts?: { | ||
maxTimeSkewInMS?: number; | ||
@@ -15,3 +15,3 @@ }): WrappedVerifiablePresentation; | ||
static isJwtEncoded(original: OriginalVerifiableCredential | OriginalVerifiablePresentation): boolean; | ||
private static isJsonLdString; | ||
private static isJsonLdAsString; | ||
static isJwtDecodedCredential(original: OriginalVerifiableCredential): boolean; | ||
@@ -24,17 +24,21 @@ static isJwtDecodedPresentation(original: OriginalVerifiablePresentation): boolean; | ||
maxTimeSkewInMS?: number; | ||
}): IPresentation; | ||
}): IVerifiablePresentation; | ||
static toUniformCredential(verifiableCredential: OriginalVerifiableCredential, opts?: { | ||
maxTimeSkewInMS?: number; | ||
}): ICredential; | ||
}): IVerifiableCredential; | ||
static toUniformPresentation(presentation: OriginalVerifiablePresentation, opts?: { | ||
maxTimeSkewInMS?: number; | ||
}): IPresentation; | ||
}): IVerifiablePresentation; | ||
static jwtEncodedCredentialToUniformCredential(jwt: string, opts?: { | ||
maxTimeSkewInMS?: number; | ||
}): ICredential; | ||
}): IVerifiableCredential; | ||
static jwtDecodedCredentialToUniformCredential(decoded: JwtDecodedVerifiableCredential, opts?: { | ||
maxTimeSkewInMS?: number; | ||
}): ICredential; | ||
}): IVerifiableCredential; | ||
static toExternalVerifiableCredential(verifiableCredential: any): IVerifiableCredential; | ||
static storedCredentialToOriginalFormat(credential: W3CVerifiableCredential): W3CVerifiableCredential; | ||
static storedPresentationToOriginalFormat(presentation: W3CVerifiablePresentation): W3CVerifiablePresentation; | ||
static toCompactJWT(jwtDocument: W3CVerifiableCredential | JwtDecodedVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiablePresentation): string; | ||
static detectDocumentType(document: W3CVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiableCredential | JwtDecodedVerifiablePresentation): DocumentFormat; | ||
} | ||
//# sourceMappingURL=credential-mapper.d.ts.map |
@@ -12,4 +12,14 @@ "use strict"; | ||
static decodeVerifiablePresentation(presentation) { | ||
var _a; | ||
if (CredentialMapper.isJwtEncoded(presentation)) { | ||
return (0, jwt_decode_1.default)(presentation); | ||
const payload = (0, jwt_decode_1.default)(presentation); | ||
const header = (0, jwt_decode_1.default)(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; | ||
} | ||
@@ -19,3 +29,3 @@ else if (CredentialMapper.isJwtDecodedPresentation(presentation)) { | ||
} | ||
else if (CredentialMapper.isJsonLdString(presentation)) { | ||
else if (CredentialMapper.isJsonLdAsString(presentation)) { | ||
return JSON.parse(presentation); | ||
@@ -28,4 +38,14 @@ } | ||
static decodeVerifiableCredential(credential) { | ||
var _a; | ||
if (CredentialMapper.isJwtEncoded(credential)) { | ||
return (0, jwt_decode_1.default)(credential); | ||
const payload = (0, jwt_decode_1.default)(credential); | ||
const header = (0, jwt_decode_1.default)(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; | ||
} | ||
@@ -35,3 +55,3 @@ else if (CredentialMapper.isJwtDecodedCredential(credential)) { | ||
} | ||
else if (CredentialMapper.isJsonLdString(credential)) { | ||
else if (CredentialMapper.isJsonLdAsString(credential)) { | ||
return JSON.parse(credential); | ||
@@ -43,4 +63,4 @@ } | ||
} | ||
static toWrappedVerifiablePresentation(presentation, opts) { | ||
const original = presentation; | ||
static toWrappedVerifiablePresentation(originalPresentation, opts) { | ||
const original = originalPresentation; | ||
const isJwtEncoded = CredentialMapper.isJwtEncoded(original); | ||
@@ -51,7 +71,14 @@ const isJwtDecoded = CredentialMapper.isJwtDecodedPresentation(original); | ||
const decoded = CredentialMapper.decodeVerifiablePresentation(original); | ||
const vp = isJwtEncoded || isJwtDecoded | ||
? CredentialMapper.jwtDecodedPresentationToUniformPresentation(decoded, false, opts) | ||
: decoded; | ||
const vcs = CredentialMapper.toWrappedVerifiableCredentials(vp.verifiableCredential, opts); | ||
// todo: We probably want to add proofs as well | ||
let vp; | ||
if (isJwtEncoded || isJwtDecoded) { | ||
vp = CredentialMapper.jwtDecodedPresentationToUniformPresentation(decoded, false, opts); | ||
} | ||
else { | ||
vp = decoded; | ||
} | ||
if (!vp || !('verifiableCredential' in vp) || !vp.verifiableCredential || vp.verifiableCredential.length === 0) { | ||
throw Error(`VP needs to have at least one verifiable credential at this point`); | ||
} | ||
const vcs = CredentialMapper.toWrappedVerifiableCredentials(vp.verifiableCredential /*.map(value => value.original)*/, opts); | ||
const presentation = Object.assign(Object.assign({}, vp), { verifiableCredential: vcs }); | ||
return { | ||
@@ -62,3 +89,3 @@ type, | ||
decoded, | ||
presentation: Object.assign(Object.assign({}, vp), { verifiableCredential: vcs }), | ||
presentation, | ||
vcs, | ||
@@ -76,7 +103,6 @@ }; | ||
const type = isJwtEncoded ? types_1.OriginalType.JWT_ENCODED : isJwtDecoded ? types_1.OriginalType.JWT_DECODED : types_1.OriginalType.JSONLD; | ||
const credential = isJwtDecoded || isJwtDecoded | ||
const credential = isJwtEncoded || isJwtDecoded | ||
? CredentialMapper.jwtDecodedCredentialToUniformCredential(decoded, opts) | ||
: decoded; | ||
const format = isJwtDecoded || isJwtDecoded ? 'jwt_vc' : 'ldp_vc'; | ||
//todo: We probably want to add proofs as well | ||
const format = isJwtEncoded || isJwtDecoded ? 'jwt_vc' : 'ldp_vc'; | ||
return { | ||
@@ -93,3 +119,3 @@ original, | ||
} | ||
static isJsonLdString(original) { | ||
static isJsonLdAsString(original) { | ||
return utils_1.ObjectUtils.isString(original) && original.includes('@context'); | ||
@@ -107,8 +133,9 @@ } | ||
static jwtDecodedPresentationToUniformPresentation(decoded, makeCredentialsUniform = true, opts) { | ||
const presentation = Object.assign({}, decoded.vp); | ||
const presentation = Object.assign({}, (decoded.vp)); | ||
if (makeCredentialsUniform) { | ||
presentation.verifiableCredential = decoded.vp.verifiableCredential.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) | ||
if (!decoded.vp.verifiableCredential) { | ||
throw Error('Verifiable Presentation should have a verifiable credential at this point'); | ||
} | ||
presentation.verifiableCredential = decoded.vp.verifiableCredential.map((vc) => CredentialMapper.toUniformCredential(vc, opts)); | ||
} | ||
// Since this is a presentation, we delete any proof just to be sure (should not occur on JWT, but better safe than sorry) | ||
delete presentation.proof; | ||
if (decoded.iss) { | ||
@@ -160,5 +187,3 @@ const holder = presentation.holder; | ||
static jwtDecodedCredentialToUniformCredential(decoded, opts) { | ||
const credential = Object.assign({}, decoded.vc); | ||
// Since this is a credential, we delete any proof just to be sure (should not occur on JWT, but better safe than sorry) | ||
delete credential.proof; | ||
const credential = Object.assign({}, (decoded.vc)); | ||
const maxSkewInMS = (opts === null || opts === void 0 ? void 0 : opts.maxTimeSkewInMS) !== undefined ? opts.maxTimeSkewInMS : 999; | ||
@@ -168,3 +193,3 @@ if (decoded.exp) { | ||
const jwtExp = parseInt(decoded.exp.toString()); | ||
// fix seconds to millisecs for the date | ||
// fix seconds to millisecond for the date | ||
const expDateAsStr = jwtExp < 9999999999 ? new Date(jwtExp * 1000).toISOString().replace(/\.000Z/, 'Z') : new Date(jwtExp).toISOString(); | ||
@@ -232,14 +257,18 @@ if (expDate && expDate !== expDateAsStr) { | ||
static toExternalVerifiableCredential(verifiableCredential) { | ||
if (!verifiableCredential.proof.type) { | ||
throw new Error('Verifiable credential proof is missing a type'); | ||
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 }); | ||
} | ||
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'); | ||
} | ||
return Object.assign(Object.assign({}, verifiableCredential), { type: verifiableCredential.type | ||
@@ -249,6 +278,66 @@ ? typeof verifiableCredential.type === 'string' | ||
: verifiableCredential.type | ||
: ['VerifiableCredential'], proof: Object.assign(Object.assign({}, verifiableCredential.proof), { type: verifiableCredential.proof.type, created: verifiableCredential.proof.created, proofPurpose: verifiableCredential.proof.proofPurpose, verificationMethod: verifiableCredential.proof.verificationMethod }) }); | ||
: ['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); | ||
} | ||
} | ||
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); | ||
} | ||
} | ||
return presentation; | ||
} | ||
static toCompactJWT(jwtDocument) { | ||
if (CredentialMapper.detectDocumentType(jwtDocument) !== 0 /* DocumentFormat.JWT */) { | ||
throw Error('Cannot convert non JWT credential to JWT'); | ||
} | ||
if (typeof jwtDocument === 'string') { | ||
return jwtDocument; | ||
} | ||
let proof; | ||
if ('vp' in jwtDocument) { | ||
proof = jwtDocument.vp.proof; | ||
} | ||
else if ('vc' in jwtDocument) { | ||
proof = 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 (typeof document === 'string') { | ||
return this.isJsonLdAsString(document) ? 1 /* DocumentFormat.JSONLD */ : 0 /* DocumentFormat.JWT */; | ||
} | ||
const proofs = 'vc' in document ? document.vc.proof : 'vp' in document ? document.vp.proof : document.proof; | ||
const proof = Array.isArray(proofs) ? proofs[0] : proofs; | ||
if (proof.jwt) { | ||
return 0 /* DocumentFormat.JWT */; | ||
} | ||
else if (proof.type === 'EthereumEip712Signature2021') { | ||
return 2 /* DocumentFormat.EIP712 */; | ||
} | ||
return 1 /* DocumentFormat.JSONLD */; | ||
} | ||
} | ||
exports.CredentialMapper = CredentialMapper; | ||
//# sourceMappingURL=credential-mapper.js.map |
@@ -20,3 +20,4 @@ export declare enum IProofPurpose { | ||
BbsBlsSignatureProof2020 = "BbsBlsSignatureProof2020", | ||
BbsBlsBoundSignatureProof2020 = "BbsBlsBoundSignatureProof2020" | ||
BbsBlsBoundSignatureProof2020 = "BbsBlsBoundSignatureProof2020", | ||
JwtProof2020 = "JwtProof2020" | ||
} | ||
@@ -23,0 +24,0 @@ export interface IParsedDID { |
@@ -26,2 +26,3 @@ "use strict"; | ||
IProofType["BbsBlsBoundSignatureProof2020"] = "BbsBlsBoundSignatureProof2020"; | ||
IProofType["JwtProof2020"] = "JwtProof2020"; | ||
})(IProofType = exports.IProofType || (exports.IProofType = {})); | ||
@@ -28,0 +29,0 @@ const parseDid = (did) => { |
@@ -41,2 +41,3 @@ import { PresentationSubmission } from './pex'; | ||
jws?: string; | ||
jwt?: string; | ||
nonce?: string; | ||
@@ -71,4 +72,4 @@ requiredRevealStatements?: string[]; | ||
'@context': ICredentialContextType | ICredentialContextType[]; | ||
type: string[]; | ||
verifiableCredential: W3CVerifiableCredential[]; | ||
type?: string | string[]; | ||
verifiableCredential?: W3CVerifiableCredential[]; | ||
presentation_submission?: PresentationSubmission; | ||
@@ -103,5 +104,5 @@ holder?: string; | ||
/** | ||
* Internal stable representation of a Credential without Proofs, created based on https://www.w3.org/TR/vc-data-model/#jwt-decoding | ||
* Internal stable representation of a Credential | ||
*/ | ||
credential: ICredential; | ||
credential: IVerifiableCredential; | ||
} | ||
@@ -141,3 +142,3 @@ export interface WrappedVerifiablePresentation { | ||
'@context': ICredentialContextType | ICredentialContextType[]; | ||
type: string[]; | ||
type: string | string[]; | ||
verifiableCredential: WrappedVerifiableCredential[]; | ||
@@ -148,3 +149,3 @@ presentation_submission?: PresentationSubmission; | ||
export interface JwtDecodedVerifiableCredential { | ||
vc: ICredential; | ||
vc: IVerifiableCredential; | ||
exp: string; | ||
@@ -172,2 +173,7 @@ iss: string; | ||
export type Original = OriginalVerifiablePresentation | OriginalVerifiableCredential; | ||
export declare const enum DocumentFormat { | ||
JWT = 0, | ||
JSONLD = 1, | ||
EIP712 = 2 | ||
} | ||
//# sourceMappingURL=vc.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.OriginalType = void 0; | ||
exports.DocumentFormat = exports.OriginalType = void 0; | ||
var OriginalType; | ||
@@ -10,2 +10,8 @@ (function (OriginalType) { | ||
})(OriginalType = exports.OriginalType || (exports.OriginalType = {})); | ||
var DocumentFormat; | ||
(function (DocumentFormat) { | ||
DocumentFormat[DocumentFormat["JWT"] = 0] = "JWT"; | ||
DocumentFormat[DocumentFormat["JSONLD"] = 1] = "JSONLD"; | ||
DocumentFormat[DocumentFormat["EIP712"] = 2] = "EIP712"; | ||
})(DocumentFormat = exports.DocumentFormat || (exports.DocumentFormat = {})); | ||
//# sourceMappingURL=vc.js.map |
{ | ||
"name": "@sphereon/ssi-types", | ||
"description": "SSI Common Types", | ||
"version": "0.8.1-next.194+1db71de", | ||
"version": "0.8.1-next.272+a34f653", | ||
"main": "dist/index.js", | ||
@@ -41,3 +41,3 @@ "types": "dist/index.d.ts", | ||
], | ||
"gitHead": "1db71de2a69c72a14bf393d8093e559554f2ab34" | ||
"gitHead": "a34f653b26d26b6d980aa9196b814ad42cfa5e3f" | ||
} |
import { | ||
ICredential, | ||
DocumentFormat, | ||
IPresentation, | ||
IProof, | ||
IProofPurpose, | ||
IProofType, | ||
IVerifiableCredential, | ||
@@ -12,2 +15,5 @@ IVerifiablePresentation, | ||
PresentationFormat, | ||
UniformVerifiablePresentation, | ||
W3CVerifiableCredential, | ||
W3CVerifiablePresentation, | ||
WrappedVerifiableCredential, | ||
@@ -19,10 +25,19 @@ WrappedVerifiablePresentation, | ||
export class CredentialMapper { | ||
static decodeVerifiablePresentation(presentation: OriginalVerifiablePresentation): JwtDecodedVerifiablePresentation | IVerifiablePresentation { | ||
if (CredentialMapper.isJwtEncoded(presentation)) { | ||
return jwt_decode(presentation as string) as JwtDecodedVerifiablePresentation | ||
const payload = jwt_decode(presentation as string) as JwtDecodedVerifiablePresentation | ||
const header = jwt_decode(presentation as string, { header: true }) as Record<string, any> | ||
payload.vp.proof = { | ||
type: IProofType.JwtProof2020, | ||
created: payload.nbf, | ||
proofPurpose: IProofPurpose.authentication, | ||
verificationMethod: header['kid'] ?? payload.iss, | ||
jwt: presentation as string, | ||
} | ||
return payload | ||
} else if (CredentialMapper.isJwtDecodedPresentation(presentation)) { | ||
return presentation as JwtDecodedVerifiablePresentation | ||
} else if (CredentialMapper.isJsonLdString(presentation)) { | ||
} else if (CredentialMapper.isJsonLdAsString(presentation)) { | ||
return JSON.parse(presentation as string) as IVerifiablePresentation | ||
@@ -36,6 +51,15 @@ } else { | ||
if (CredentialMapper.isJwtEncoded(credential)) { | ||
return jwt_decode(credential as string) as JwtDecodedVerifiableCredential | ||
const payload = jwt_decode(credential as string) as JwtDecodedVerifiableCredential | ||
const header = jwt_decode(credential as string, { header: true }) as Record<string, any> | ||
payload.vc.proof = { | ||
type: IProofType.JwtProof2020, | ||
created: payload.nbf, | ||
proofPurpose: IProofPurpose.authentication, | ||
verificationMethod: header['kid'] ?? payload.iss, | ||
jwt: credential as string, | ||
} | ||
return payload | ||
} else if (CredentialMapper.isJwtDecodedCredential(credential)) { | ||
return credential as JwtDecodedVerifiableCredential | ||
} else if (CredentialMapper.isJsonLdString(credential)) { | ||
} else if (CredentialMapper.isJsonLdAsString(credential)) { | ||
return JSON.parse(credential as string) as IVerifiableCredential | ||
@@ -48,6 +72,6 @@ } else { | ||
static toWrappedVerifiablePresentation( | ||
presentation: OriginalVerifiablePresentation, | ||
opts?: { maxTimeSkewInMS?: number } | ||
originalPresentation: OriginalVerifiablePresentation, | ||
opts?: { maxTimeSkewInMS?: number }, | ||
): WrappedVerifiablePresentation { | ||
const original = presentation | ||
const original = originalPresentation | ||
const isJwtEncoded: boolean = CredentialMapper.isJwtEncoded(original) | ||
@@ -59,9 +83,17 @@ const isJwtDecoded: boolean = CredentialMapper.isJwtDecodedPresentation(original) | ||
const decoded = CredentialMapper.decodeVerifiablePresentation(original) | ||
const vp: IPresentation = | ||
isJwtEncoded || isJwtDecoded | ||
? CredentialMapper.jwtDecodedPresentationToUniformPresentation(decoded as JwtDecodedVerifiablePresentation, false, opts) | ||
: (decoded as IPresentation) | ||
const vcs: WrappedVerifiableCredential[] = CredentialMapper.toWrappedVerifiableCredentials(vp.verifiableCredential, opts) | ||
let vp: OriginalVerifiablePresentation | ||
if (isJwtEncoded || isJwtDecoded) { | ||
vp = CredentialMapper.jwtDecodedPresentationToUniformPresentation(decoded as JwtDecodedVerifiablePresentation, false, opts) | ||
} else { | ||
vp = decoded as IVerifiablePresentation | ||
} | ||
if (!vp || !('verifiableCredential' in vp) || !vp.verifiableCredential || vp.verifiableCredential.length === 0) { | ||
throw Error(`VP needs to have at least one verifiable credential at this point`) | ||
} | ||
const vcs: WrappedVerifiableCredential[] = CredentialMapper.toWrappedVerifiableCredentials(vp.verifiableCredential/*.map(value => value.original)*/, opts) | ||
// todo: We probably want to add proofs as well | ||
const presentation = { | ||
...vp, | ||
verifiableCredential: vcs, // We overwrite the credentials with wrapped versions, making it an InternalVerifiablePresentation. Note: we keep the singular key name of the vc data model | ||
} as UniformVerifiablePresentation | ||
return { | ||
@@ -72,6 +104,3 @@ type, | ||
decoded, | ||
presentation: { | ||
...vp, | ||
verifiableCredential: vcs, // We overwrite the credentials with wrapped versions, making it an InternalVerifiablePresentation. Note: we keep the singular key name of the vc data model | ||
}, | ||
presentation, | ||
vcs, | ||
@@ -83,3 +112,3 @@ } | ||
verifiableCredentials: OriginalVerifiableCredential[], | ||
opts?: { maxTimeSkewInMS?: number } | ||
opts?: { maxTimeSkewInMS?: number }, | ||
): WrappedVerifiableCredential[] { | ||
@@ -91,6 +120,5 @@ return verifiableCredentials.map((vc) => CredentialMapper.toWrappedVerifiableCredential(vc, opts)) | ||
verifiableCredential: OriginalVerifiableCredential, | ||
opts?: { maxTimeSkewInMS?: number } | ||
opts?: { maxTimeSkewInMS?: number }, | ||
): WrappedVerifiableCredential { | ||
const original = verifiableCredential | ||
const decoded = CredentialMapper.decodeVerifiableCredential(verifiableCredential) | ||
@@ -103,7 +131,7 @@ | ||
const credential = | ||
isJwtDecoded || isJwtDecoded | ||
isJwtEncoded || isJwtDecoded | ||
? CredentialMapper.jwtDecodedCredentialToUniformCredential(decoded as JwtDecodedVerifiableCredential, opts) | ||
: (decoded as ICredential) | ||
const format = isJwtDecoded || isJwtDecoded ? 'jwt_vc' : 'ldp_vc' | ||
//todo: We probably want to add proofs as well | ||
: (decoded as IVerifiableCredential) | ||
const format = isJwtEncoded || isJwtDecoded ? 'jwt_vc' : 'ldp_vc' | ||
return { | ||
@@ -122,3 +150,3 @@ original, | ||
private static isJsonLdString(original: OriginalVerifiableCredential | OriginalVerifiablePresentation) { | ||
private static isJsonLdAsString(original: OriginalVerifiableCredential | OriginalVerifiablePresentation) { | ||
return ObjectUtils.isString(original) && (original as string).includes('@context') | ||
@@ -138,3 +166,3 @@ } | ||
makeCredentialsUniform: boolean = true, | ||
opts?: { maxTimeSkewInMS?: number } | ||
opts?: { maxTimeSkewInMS?: number }, | ||
): IPresentation { | ||
@@ -147,15 +175,15 @@ return CredentialMapper.jwtDecodedPresentationToUniformPresentation(jwt_decode(jwt), makeCredentialsUniform, opts) | ||
makeCredentialsUniform: boolean = true, | ||
opts?: { maxTimeSkewInMS?: number } | ||
): IPresentation { | ||
const presentation: IPresentation = { | ||
...(decoded.vp as IPresentation), | ||
opts?: { maxTimeSkewInMS?: number }, | ||
): IVerifiablePresentation { | ||
const presentation: IVerifiablePresentation = { | ||
...(decoded.vp), | ||
} | ||
if (makeCredentialsUniform) { | ||
if (!decoded.vp.verifiableCredential) { | ||
throw Error('Verifiable Presentation should have a verifiable credential at this point') | ||
} | ||
presentation.verifiableCredential = decoded.vp.verifiableCredential.map((vc) => | ||
CredentialMapper.toUniformCredential(vc, opts) | ||
) as IVerifiableCredential[] // We cast it because we IPresentation needs a VC. The internal Credential doesn't have the required Proof anymore (that is intended) | ||
CredentialMapper.toUniformCredential(vc, opts), | ||
) | ||
} | ||
// Since this is a presentation, we delete any proof just to be sure (should not occur on JWT, but better safe than sorry) | ||
delete presentation.proof | ||
if (decoded.iss) { | ||
@@ -180,3 +208,3 @@ const holder = presentation.holder | ||
static toUniformCredential(verifiableCredential: OriginalVerifiableCredential, opts?: { maxTimeSkewInMS?: number }): ICredential { | ||
static toUniformCredential(verifiableCredential: OriginalVerifiableCredential, opts?: { maxTimeSkewInMS?: number }): IVerifiableCredential { | ||
const original = verifiableCredential | ||
@@ -191,7 +219,7 @@ const decoded = CredentialMapper.decodeVerifiableCredential(verifiableCredential) | ||
} else { | ||
return decoded as ICredential | ||
return decoded as IVerifiableCredential | ||
} | ||
} | ||
static toUniformPresentation(presentation: OriginalVerifiablePresentation, opts?: { maxTimeSkewInMS?: number }): IPresentation { | ||
static toUniformPresentation(presentation: OriginalVerifiablePresentation, opts?: { maxTimeSkewInMS?: number }): IVerifiablePresentation { | ||
const original = presentation | ||
@@ -204,5 +232,5 @@ const decoded = CredentialMapper.decodeVerifiablePresentation(original) | ||
? CredentialMapper.jwtDecodedPresentationToUniformPresentation(decoded as JwtDecodedVerifiablePresentation, false) | ||
: (decoded as IPresentation) | ||
: (decoded as IVerifiablePresentation) | ||
uniformPresentation.verifiableCredential = uniformPresentation.verifiableCredential?.map((vc) => | ||
CredentialMapper.toUniformCredential(vc, opts) | ||
CredentialMapper.toUniformCredential(vc, opts), | ||
) as IVerifiableCredential[] // We cast it because we IPresentation needs a VC. The internal Credential doesn't have the required Proof anymore (that is intended) | ||
@@ -212,12 +240,10 @@ return uniformPresentation | ||
static jwtEncodedCredentialToUniformCredential(jwt: string, opts?: { maxTimeSkewInMS?: number }): ICredential { | ||
static jwtEncodedCredentialToUniformCredential(jwt: string, opts?: { maxTimeSkewInMS?: number }): IVerifiableCredential { | ||
return CredentialMapper.jwtDecodedCredentialToUniformCredential(jwt_decode(jwt), opts) | ||
} | ||
static jwtDecodedCredentialToUniformCredential(decoded: JwtDecodedVerifiableCredential, opts?: { maxTimeSkewInMS?: number }): ICredential { | ||
const credential: ICredential = { | ||
...(decoded.vc as ICredential), | ||
static jwtDecodedCredentialToUniformCredential(decoded: JwtDecodedVerifiableCredential, opts?: { maxTimeSkewInMS?: number }): IVerifiableCredential { | ||
const credential: IVerifiableCredential = { | ||
...(decoded.vc), | ||
} | ||
// Since this is a credential, we delete any proof just to be sure (should not occur on JWT, but better safe than sorry) | ||
delete credential.proof | ||
@@ -229,3 +255,3 @@ const maxSkewInMS = opts?.maxTimeSkewInMS !== undefined ? opts.maxTimeSkewInMS : 999 | ||
const jwtExp = parseInt(decoded.exp.toString()) | ||
// fix seconds to millisecs for the date | ||
// fix seconds to millisecond for the date | ||
const expDateAsStr = jwtExp < 9999999999 ? new Date(jwtExp * 1000).toISOString().replace(/\.000Z/, 'Z') : new Date(jwtExp).toISOString() | ||
@@ -291,2 +317,3 @@ if (expDate && expDate !== expDateAsStr) { | ||
} | ||
return credential | ||
@@ -296,16 +323,26 @@ } | ||
static toExternalVerifiableCredential(verifiableCredential: any): IVerifiableCredential { | ||
if (!verifiableCredential.proof.type) { | ||
throw new Error('Verifiable credential proof is missing a type') | ||
} | ||
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.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.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') | ||
if (!verifiableCredential.proof.verificationMethod) { | ||
throw new Error('Verifiable credential proof is missing a verification method') | ||
} | ||
proof = { | ||
...verifiableCredential.proof, | ||
type: verifiableCredential.proof.type, | ||
created: verifiableCredential.proof.created, | ||
proofPurpose: verifiableCredential.proof.proofPurpose, | ||
verificationMethod: verifiableCredential.proof.verificationMethod, | ||
} | ||
} | ||
@@ -320,11 +357,65 @@ | ||
: ['VerifiableCredential'], | ||
proof: { | ||
...verifiableCredential.proof, | ||
type: verifiableCredential.proof.type, | ||
created: verifiableCredential.proof.created, | ||
proofPurpose: verifiableCredential.proof.proofPurpose, | ||
verificationMethod: verifiableCredential.proof.verificationMethod, | ||
}, | ||
proof, | ||
} | ||
} | ||
static storedCredentialToOriginalFormat(credential: W3CVerifiableCredential): W3CVerifiableCredential { | ||
const type: DocumentFormat = CredentialMapper.detectDocumentType(credential) | ||
if (typeof credential === 'string') { | ||
if (type === DocumentFormat.JWT) { | ||
return CredentialMapper.toCompactJWT(credential) | ||
} else if (type === DocumentFormat.JSONLD) { | ||
return JSON.parse(credential) | ||
} | ||
} | ||
return credential | ||
} | ||
static storedPresentationToOriginalFormat(presentation: W3CVerifiablePresentation): W3CVerifiablePresentation { | ||
const type: DocumentFormat = CredentialMapper.detectDocumentType(presentation) | ||
if (typeof presentation === 'string') { | ||
if (type === DocumentFormat.JWT) { | ||
return CredentialMapper.toCompactJWT(presentation) | ||
} else if (type === DocumentFormat.JSONLD) { | ||
return JSON.parse(presentation) | ||
} | ||
} | ||
return presentation | ||
} | ||
static toCompactJWT(jwtDocument: W3CVerifiableCredential | JwtDecodedVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiablePresentation): string { | ||
if (CredentialMapper.detectDocumentType(jwtDocument) !== DocumentFormat.JWT) { | ||
throw Error('Cannot convert non JWT credential to JWT') | ||
} | ||
if (typeof jwtDocument === 'string') { | ||
return jwtDocument | ||
} | ||
let proof: string | undefined | ||
if ('vp' in jwtDocument) { | ||
proof = jwtDocument.vp.proof | ||
} else if ('vc' in jwtDocument) { | ||
proof = 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: W3CVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiableCredential | JwtDecodedVerifiablePresentation): DocumentFormat { | ||
if (typeof document === 'string') { | ||
return this.isJsonLdAsString(document) ? DocumentFormat.JSONLD : DocumentFormat.JWT | ||
} | ||
const proofs = 'vc' in document ? document.vc.proof : 'vp' in document ? document.vp.proof : (<IVerifiableCredential>document).proof | ||
const proof: IProof = Array.isArray(proofs) ? proofs[0] : proofs | ||
if (proof.jwt) { | ||
return DocumentFormat.JWT | ||
} else if (proof.type === 'EthereumEip712Signature2021') { | ||
return DocumentFormat.EIP712 | ||
} | ||
return DocumentFormat.JSONLD | ||
} | ||
} |
@@ -22,2 +22,3 @@ export enum IProofPurpose { | ||
BbsBlsBoundSignatureProof2020 = 'BbsBlsBoundSignatureProof2020', | ||
JwtProof2020 = 'JwtProof2020' | ||
} | ||
@@ -24,0 +25,0 @@ |
@@ -56,2 +56,3 @@ import { PresentationSubmission } from './pex' | ||
jws?: string // JWS based proof | ||
jwt?: string //Jwt 2020 proof. Used to map a JWT VC onto a uniform presentation, and retain access to the original JWT | ||
nonce?: string // Similar to challenge. A nonce to protect against replay attacks, used in some ZKP proofs | ||
@@ -95,4 +96,4 @@ requiredRevealStatements?: string[] // The parts of the proof that must be revealed in a derived proof | ||
'@context': ICredentialContextType | ICredentialContextType[] | ||
type: string[] | ||
verifiableCredential: W3CVerifiableCredential[] // we relax to ICredential for internal decoded stable representations without proofs | ||
type?: string | string[] | ||
verifiableCredential?: W3CVerifiableCredential[] | ||
presentation_submission?: PresentationSubmission | ||
@@ -131,5 +132,5 @@ holder?: string | ||
/** | ||
* Internal stable representation of a Credential without Proofs, created based on https://www.w3.org/TR/vc-data-model/#jwt-decoding | ||
* Internal stable representation of a Credential | ||
*/ | ||
credential: ICredential | ||
credential: IVerifiableCredential | ||
} | ||
@@ -172,3 +173,3 @@ | ||
'@context': ICredentialContextType | ICredentialContextType[] | ||
type: string[] | ||
type: string | string[] | ||
verifiableCredential: WrappedVerifiableCredential[] | ||
@@ -180,3 +181,3 @@ presentation_submission?: PresentationSubmission | ||
export interface JwtDecodedVerifiableCredential { | ||
vc: ICredential | ||
vc: IVerifiableCredential | ||
exp: string | ||
@@ -209,1 +210,7 @@ iss: string | ||
export type Original = OriginalVerifiablePresentation | OriginalVerifiableCredential | ||
export const enum DocumentFormat { | ||
JWT, | ||
JSONLD, | ||
EIP712, | ||
} |
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
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
102164
1487