Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: fix intoWrappedVerifiablePresentation for mdoc #288

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 31 additions & 28 deletions packages/ssi-types/src/mapper/credential-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class CredentialMapper {
*/
static decodeVerifiablePresentation(
presentation: OriginalVerifiablePresentation,
hasher?: Hasher,
hasher?: Hasher
): JwtDecodedVerifiablePresentation | IVerifiablePresentation | SdJwtDecodedVerifiableCredential | MdocOid4vpMdocVpToken | MdocDeviceResponse {
if (CredentialMapper.isJwtEncoded(presentation)) {
const payload = jwt_decode(presentation as string) as JwtDecodedVerifiablePresentation
Expand Down Expand Up @@ -111,7 +111,7 @@ export class CredentialMapper {
*/
static decodeVerifiableCredential(
credential: OriginalVerifiableCredential,
hasher?: Hasher,
hasher?: Hasher
): JwtDecodedVerifiableCredential | IVerifiableCredential | SdJwtDecodedVerifiableCredential {
if (CredentialMapper.isJwtEncoded(credential)) {
const payload = jwt_decode(credential as string) as JwtDecodedVerifiableCredential
Expand Down Expand Up @@ -151,26 +151,29 @@ export class CredentialMapper {
*/
static toWrappedVerifiablePresentation(
originalPresentation: OriginalVerifiablePresentation,
opts?: { maxTimeSkewInMS?: number; hasher?: Hasher },
opts?: { maxTimeSkewInMS?: number; hasher?: Hasher }
): WrappedVerifiablePresentation {
// MSO_MDOC
if (CredentialMapper.isMsoMdocDecodedPresentation(originalPresentation) || CredentialMapper.isMsoMdocOid4VPEncoded(originalPresentation)) {
let deviceResponse: MdocDeviceResponse
let originalType: OriginalType
if (CredentialMapper.isMsoMdocOid4VPEncoded(originalPresentation)) {
deviceResponse = decodeMdocDeviceResponse(originalPresentation)
originalType = OriginalType.MSO_MDOC_ENCODED
} else {
deviceResponse = originalPresentation
originalType = OriginalType.MSO_MDOC_DECODED
}

const mdocCredentials = deviceResponse.documents?.map(
(doc) => CredentialMapper.toWrappedVerifiableCredential(doc, opts) as WrappedMdocCredential,
(doc) => CredentialMapper.toWrappedVerifiableCredential(doc, opts) as WrappedMdocCredential
)
if (!mdocCredentials || mdocCredentials.length === 0) {
throw new Error('could not extract any mdoc credentials from mdoc device response')
}

return {
type: CredentialMapper.isMsoMdocDecodedPresentation(originalPresentation) ? OriginalType.MSO_MDOC_DECODED : OriginalType.MSO_MDOC_ENCODED,
type: originalType,
format: 'mso_mdoc',
original: originalPresentation,
presentation: deviceResponse,
Expand Down Expand Up @@ -206,7 +209,7 @@ export class CredentialMapper {
typeof originalPresentation !== 'string' && CredentialMapper.hasJWTProofType(originalPresentation) ? proof?.jwt : originalPresentation
if (!original) {
throw Error(
'Could not determine original presentation, probably it was a converted JWT presentation, that is now missing the JWT value in the proof',
'Could not determine original presentation, probably it was a converted JWT presentation, that is now missing the JWT value in the proof'
)
}
const decoded = CredentialMapper.decodeVerifiablePresentation(original) as IVerifiablePresentation | JwtDecodedVerifiablePresentation
Expand Down Expand Up @@ -234,7 +237,7 @@ export class CredentialMapper {
? []
: (CredentialMapper.toWrappedVerifiableCredentials(
vp.verifiableCredential ?? [] /*.map(value => value.original)*/,
opts,
opts
) as WrappedW3CVerifiableCredential[])

const presentation = {
Expand Down Expand Up @@ -262,7 +265,7 @@ export class CredentialMapper {
*/
static toWrappedVerifiableCredentials(
verifiableCredentials: OriginalVerifiableCredential[],
opts?: { maxTimeSkewInMS?: number; hasher?: Hasher },
opts?: { maxTimeSkewInMS?: number; hasher?: Hasher }
): WrappedVerifiableCredential[] {
return verifiableCredentials.map((vc) => CredentialMapper.toWrappedVerifiableCredential(vc, opts))
}
Expand All @@ -278,7 +281,7 @@ export class CredentialMapper {
*/
static toWrappedVerifiableCredential(
verifiableCredential: OriginalVerifiableCredential,
opts?: { maxTimeSkewInMS?: number; hasher?: Hasher },
opts?: { maxTimeSkewInMS?: number; hasher?: Hasher }
): WrappedVerifiableCredential {
// MSO_MDOC
if (CredentialMapper.isMsoMdocDecodedCredential(verifiableCredential) || CredentialMapper.isMsoMdocOid4VPEncoded(verifiableCredential)) {
Expand Down Expand Up @@ -320,10 +323,10 @@ export class CredentialMapper {

// If the VC is not an encoded/decoded SD-JWT, we assume it will be a W3C VC
const proof = CredentialMapper.getFirstProof(verifiableCredential)
const original = CredentialMapper.hasJWTProofType(verifiableCredential) && proof ? (proof.jwt ?? verifiableCredential) : verifiableCredential
const original = CredentialMapper.hasJWTProofType(verifiableCredential) && proof ? proof.jwt ?? verifiableCredential : verifiableCredential
if (!original) {
throw Error(
'Could not determine original credential, probably it was a converted JWT credential, that is now missing the JWT value in the proof',
'Could not determine original credential, probably it was a converted JWT credential, that is now missing the JWT value in the proof'
)
}
const decoded = CredentialMapper.decodeVerifiableCredential(original) as JwtDecodedVerifiableCredential | IVerifiableCredential
Expand Down Expand Up @@ -439,7 +442,7 @@ export class CredentialMapper {
}

public static isW3cPresentation(
presentation: UniformVerifiablePresentation | IPresentation | SdJwtDecodedVerifiableCredential | DeviceResponseCbor,
presentation: UniformVerifiablePresentation | IPresentation | SdJwtDecodedVerifiableCredential | DeviceResponseCbor
): presentation is IPresentation {
return (
typeof presentation === 'object' &&
Expand All @@ -449,7 +452,7 @@ export class CredentialMapper {
}

public static isSdJwtDecodedCredentialPayload(
credential: ICredential | SdJwtDecodedVerifiableCredentialPayload,
credential: ICredential | SdJwtDecodedVerifiableCredentialPayload
): credential is SdJwtDecodedVerifiableCredentialPayload {
return typeof credential === 'object' && 'vct' in credential
}
Expand Down Expand Up @@ -481,7 +484,7 @@ export class CredentialMapper {
}

public static isSdJwtDecodedCredential(
original: OriginalVerifiableCredential | OriginalVerifiablePresentation | ICredential | IPresentation,
original: OriginalVerifiableCredential | OriginalVerifiablePresentation | ICredential | IPresentation
): original is SdJwtDecodedVerifiableCredential {
return (
typeof original === 'object' &&
Expand All @@ -490,7 +493,7 @@ export class CredentialMapper {
}

public static isMsoMdocDecodedCredential(
original: OriginalVerifiableCredential | OriginalVerifiablePresentation | ICredential | IPresentation,
original: OriginalVerifiableCredential | OriginalVerifiablePresentation | ICredential | IPresentation
): original is MdocDocument {
return typeof original === 'object' && 'issuerSigned' in original && (<MdocDocument>original).issuerSigned !== undefined
}
Expand Down Expand Up @@ -525,15 +528,15 @@ export class CredentialMapper {
static jwtEncodedPresentationToUniformPresentation(
jwt: string,
makeCredentialsUniform: boolean = true,
opts?: { maxTimeSkewInMS?: number },
opts?: { maxTimeSkewInMS?: number }
): IPresentation {
return CredentialMapper.jwtDecodedPresentationToUniformPresentation(jwt_decode(jwt), makeCredentialsUniform, opts)
}

static jwtDecodedPresentationToUniformPresentation(
decoded: JwtDecodedVerifiablePresentation,
makeCredentialsUniform: boolean = true,
opts?: { maxTimeSkewInMS?: number },
opts?: { maxTimeSkewInMS?: number }
): IVerifiablePresentation {
const { iss, aud, jti, vp, ...rest } = decoded

Expand Down Expand Up @@ -580,7 +583,7 @@ export class CredentialMapper {
opts?: {
maxTimeSkewInMS?: number
hasher?: Hasher
},
}
): IVerifiableCredential {
if (CredentialMapper.isMsoMdocDecodedCredential(verifiableCredential)) {
return mdocDecodedCredentialToUniformCredential(verifiableCredential)
Expand All @@ -594,7 +597,7 @@ export class CredentialMapper {
: verifiableCredential
if (!original) {
throw Error(
'Could not determine original credential from passed in credential. Probably because a JWT proof type was present, but now is not available anymore',
'Could not determine original credential from passed in credential. Probably because a JWT proof type was present, but now is not available anymore'
)
}
const decoded = CredentialMapper.decodeVerifiableCredential(original, opts?.hasher)
Expand All @@ -617,7 +620,7 @@ export class CredentialMapper {

static toUniformPresentation(
presentation: OriginalVerifiablePresentation,
opts?: { maxTimeSkewInMS?: number; addContextIfMissing?: boolean; hasher?: Hasher },
opts?: { maxTimeSkewInMS?: number; addContextIfMissing?: boolean; hasher?: Hasher }
): IVerifiablePresentation {
if (CredentialMapper.isSdJwtDecodedCredential(presentation)) {
throw new Error('Converting SD-JWT VC to uniform VP is not supported.')
Expand All @@ -629,7 +632,7 @@ export class CredentialMapper {
const original = typeof presentation !== 'string' && CredentialMapper.hasJWTProofType(presentation) ? proof?.jwt : presentation
if (!original) {
throw Error(
'Could not determine original presentation, probably it was a converted JWT presentation, that is now missing the JWT value in the proof',
'Could not determine original presentation, probably it was a converted JWT presentation, that is now missing the JWT value in the proof'
)
}
const decoded = CredentialMapper.decodeVerifiablePresentation(original, opts?.hasher)
Expand All @@ -646,7 +649,7 @@ export class CredentialMapper {
}

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)
return uniformPresentation
}
Expand All @@ -655,14 +658,14 @@ export class CredentialMapper {
jwt: string,
opts?: {
maxTimeSkewInMS?: number
},
}
): IVerifiableCredential {
return CredentialMapper.jwtDecodedCredentialToUniformCredential(jwt_decode(jwt), opts)
}

static jwtDecodedCredentialToUniformCredential(
decoded: JwtDecodedVerifiableCredential,
opts?: { maxTimeSkewInMS?: number },
opts?: { maxTimeSkewInMS?: number }
): IVerifiableCredential {
const { exp, nbf, iss, vc, sub, jti, ...rest } = decoded
const credential: IVerifiableCredential = {
Expand Down Expand Up @@ -830,7 +833,7 @@ export class CredentialMapper {
}

static toCompactJWT(
jwtDocument: W3CVerifiableCredential | JwtDecodedVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiablePresentation | string,
jwtDocument: W3CVerifiableCredential | JwtDecodedVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiablePresentation | string
): string {
if (!jwtDocument || CredentialMapper.detectDocumentType(jwtDocument) !== DocumentFormat.JWT) {
throw Error('Cannot convert non JWT credential to JWT')
Expand Down Expand Up @@ -860,7 +863,7 @@ export class CredentialMapper {
| JwtDecodedVerifiablePresentation
| SdJwtDecodedVerifiableCredential
| MdocDeviceResponse
| MdocDocument,
| MdocDocument
): DocumentFormat {
if (this.isMsoMdocOid4VPEncoded(document as any) || this.isMsoMdocDecodedCredential(document as any)) {
return DocumentFormat.MSO_MDOC
Expand Down Expand Up @@ -888,7 +891,7 @@ export class CredentialMapper {
}

private static hasJWTProofType(
document: W3CVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiableCredential | JwtDecodedVerifiablePresentation,
document: W3CVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiableCredential | JwtDecodedVerifiablePresentation
): boolean {
if (typeof document === 'string') {
return false
Expand All @@ -897,7 +900,7 @@ export class CredentialMapper {
}

private static getFirstProof(
document: W3CVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiableCredential | JwtDecodedVerifiablePresentation,
document: W3CVerifiableCredential | W3CVerifiablePresentation | JwtDecodedVerifiableCredential | JwtDecodedVerifiablePresentation
): IProof | undefined {
if (!document || typeof document === 'string') {
return undefined
Expand Down