Skip to content

Commit

Permalink
Introduce sd-jwt-vc format in presentation definition preparation
Browse files Browse the repository at this point in the history
  • Loading branch information
vafeini committed Dec 10, 2024
1 parent c67678c commit be89f19
Show file tree
Hide file tree
Showing 27 changed files with 430 additions and 289 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {Attestation} from "@core/models/attestation/Attestation";
import {AttestationDefinition} from "@core/models/attestation/AttestationDefinition";
import {AttestationType} from "@core/models/attestation/AttestationType";
import {AttestationFormat} from "@core/models/attestation/AttestationFormat";

export const PID_ATTESTATION: Attestation = {
export const PID_ATTESTATION: AttestationDefinition = {
name: "Person Identification Data (PID)",
type: AttestationType.PID,
dataSet: [
Expand Down Expand Up @@ -37,7 +36,7 @@ export const PID_ATTESTATION: Attestation = {
]
}

export const MDL_ATTESTATION: Attestation = {
export const MDL_ATTESTATION: AttestationDefinition = {
name: "Mobile Driving Licence (MDL)",
type: AttestationType.MDL,
dataSet: [
Expand Down Expand Up @@ -75,7 +74,7 @@ export const MDL_ATTESTATION: Attestation = {
]
}

export const AGE_OVER_18_ATTESTATION: Attestation = {
export const AGE_OVER_18_ATTESTATION: AttestationDefinition = {
name: "Age Over 18",
type: AttestationType.AGE_OVER_18,
dataSet: [
Expand All @@ -89,7 +88,7 @@ export const AGE_OVER_18_ATTESTATION: Attestation = {
]
}

export const PHOTO_ID_ATTESTATION: Attestation = {
export const PHOTO_ID_ATTESTATION: AttestationDefinition = {
name: "Photo ID",
type: AttestationType.PHOTO_ID,
dataSet: [
Expand Down Expand Up @@ -128,14 +127,10 @@ export const PHOTO_ID_ATTESTATION: Attestation = {
]
}

export const SUPPORTED_ATTESTATIONS: { [id: string]: Attestation } = {
export const SUPPORTED_ATTESTATIONS: { [id: string]: AttestationDefinition } = {
"pid": PID_ATTESTATION,
"mdl": MDL_ATTESTATION,
"photo_id": PHOTO_ID_ATTESTATION,
"age_over_18": AGE_OVER_18_ATTESTATION,
}

export const SUPPORTED_FORMATS: AttestationFormat[] = [
AttestationFormat.MSO_MDOC
]

134 changes: 134 additions & 0 deletions src/app/core/constants/attestations-per-format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import {Attestation, MsoMdocAttestation, SdJwtVcAttestation} from "@core/models/attestation/Attestations";
import {AGE_OVER_18_ATTESTATION, MDL_ATTESTATION, PHOTO_ID_ATTESTATION, PID_ATTESTATION} from "@core/constants/attestation-definitions";
import {AttestationFormat} from "@core/models/attestation/AttestationFormat";
import {AttestationType} from "@core/models/attestation/AttestationType";
import {DataElement} from "@core/models/attestation/AttestationDefinition";

export const SUPPORTED_FORMATS: AttestationFormat[] = [
AttestationFormat.MSO_MDOC,
AttestationFormat.SD_JWT_VC
]

/*---- MDL ATTESTATION INSTANCES PER FORMAT ----*/
export const MDL_MSO_MDOC: MsoMdocAttestation = {
format: AttestationFormat.MSO_MDOC,
attestationDef: MDL_ATTESTATION,
doctype: 'org.iso.18013.5.1.mDL',
namespace: 'org.iso.18013.5.1',
attributePath: (attribute: DataElement) => { return msoMdocAttributePath(attribute, 'org.iso.18013.5.1') }
}
export const MDL_SD_JWT_VC: SdJwtVcAttestation = {
format: AttestationFormat.SD_JWT_VC,
vct: "urn:eu.europa.ec.eudi:pid:1",
attestationDef: MDL_ATTESTATION,
attributePath: (attribute: DataElement) => { return sdJwtVcAttributePath(attribute, AttestationType.MDL) }
}

/*---- PID ATTESTATION INSTANCES PER FORMAT ----*/
export const PID_MSO_MDOC: MsoMdocAttestation = {
format: AttestationFormat.MSO_MDOC,
attestationDef: PID_ATTESTATION,
doctype: 'eu.europa.ec.eudi.pid.1',
namespace: 'eu.europa.ec.eudi.pid.1',
attributePath: (attribute: DataElement) => { return msoMdocAttributePath(attribute, 'eu.europa.ec.eudi.pid.1') }
}
export const PID_SD_JWT_VC: SdJwtVcAttestation = {
format: AttestationFormat.SD_JWT_VC,
vct: "urn:eu.europa.ec.eudi:pid:1",
attestationDef: PID_ATTESTATION,
attributePath: (attribute: DataElement) => { return sdJwtVcAttributePath(attribute, AttestationType.PID) }
}

/*---- AGE OVER 18 ATTESTATION INSTANCES PER FORMAT ----*/
export const AGE_OVER_18_MSO_MDOC: MsoMdocAttestation = {
format: AttestationFormat.MSO_MDOC,
attestationDef: AGE_OVER_18_ATTESTATION,
doctype: 'eu.europa.ec.eudi.pseudonym.age_over_18.1',
namespace: 'eu.europa.ec.eudi.pseudonym.age_over_18.1',
attributePath: (attribute: DataElement) => { return msoMdocAttributePath(attribute, 'eu.europa.ec.eudi.pseudonym.age_over_18.1') }
}
export const AGE_OVER_18_SD_JWT_VC: SdJwtVcAttestation = {
format: AttestationFormat.SD_JWT_VC,
vct: "urn:eu.europa.ec.eudi:pid:1",
attestationDef: AGE_OVER_18_ATTESTATION,
attributePath: (attribute: DataElement) => { return sdJwtVcAttributePath(attribute, AttestationType.AGE_OVER_18) }
}

/*---- PHOTO ID ATTESTATION INSTANCES PER FORMAT ----*/
export const PHOTO_ID_MSO_MDOC: MsoMdocAttestation = {
format: AttestationFormat.MSO_MDOC,
attestationDef: PHOTO_ID_ATTESTATION,
doctype: 'org.iso.23220.2.photoid.1',
namespace: 'org.iso.23220.2.photoid.1',
attributePath: (attribute: DataElement) => { return msoMdocAttributePath(attribute, 'org.iso.23220.2.photoid.1') }
}
export const PHOTO_ID_SD_JWT_VC: SdJwtVcAttestation = {
format: AttestationFormat.SD_JWT_VC,
vct: "urn:eu.europa.ec.eudi:pid:1",
attestationDef: PHOTO_ID_ATTESTATION,
attributePath: (attribute: DataElement) => { return sdJwtVcAttributePath(attribute, AttestationType.PHOTO_ID) }
}

function msoMdocAttributePath(attribute: DataElement, namespace: string): string {
return '$[\'' + namespace + '\'][\'' + attribute.identifier + '\']'
}

function sdJwtVcAttributePath(attribute: DataElement, attestationType: AttestationType): string {
let resolvedAttribute = attribute.identifier
if (attestationType === AttestationType.PID) {
let mappedAttribute = PID_SD_JWT_VC_ATTRIBUTE_MAP[attribute.identifier];
resolvedAttribute = mappedAttribute ? mappedAttribute : attribute.identifier;
}
return '$.' + resolvedAttribute;
}

export const PID_SD_JWT_VC_ATTRIBUTE_MAP: { [id: string]: string } = {
"birth_date": "birthdate",
"age_over_18": "age_equal_or_over.18",
"age_over_NN": "age_equal_or_over.NN",
"family_name_birth": "birth_family_name",
"given_name_birth": "birth_given_name",
"birth_place": "place_of_birth.locality",
"birth_country": "place_of_birth.country",
"birth_state": "place_of_birth.region",
"birth_city": "place_of_birth.locality",
"resident_address": "address.formatted",
"resident_country": "address.country",
"resident_state": "address.region",
"resident_city": "address.locality",
"resident_postal_code": "address.postal_code",
"resident_street": "address.street_address",
"resident_house_number": "address.house_number",
"gender": "gender",
"nationality": "nationalities",
"issuance_date": "iat",
"expiry_date": "exp"
}


export const MSO_MDOC_ATTESTATIONS: { [id: string]: MsoMdocAttestation } = {
"pid": PID_MSO_MDOC,
"mdl": MDL_MSO_MDOC,
"photo_id": PHOTO_ID_MSO_MDOC,
"age_over_18": AGE_OVER_18_MSO_MDOC,
}

export const ATTESTATIONS_BY_TYPE: { [id: string]: Attestation[] } = {
"pid": [PID_MSO_MDOC, PID_SD_JWT_VC],
"mdl": [MDL_MSO_MDOC, MDL_SD_JWT_VC],
"photo_id": [PHOTO_ID_MSO_MDOC, PHOTO_ID_SD_JWT_VC],
"age_over_18": [AGE_OVER_18_MSO_MDOC, AGE_OVER_18_SD_JWT_VC],
}

export const ATTESTATIONS_BY_FORMAT: { [id: string]: Attestation[] } = {
"mso_mdoc": [PID_MSO_MDOC, MDL_MSO_MDOC, PHOTO_ID_MSO_MDOC, AGE_OVER_18_MSO_MDOC],
"vc+sd-jwt": [PID_SD_JWT_VC, MDL_SD_JWT_VC, PHOTO_ID_SD_JWT_VC, AGE_OVER_18_SD_JWT_VC]
}

export const getAttestationByFormatAndType =
(type: AttestationType, format: AttestationFormat): Attestation | null => {
let filtered = ATTESTATIONS_BY_FORMAT[format as string].filter((attestation: Attestation) =>
attestation.attestationDef.type === type
);
return filtered ? filtered[0] : null;
}
37 changes: 0 additions & 37 deletions src/app/core/data/MsoMdocDocuments.ts

This file was deleted.

3 changes: 2 additions & 1 deletion src/app/core/models/FormSelectableField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import {FieldConstraint} from "@core/models/presentation/FieldConstraint";
export type FormSelectableField = {
id: number,
label: string,
value: FieldConstraint
value: FieldConstraint,
visible?: boolean
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {AttestationType} from "@core/models/attestation/AttestationType";

export type Attestation = {
export type AttestationDefinition = {
type: AttestationType,
name: string,
dataSet: DataElement[]
Expand Down
19 changes: 19 additions & 0 deletions src/app/core/models/attestation/Attestations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {AttestationDefinition, DataElement} from "@core/models/attestation/AttestationDefinition";
import {AttestationFormat} from "@core/models/attestation/AttestationFormat";

export type Attestation = MsoMdocAttestation | SdJwtVcAttestation;

export type MsoMdocAttestation = {
format: AttestationFormat.MSO_MDOC,
doctype: string,
namespace: string,
attestationDef: AttestationDefinition,
attributePath: (attribute: DataElement) => string,
}

export type SdJwtVcAttestation = {
format: AttestationFormat.SD_JWT_VC,
vct: string,
attestationDef: AttestationDefinition
attributePath: (attribute: DataElement) => string,
}
7 changes: 0 additions & 7 deletions src/app/core/models/attestation/MsoMdocAttestation.ts

This file was deleted.

3 changes: 2 additions & 1 deletion src/app/core/models/presentation/FieldConstraint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export type FieldConstraint = {

export type Filter = {
type: string,
contains: any
contains?: any,
const?: string
}
4 changes: 4 additions & 0 deletions src/app/core/models/presentation/InputDescriptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ export type Format = {
},
mso_mdoc?: {
alg: string[]
},
"vc+sd-jwt"?: {
"sd-jwt_alg_values": string[],
"kb-jwt_alg_values": string[]
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {KeyValue} from "@angular/common";
import {AttestationFormat} from "@core/models/attestation/AttestationFormat";

export type SharedAttestation = Single | Enveloped
export type PresentedAttestation = Single | Enveloped

export type Single = {
kind: 'single',
Expand Down
31 changes: 0 additions & 31 deletions src/app/core/services/attestation-selectable-model.service.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/app/core/services/decoders/AttestationDecoder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {AttestationFormat} from "@core/models/attestation/AttestationFormat";
import {SharedAttestation} from "@core/models/presentation/SharedAttestation";
import {PresentedAttestation} from "@core/models/presentation/PresentedAttestation";

export interface AttestationDecoder {
supports(format: AttestationFormat): boolean;
decode(attestation: string): SharedAttestation
decode(attestation: string): PresentedAttestation
}
4 changes: 2 additions & 2 deletions src/app/core/services/decoders/JwtVcJsonAttestationDecoder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Injectable} from "@angular/core";
import {AttestationDecoder} from "@core/services/decoders/AttestationDecoder";
import {SharedAttestation, Single} from "@core/models/presentation/SharedAttestation";
import {PresentedAttestation, Single} from "@core/models/presentation/PresentedAttestation";
import {AttestationFormat} from "@core/models/attestation/AttestationFormat";
import {JWTService} from "@core/services/jwt.service";
import {KeyValue} from "@angular/common";
Expand All @@ -23,7 +23,7 @@ export class JwtVcJsonAttestationDecoder implements AttestationDecoder {
return format === AttestationFormat.JWT_VC_JSON;
}

decode(attestation: string): SharedAttestation {
decode(attestation: string): PresentedAttestation {
let vp = this.jWTService.decodeToObject(attestation);
let sharedCredentials = this.unWrapCredentials(vp)

Expand Down
4 changes: 2 additions & 2 deletions src/app/core/services/decoders/MsoMdocAttestationDecoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {AttestationFormat} from "@core/models/attestation/AttestationFormat";
import {decode} from "cbor-x";
import {Buffer} from 'buffer';

import {SharedAttestation, Single} from "@core/models/presentation/SharedAttestation";
import {PresentedAttestation, Single} from "@core/models/presentation/PresentedAttestation";
import {KeyValue} from "@angular/common";
import {elementAsString} from "@core/services/decoders/DecodingUtils";

Expand All @@ -17,7 +17,7 @@ export class MsoMdocAttestationDecoder implements AttestationDecoder {
return format === AttestationFormat.MSO_MDOC;
}

decode(attestation: string): SharedAttestation {
decode(attestation: string): PresentedAttestation {
const buffer = this.decodeBase64OrHex(attestation);
const decodedData = this.decodeCborData(buffer);
if (decodedData.documents.length === 1) {
Expand Down
Loading

0 comments on commit be89f19

Please sign in to comment.