@pagopa/io-react-native-wallet 2.1.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/lib/commonjs/credential/index.js +3 -1
- package/lib/commonjs/credential/index.js.map +1 -1
- package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js +82 -58
- package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
- package/lib/commonjs/credential/offer/01-start-flow.js +75 -0
- package/lib/commonjs/credential/offer/01-start-flow.js.map +1 -0
- package/lib/commonjs/credential/offer/02-fetch-credential-offer.js +45 -0
- package/lib/commonjs/credential/offer/02-fetch-credential-offer.js.map +1 -0
- package/lib/commonjs/credential/offer/README.md +174 -0
- package/lib/commonjs/credential/offer/errors.js +22 -0
- package/lib/commonjs/credential/offer/errors.js.map +1 -0
- package/lib/commonjs/credential/offer/index.js +25 -0
- package/lib/commonjs/credential/offer/index.js.map +1 -0
- package/lib/commonjs/credential/offer/types.js +51 -0
- package/lib/commonjs/credential/offer/types.js.map +1 -0
- package/lib/commonjs/credential/presentation/01-start-flow.js +1 -1
- package/lib/commonjs/credentials-catalogue/README.md +15 -0
- package/lib/commonjs/credentials-catalogue/fetch-and-parse-catalogue.js +42 -0
- package/lib/commonjs/credentials-catalogue/fetch-and-parse-catalogue.js.map +1 -0
- package/lib/commonjs/credentials-catalogue/index.js +13 -0
- package/lib/commonjs/credentials-catalogue/index.js.map +1 -0
- package/lib/commonjs/credentials-catalogue/types.js +99 -0
- package/lib/commonjs/credentials-catalogue/types.js.map +1 -0
- package/lib/commonjs/index.js +5 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/mdoc/index.js +15 -0
- package/lib/commonjs/mdoc/index.js.map +1 -1
- package/lib/commonjs/mdoc/utils.js +37 -1
- package/lib/commonjs/mdoc/utils.js.map +1 -1
- package/lib/commonjs/utils/nestedProperty.js +21 -10
- package/lib/commonjs/utils/nestedProperty.js.map +1 -1
- package/lib/commonjs/utils/zod.js +28 -0
- package/lib/commonjs/utils/zod.js.map +1 -0
- package/lib/module/credential/index.js +2 -1
- package/lib/module/credential/index.js.map +1 -1
- package/lib/module/credential/issuance/07-verify-and-parse-credential.js +83 -59
- package/lib/module/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
- package/lib/module/credential/offer/01-start-flow.js +66 -0
- package/lib/module/credential/offer/01-start-flow.js.map +1 -0
- package/lib/module/credential/offer/02-fetch-credential-offer.js +38 -0
- package/lib/module/credential/offer/02-fetch-credential-offer.js.map +1 -0
- package/lib/module/credential/offer/README.md +174 -0
- package/lib/module/credential/offer/errors.js +14 -0
- package/lib/module/credential/offer/errors.js.map +1 -0
- package/lib/module/credential/offer/index.js +5 -0
- package/lib/module/credential/offer/index.js.map +1 -0
- package/lib/module/credential/offer/types.js +41 -0
- package/lib/module/credential/offer/types.js.map +1 -0
- package/lib/module/credential/presentation/01-start-flow.js +1 -1
- package/lib/module/credentials-catalogue/README.md +15 -0
- package/lib/module/credentials-catalogue/fetch-and-parse-catalogue.js +35 -0
- package/lib/module/credentials-catalogue/fetch-and-parse-catalogue.js.map +1 -0
- package/lib/module/credentials-catalogue/index.js +2 -0
- package/lib/module/credentials-catalogue/index.js.map +1 -0
- package/lib/module/credentials-catalogue/types.js +89 -0
- package/lib/module/credentials-catalogue/types.js.map +1 -0
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/mdoc/index.js +1 -0
- package/lib/module/mdoc/index.js.map +1 -1
- package/lib/module/mdoc/utils.js +35 -0
- package/lib/module/mdoc/utils.js.map +1 -1
- package/lib/module/utils/nestedProperty.js +21 -10
- package/lib/module/utils/nestedProperty.js.map +1 -1
- package/lib/module/utils/zod.js +20 -0
- package/lib/module/utils/zod.js.map +1 -0
- package/lib/typescript/credential/index.d.ts +2 -1
- package/lib/typescript/credential/index.d.ts.map +1 -1
- package/lib/typescript/credential/issuance/01-start-flow.d.ts +1 -1
- package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts.map +1 -1
- package/lib/typescript/credential/offer/01-start-flow.d.ts +172 -0
- package/lib/typescript/credential/offer/01-start-flow.d.ts.map +1 -0
- package/lib/typescript/credential/offer/02-fetch-credential-offer.d.ts +20 -0
- package/lib/typescript/credential/offer/02-fetch-credential-offer.d.ts.map +1 -0
- package/lib/typescript/credential/offer/errors.d.ts +10 -0
- package/lib/typescript/credential/offer/errors.d.ts.map +1 -0
- package/lib/typescript/credential/offer/index.d.ts +7 -0
- package/lib/typescript/credential/offer/index.d.ts.map +1 -0
- package/lib/typescript/credential/offer/types.d.ts +264 -0
- package/lib/typescript/credential/offer/types.d.ts.map +1 -0
- package/lib/typescript/credential/presentation/01-start-flow.d.ts +1 -1
- package/lib/typescript/credentials-catalogue/fetch-and-parse-catalogue.d.ts +15 -0
- package/lib/typescript/credentials-catalogue/fetch-and-parse-catalogue.d.ts.map +1 -0
- package/lib/typescript/credentials-catalogue/index.d.ts +3 -0
- package/lib/typescript/credentials-catalogue/index.d.ts.map +1 -0
- package/lib/typescript/credentials-catalogue/types.d.ts +844 -0
- package/lib/typescript/credentials-catalogue/types.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/mdoc/index.d.ts +1 -0
- package/lib/typescript/mdoc/index.d.ts.map +1 -1
- package/lib/typescript/mdoc/utils.d.ts +50 -0
- package/lib/typescript/mdoc/utils.d.ts.map +1 -1
- package/lib/typescript/utils/nestedProperty.d.ts +2 -1
- package/lib/typescript/utils/nestedProperty.d.ts.map +1 -1
- package/lib/typescript/utils/zod.d.ts +15 -0
- package/lib/typescript/utils/zod.d.ts.map +1 -0
- package/package.json +21 -2
- package/src/credential/index.ts +2 -1
- package/src/credential/issuance/01-start-flow.ts +1 -1
- package/src/credential/issuance/07-verify-and-parse-credential.ts +60 -26
- package/src/credential/offer/01-start-flow.ts +89 -0
- package/src/credential/offer/02-fetch-credential-offer.ts +54 -0
- package/src/credential/offer/README.md +174 -0
- package/src/credential/offer/errors.ts +17 -0
- package/src/credential/offer/index.ts +16 -0
- package/src/credential/offer/types.ts +59 -0
- package/src/credential/presentation/01-start-flow.ts +1 -1
- package/src/credentials-catalogue/README.md +15 -0
- package/src/credentials-catalogue/fetch-and-parse-catalogue.ts +54 -0
- package/src/credentials-catalogue/index.ts +2 -0
- package/src/credentials-catalogue/types.ts +97 -0
- package/src/index.ts +4 -0
- package/src/mdoc/index.ts +1 -0
- package/src/mdoc/utils.ts +43 -0
- package/src/utils/nestedProperty.ts +35 -10
- package/src/utils/zod.ts +28 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Credential Offer
|
|
2
|
+
|
|
3
|
+
This flow handles the initial step of credential issuance by processing Credential Offers from Credential Issuers. The Credential Offer contains information about what credentials are available and how they can be obtained. Each step in the flow is imported from the related file which is named with a sequential number.
|
|
4
|
+
|
|
5
|
+
A Credential Offer can be received by the Wallet in two ways: **by value** (complete offer embedded in the URL) or **by reference** (URL pointing to the offer endpoint). The offer specifies which credentials are available and what authorization flows are supported by the issuer.
|
|
6
|
+
|
|
7
|
+
The implementation follows the [OpenID for Verifiable Credential Issuance 1.0](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html#name-credential-offer-endpoint) specification and supports both Authorization Code flow and Pre-Authorized Code flow.
|
|
8
|
+
|
|
9
|
+
## Sequence Diagram
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
sequenceDiagram
|
|
13
|
+
autonumber
|
|
14
|
+
participant U as User
|
|
15
|
+
participant W as Wallet
|
|
16
|
+
participant CI as Credential Issuer
|
|
17
|
+
|
|
18
|
+
CI->>U: QR Code / Deep Link with Credential Offer
|
|
19
|
+
U->>W: Scan QR / Click Link
|
|
20
|
+
W->>W: startFlowFromQR: Parse offer parameters
|
|
21
|
+
alt Credential Offer by Reference
|
|
22
|
+
W->>CI: fetchCredentialOffer: Fetch offer from URI
|
|
23
|
+
CI->>W: Return Credential Offer JSON
|
|
24
|
+
end
|
|
25
|
+
W->>W: Validate Credential Offer schema
|
|
26
|
+
W->>W: Determine available grant types
|
|
27
|
+
Note over W: Flow continues with credential issuance
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Grant Types
|
|
31
|
+
|
|
32
|
+
The Credential Offer supports two OAuth 2.0 grant types that determine how authorization is handled:
|
|
33
|
+
|
|
34
|
+
### Authorization Code Flow
|
|
35
|
+
|
|
36
|
+
Used for interactive flows where user authentication and consent are required at the Authorization Server.
|
|
37
|
+
|
|
38
|
+
- **`issuer_state`** (optional): Binds the authorization request to a specific issuer context
|
|
39
|
+
- **`authorization_server`** (optional): Identifies which authorization server to use when multiple are available
|
|
40
|
+
|
|
41
|
+
### Pre-Authorized Code Flow
|
|
42
|
+
|
|
43
|
+
Used when the user has already been authenticated and authorized out-of-band. The issuer provides a pre-authorized code that can be exchanged directly for credentials.
|
|
44
|
+
|
|
45
|
+
- **`pre-authorized_code`**: Short-lived single-use authorization code
|
|
46
|
+
- **`tx_code`** (optional): Additional transaction code requirements for security
|
|
47
|
+
- **`authorization_server`** (optional): Identifies which authorization server to use
|
|
48
|
+
|
|
49
|
+
## Transaction Code Requirements
|
|
50
|
+
|
|
51
|
+
When a transaction code is required for Pre-Authorized Code flow, the following parameters control the user experience:
|
|
52
|
+
|
|
53
|
+
| Parameter | Type | Description |
|
|
54
|
+
| ------------- | ----------------------- | ---------------------------------------------------- |
|
|
55
|
+
| `input_mode` | `"numeric"` \| `"text"` | Character set for the code (default: `"numeric"`) |
|
|
56
|
+
| `length` | number | Expected code length to optimize input UI |
|
|
57
|
+
| `description` | string | User guidance (max 300 chars) for obtaining the code |
|
|
58
|
+
|
|
59
|
+
## Credential Offer Transmission
|
|
60
|
+
|
|
61
|
+
### By Value
|
|
62
|
+
|
|
63
|
+
The complete Credential Offer is embedded in the URL parameter:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
openid-credential-offer://?credential_offer=%7B%22credential_issuer%22...
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### By Reference
|
|
70
|
+
|
|
71
|
+
A URL points to an endpoint serving the Credential Offer:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fserver.example.com%2Foffer
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
When using by reference, the Wallet fetches the offer via HTTP GET with `Accept: application/json`.
|
|
78
|
+
|
|
79
|
+
## Mapped Results
|
|
80
|
+
|
|
81
|
+
The following errors are mapped during credential offer processing:
|
|
82
|
+
|
|
83
|
+
| Error | Description |
|
|
84
|
+
| ----------------------------- | ---------------------------------------------------------------------------------- |
|
|
85
|
+
| `InvalidQRCodeError` | The QR code format is invalid or doesn't contain valid credential offer parameters |
|
|
86
|
+
| `InvalidCredentialOfferError` | The credential offer schema validation failed or contains invalid data |
|
|
87
|
+
|
|
88
|
+
## Examples
|
|
89
|
+
|
|
90
|
+
<details>
|
|
91
|
+
<summary>Credential Offer processing flow</summary>
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
// Parse QR code or deep link
|
|
95
|
+
const qrCode =
|
|
96
|
+
"openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fissuer.example.com%2Foffer";
|
|
97
|
+
const { credential_offer_uri } = startFlowFromQR(qrCode);
|
|
98
|
+
|
|
99
|
+
// Fetch the credential offer if by reference
|
|
100
|
+
const offer = await fetchCredentialOffer(credential_offer_uri, { appFetch });
|
|
101
|
+
|
|
102
|
+
console.log(offer);
|
|
103
|
+
// {
|
|
104
|
+
// credential_issuer: "https://issuer.example.com",
|
|
105
|
+
// credential_configuration_ids: ["UniversityDegree", "DriverLicense"],
|
|
106
|
+
// grants: {
|
|
107
|
+
// authorization_code: {
|
|
108
|
+
// issuer_state: "xyz123"
|
|
109
|
+
// },
|
|
110
|
+
// "urn:ietf:params:oauth:grant-type:pre-authorized_code": {
|
|
111
|
+
// "pre-authorized_code": "SplxlOBeZQQYbYS6WxSbIA",
|
|
112
|
+
// tx_code: {
|
|
113
|
+
// length: 6,
|
|
114
|
+
// input_mode: "numeric",
|
|
115
|
+
// description: "Enter the code sent to your email"
|
|
116
|
+
// }
|
|
117
|
+
// }
|
|
118
|
+
// }
|
|
119
|
+
// }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
<details>
|
|
125
|
+
<summary>Pre-Authorized Code with Transaction Code</summary>
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const offer: CredentialOffer = {
|
|
129
|
+
credential_issuer: "https://university.example.edu",
|
|
130
|
+
credential_configuration_ids: ["DiplomaCredential"],
|
|
131
|
+
grants: {
|
|
132
|
+
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
|
|
133
|
+
"pre-authorized_code": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
|
|
134
|
+
tx_code: {
|
|
135
|
+
length: 4,
|
|
136
|
+
input_mode: "numeric",
|
|
137
|
+
description: "Check your email for the verification code",
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// The user would need to:
|
|
144
|
+
// 1. Check their email for a 4-digit numeric code
|
|
145
|
+
// 2. Enter it in the wallet when prompted
|
|
146
|
+
// 3. The wallet uses both pre-authorized_code and tx_code in the token request
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
</details>
|
|
150
|
+
|
|
151
|
+
<details>
|
|
152
|
+
<summary>Authorization Code Flow</summary>
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
const offer: CredentialOffer = {
|
|
156
|
+
credential_issuer: "https://dmv.example.gov",
|
|
157
|
+
credential_configuration_ids: ["org.iso.18013.5.1.mDL"],
|
|
158
|
+
grants: {
|
|
159
|
+
authorization_code: {
|
|
160
|
+
issuer_state: "af0ifjsldkj",
|
|
161
|
+
authorization_server: "https://auth.dmv.example.gov",
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// This would lead to:
|
|
167
|
+
// 1. User authentication at the authorization server
|
|
168
|
+
// 2. User consent for credential issuance
|
|
169
|
+
// 3. Authorization code returned to wallet
|
|
170
|
+
// 4. Wallet exchanges code for access token
|
|
171
|
+
// 5. Wallet uses access token to request credential
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
</details>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IoWalletError } from "../../utils/errors";
|
|
2
|
+
export class InvalidCredentialOfferError extends IoWalletError {
|
|
3
|
+
code = "ERR_INVALID_CREDENTIAL_OFFER";
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export class InvalidQRCodeError extends IoWalletError {
|
|
9
|
+
code = "ERR_INVALID_QR_CODE";
|
|
10
|
+
constructor(message) {
|
|
11
|
+
super(message);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["IoWalletError","InvalidCredentialOfferError","code","constructor","message","InvalidQRCodeError"],"sourceRoot":"../../../../src","sources":["credential/offer/errors.ts"],"mappings":"AAAA,SAASA,aAAa,QAAQ,oBAAoB;AAElD,OAAO,MAAMC,2BAA2B,SAASD,aAAa,CAAC;EAC7DE,IAAI,GAAG,8BAA8B;EAErCC,WAAWA,CAACC,OAAgB,EAAE;IAC5B,KAAK,CAACA,OAAO,CAAC;EAChB;AACF;AAEA,OAAO,MAAMC,kBAAkB,SAASL,aAAa,CAAC;EACpDE,IAAI,GAAG,qBAAqB;EAE5BC,WAAWA,CAACC,OAAgB,EAAE;IAC5B,KAAK,CAACA,OAAO,CAAC;EAChB;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["startFlowFromQR","fetchCredentialOffer","Errors"],"sourceRoot":"../../../../src","sources":["credential/offer/index.ts"],"mappings":"AAAA,SAASA,eAAe,QAAwB,iBAAiB;AACjE,SACEC,oBAAoB,QAEf,6BAA6B;AACpC,OAAO,KAAKC,MAAM,MAAM,UAAU;AASlC,SAASA,MAAM,EAAED,oBAAoB,EAAED,eAAe"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OAuth 2.0 Authorization Code flow parameters.
|
|
5
|
+
*/
|
|
6
|
+
export const AuthorizationCodeGrantSchema = z.object({
|
|
7
|
+
issuer_state: z.string().optional(),
|
|
8
|
+
authorization_server: z.string().url().optional()
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Transaction Code requirements for Pre-Authorized Code flow.
|
|
12
|
+
*/
|
|
13
|
+
export const TransactionCodeSchema = z.object({
|
|
14
|
+
input_mode: z.enum(["numeric", "text"]).optional(),
|
|
15
|
+
length: z.number().int().positive().optional(),
|
|
16
|
+
description: z.string().max(300).optional()
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Pre-Authorized Code flow parameters.
|
|
20
|
+
*/
|
|
21
|
+
export const PreAuthorizedCodeGrantSchema = z.object({
|
|
22
|
+
"pre-authorized_code": z.string(),
|
|
23
|
+
tx_code: TransactionCodeSchema.optional(),
|
|
24
|
+
authorization_server: z.string().url().optional()
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Supported grant types for Credential Offer.
|
|
28
|
+
*/
|
|
29
|
+
export const GrantsSchema = z.object({
|
|
30
|
+
authorization_code: AuthorizationCodeGrantSchema.optional(),
|
|
31
|
+
"urn:ietf:params:oauth:grant-type:pre-authorized_code": PreAuthorizedCodeGrantSchema.optional()
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* Credential Offer object as defined in OpenID4VCI Section 4.1.1.
|
|
35
|
+
*/
|
|
36
|
+
export const CredentialOfferSchema = z.object({
|
|
37
|
+
credential_issuer: z.string().url(),
|
|
38
|
+
credential_configuration_ids: z.array(z.string()).min(1),
|
|
39
|
+
grants: GrantsSchema.optional()
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["z","AuthorizationCodeGrantSchema","object","issuer_state","string","optional","authorization_server","url","TransactionCodeSchema","input_mode","enum","length","number","int","positive","description","max","PreAuthorizedCodeGrantSchema","tx_code","GrantsSchema","authorization_code","CredentialOfferSchema","credential_issuer","credential_configuration_ids","array","min","grants"],"sourceRoot":"../../../../src","sources":["credential/offer/types.ts"],"mappings":"AAAA,SAASA,CAAC,QAAQ,KAAK;;AAEvB;AACA;AACA;AACA,OAAO,MAAMC,4BAA4B,GAAGD,CAAC,CAACE,MAAM,CAAC;EACnDC,YAAY,EAAEH,CAAC,CAACI,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,CAAC;EACnCC,oBAAoB,EAAEN,CAAC,CAACI,MAAM,CAAC,CAAC,CAACG,GAAG,CAAC,CAAC,CAACF,QAAQ,CAAC;AAClD,CAAC,CAAC;AAMF;AACA;AACA;AACA,OAAO,MAAMG,qBAAqB,GAAGR,CAAC,CAACE,MAAM,CAAC;EAC5CO,UAAU,EAAET,CAAC,CAACU,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAACL,QAAQ,CAAC,CAAC;EAClDM,MAAM,EAAEX,CAAC,CAACY,MAAM,CAAC,CAAC,CAACC,GAAG,CAAC,CAAC,CAACC,QAAQ,CAAC,CAAC,CAACT,QAAQ,CAAC,CAAC;EAC9CU,WAAW,EAAEf,CAAC,CAACI,MAAM,CAAC,CAAC,CAACY,GAAG,CAAC,GAAG,CAAC,CAACX,QAAQ,CAAC;AAC5C,CAAC,CAAC;AAIF;AACA;AACA;AACA,OAAO,MAAMY,4BAA4B,GAAGjB,CAAC,CAACE,MAAM,CAAC;EACnD,qBAAqB,EAAEF,CAAC,CAACI,MAAM,CAAC,CAAC;EACjCc,OAAO,EAAEV,qBAAqB,CAACH,QAAQ,CAAC,CAAC;EACzCC,oBAAoB,EAAEN,CAAC,CAACI,MAAM,CAAC,CAAC,CAACG,GAAG,CAAC,CAAC,CAACF,QAAQ,CAAC;AAClD,CAAC,CAAC;AAMF;AACA;AACA;AACA,OAAO,MAAMc,YAAY,GAAGnB,CAAC,CAACE,MAAM,CAAC;EACnCkB,kBAAkB,EAAEnB,4BAA4B,CAACI,QAAQ,CAAC,CAAC;EAC3D,sDAAsD,EACpDY,4BAA4B,CAACZ,QAAQ,CAAC;AAC1C,CAAC,CAAC;AAIF;AACA;AACA;AACA,OAAO,MAAMgB,qBAAqB,GAAGrB,CAAC,CAACE,MAAM,CAAC;EAC5CoB,iBAAiB,EAAEtB,CAAC,CAACI,MAAM,CAAC,CAAC,CAACG,GAAG,CAAC,CAAC;EACnCgB,4BAA4B,EAAEvB,CAAC,CAACwB,KAAK,CAACxB,CAAC,CAACI,MAAM,CAAC,CAAC,CAAC,CAACqB,GAAG,CAAC,CAAC,CAAC;EACxDC,MAAM,EAAEP,YAAY,CAACd,QAAQ,CAAC;AAChC,CAAC,CAAC"}
|
|
@@ -9,7 +9,7 @@ const PresentationParams = z.object({
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* The beginning of the presentation flow.
|
|
12
|
-
* To be implemented
|
|
12
|
+
* To be implemented according to the user touchpoint
|
|
13
13
|
*
|
|
14
14
|
* @param params Presentation parameters, depending on the starting touchpoint
|
|
15
15
|
* @returns The url for the Relying Party to connect with
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Digital Credentials Catalogue
|
|
2
|
+
|
|
3
|
+
Module that manages the [**Digital Credentials Catalogue**](https://italia.github.io/eid-wallet-it-docs/releases/1.1.0/en/registry-catalogue.html) published by the Trust Anchor.
|
|
4
|
+
|
|
5
|
+
The module allows:
|
|
6
|
+
- Fetching, verifying and parsing the catalogue's JWT.
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
// Fetch the catalogue
|
|
12
|
+
const TRUST_ANCHOR_BASE_URL = "https://pre.ta.wallet.ipzs.it";
|
|
13
|
+
const credentialsCatalogue =
|
|
14
|
+
await CredentialsCatalogue.fetchAndParseCatalogue(TRUST_ANCHOR_BASE_URL);
|
|
15
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { decode as decodeJwt, verify } from "@pagopa/io-react-native-jwt";
|
|
2
|
+
import { hasStatusOrThrow } from "../utils/misc";
|
|
3
|
+
import { IoWalletError } from "../utils/errors";
|
|
4
|
+
import { DigitalCredentialsCatalogue } from "./types";
|
|
5
|
+
import { getTrustAnchorEntityConfiguration } from "../trust/build-chain";
|
|
6
|
+
/**
|
|
7
|
+
* Fetch and parse the Digital Credential Catalogue from the Trust Anchor.
|
|
8
|
+
* The catalogue's JWT signature is verified against the Trust Anchor's JWKs.
|
|
9
|
+
*
|
|
10
|
+
* @param trustAnchorUrl Base URL of the Trust Anchor
|
|
11
|
+
* @param context.appFetch (optional) fetch API implementation. Default: built-in fetch
|
|
12
|
+
* @returns The Digital Credential Catalogue payload
|
|
13
|
+
*/
|
|
14
|
+
export const fetchAndParseCatalogue = async function (trustAnchorBaseUrl) {
|
|
15
|
+
let {
|
|
16
|
+
appFetch = fetch
|
|
17
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
18
|
+
const trustAnchorConfig = await getTrustAnchorEntityConfiguration(trustAnchorBaseUrl);
|
|
19
|
+
const responseText = await appFetch(`${trustAnchorConfig.payload.sub}/.well-known/credential-catalogue`, {
|
|
20
|
+
method: "GET"
|
|
21
|
+
}).then(hasStatusOrThrow(200)).then(res => res.text());
|
|
22
|
+
const responseJwt = decodeJwt(responseText);
|
|
23
|
+
const catalogueKid = responseJwt.protectedHeader.kid;
|
|
24
|
+
const trustAnchorJwk = trustAnchorConfig.payload.jwks.keys.find(jwk => jwk.kid === catalogueKid);
|
|
25
|
+
if (!trustAnchorJwk) {
|
|
26
|
+
throw new IoWalletError(`Could not find JWK with kid ${catalogueKid} in Trust Anchor's Entity Configuration`);
|
|
27
|
+
}
|
|
28
|
+
await verify(responseText, trustAnchorJwk);
|
|
29
|
+
const parsedDigitalCredentialsCatalogue = DigitalCredentialsCatalogue.parse({
|
|
30
|
+
header: responseJwt.protectedHeader,
|
|
31
|
+
payload: responseJwt.payload
|
|
32
|
+
});
|
|
33
|
+
return parsedDigitalCredentialsCatalogue.payload;
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=fetch-and-parse-catalogue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["decode","decodeJwt","verify","hasStatusOrThrow","IoWalletError","DigitalCredentialsCatalogue","getTrustAnchorEntityConfiguration","fetchAndParseCatalogue","trustAnchorBaseUrl","appFetch","fetch","arguments","length","undefined","trustAnchorConfig","responseText","payload","sub","method","then","res","text","responseJwt","catalogueKid","protectedHeader","kid","trustAnchorJwk","jwks","keys","find","jwk","parsedDigitalCredentialsCatalogue","parse","header"],"sourceRoot":"../../../src","sources":["credentials-catalogue/fetch-and-parse-catalogue.ts"],"mappings":"AAAA,SAASA,MAAM,IAAIC,SAAS,EAAEC,MAAM,QAAQ,6BAA6B;AACzE,SAASC,gBAAgB,QAAQ,eAAe;AAChD,SAASC,aAAa,QAAQ,iBAAiB;AAC/C,SAASC,2BAA2B,QAAQ,SAAS;AACrD,SAASC,iCAAiC,QAAQ,sBAAsB;AAMxE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,sBAAsB,GAAG,eAAAA,CACpCC,kBAA0B,EAE0B;EAAA,IADpD;IAAEC,QAAQ,GAAGC;EAA2B,CAAC,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC,CAAC;EAE9C,MAAMG,iBAAiB,GACrB,MAAMR,iCAAiC,CAACE,kBAAkB,CAAC;EAE7D,MAAMO,YAAY,GAAG,MAAMN,QAAQ,CAChC,GAAEK,iBAAiB,CAACE,OAAO,CAACC,GAAI,mCAAkC,EACnE;IAAEC,MAAM,EAAE;EAAM,CAClB,CAAC,CACEC,IAAI,CAAChB,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAC3BgB,IAAI,CAAEC,GAAG,IAAKA,GAAG,CAACC,IAAI,CAAC,CAAC,CAAC;EAE5B,MAAMC,WAAW,GAAGrB,SAAS,CAACc,YAAY,CAAC;EAC3C,MAAMQ,YAAY,GAAGD,WAAW,CAACE,eAAe,CAACC,GAAG;EAEpD,MAAMC,cAAc,GAAGZ,iBAAiB,CAACE,OAAO,CAACW,IAAI,CAACC,IAAI,CAACC,IAAI,CAC5DC,GAAG,IAAKA,GAAG,CAACL,GAAG,KAAKF,YACvB,CAAC;EAED,IAAI,CAACG,cAAc,EAAE;IACnB,MAAM,IAAItB,aAAa,CACpB,+BAA8BmB,YAAa,yCAC9C,CAAC;EACH;EAEA,MAAMrB,MAAM,CAACa,YAAY,EAAEW,cAAc,CAAC;EAE1C,MAAMK,iCAAiC,GAAG1B,2BAA2B,CAAC2B,KAAK,CAAC;IAC1EC,MAAM,EAAEX,WAAW,CAACE,eAAe;IACnCR,OAAO,EAAEM,WAAW,CAACN;EACvB,CAAC,CAAC;EAEF,OAAOe,iCAAiC,CAACf,OAAO;AAClD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["fetchAndParseCatalogue"],"sourceRoot":"../../../src","sources":["credentials-catalogue/index.ts"],"mappings":"AAAA,SAASA,sBAAsB,QAAQ,6BAA6B"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { UnixTime } from "../sd-jwt/types";
|
|
3
|
+
const CredentialPurpose = z.object({
|
|
4
|
+
id: z.string(),
|
|
5
|
+
description: z.string(),
|
|
6
|
+
category: z.string(),
|
|
7
|
+
subcategory: z.string(),
|
|
8
|
+
claims_required: z.array(z.string()),
|
|
9
|
+
claim_recommended: z.array(z.string())
|
|
10
|
+
});
|
|
11
|
+
const CredentialIssuer = z.object({
|
|
12
|
+
id: z.string(),
|
|
13
|
+
organization_name: z.string(),
|
|
14
|
+
organization_code: z.string(),
|
|
15
|
+
organization_country: z.string(),
|
|
16
|
+
contacts: z.array(z.string()).optional(),
|
|
17
|
+
homepage_uri: z.string().optional(),
|
|
18
|
+
logo_uri: z.string().optional(),
|
|
19
|
+
policy_uri: z.string().optional(),
|
|
20
|
+
tos_uri: z.string().optional()
|
|
21
|
+
});
|
|
22
|
+
const AuthenticSource = z.object({
|
|
23
|
+
id: z.string(),
|
|
24
|
+
organization_name: z.string(),
|
|
25
|
+
organization_code: z.string(),
|
|
26
|
+
organization_country: z.string(),
|
|
27
|
+
source_type: z.enum(["public", "private"]),
|
|
28
|
+
contacts: z.array(z.string()).optional(),
|
|
29
|
+
homepage_uri: z.string().optional(),
|
|
30
|
+
logo_uri: z.string().optional(),
|
|
31
|
+
user_information: z.string().optional()
|
|
32
|
+
});
|
|
33
|
+
const CredentialFormat = z.object({
|
|
34
|
+
configuration_id: z.string(),
|
|
35
|
+
format: z.enum(["dc+sd-jwt", "mso_mdoc"]),
|
|
36
|
+
vct: z.string().url().optional(),
|
|
37
|
+
docType: z.string().optional(),
|
|
38
|
+
schema_uri: z.string().url().optional(),
|
|
39
|
+
"schema_uri#integrity": z.string().optional()
|
|
40
|
+
});
|
|
41
|
+
const Claim = z.object({
|
|
42
|
+
name: z.string(),
|
|
43
|
+
taxonomy_ref: z.string(),
|
|
44
|
+
display_name: z.string()
|
|
45
|
+
});
|
|
46
|
+
export const DigitalCredential = z.object({
|
|
47
|
+
version: z.string(),
|
|
48
|
+
credential_type: z.string(),
|
|
49
|
+
legal_type: z.string(),
|
|
50
|
+
name: z.string(),
|
|
51
|
+
description: z.string(),
|
|
52
|
+
validity_info: z.object({
|
|
53
|
+
max_validity_days: z.number(),
|
|
54
|
+
status_methods: z.array(z.string()),
|
|
55
|
+
allowed_states: z.array(z.string())
|
|
56
|
+
}),
|
|
57
|
+
authentication: z.object({
|
|
58
|
+
user_auth_required: z.boolean(),
|
|
59
|
+
min_loa: z.string(),
|
|
60
|
+
supported_eid_schemes: z.array(z.string())
|
|
61
|
+
}),
|
|
62
|
+
purposes: z.array(CredentialPurpose),
|
|
63
|
+
issuers: z.array(CredentialIssuer),
|
|
64
|
+
authentic_sources: z.array(AuthenticSource),
|
|
65
|
+
formats: z.array(CredentialFormat),
|
|
66
|
+
claims: z.array(Claim)
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The Digital Credentials Catalogue published by the Trust Anchor
|
|
71
|
+
*
|
|
72
|
+
* @version 1.1.0
|
|
73
|
+
* @see https://italia.github.io/eid-wallet-it-docs/releases/1.1.0/en/registry-catalogue.html
|
|
74
|
+
*/
|
|
75
|
+
export const DigitalCredentialsCatalogue = z.object({
|
|
76
|
+
header: z.object({
|
|
77
|
+
typ: z.string(),
|
|
78
|
+
alg: z.string(),
|
|
79
|
+
kid: z.string()
|
|
80
|
+
}),
|
|
81
|
+
payload: z.object({
|
|
82
|
+
catalog_version: z.string(),
|
|
83
|
+
taxonomy_uri: z.string().url(),
|
|
84
|
+
credentials: z.array(DigitalCredential),
|
|
85
|
+
iat: UnixTime,
|
|
86
|
+
exp: UnixTime
|
|
87
|
+
})
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["z","UnixTime","CredentialPurpose","object","id","string","description","category","subcategory","claims_required","array","claim_recommended","CredentialIssuer","organization_name","organization_code","organization_country","contacts","optional","homepage_uri","logo_uri","policy_uri","tos_uri","AuthenticSource","source_type","enum","user_information","CredentialFormat","configuration_id","format","vct","url","docType","schema_uri","Claim","name","taxonomy_ref","display_name","DigitalCredential","version","credential_type","legal_type","validity_info","max_validity_days","number","status_methods","allowed_states","authentication","user_auth_required","boolean","min_loa","supported_eid_schemes","purposes","issuers","authentic_sources","formats","claims","DigitalCredentialsCatalogue","header","typ","alg","kid","payload","catalog_version","taxonomy_uri","credentials","iat","exp"],"sourceRoot":"../../../src","sources":["credentials-catalogue/types.ts"],"mappings":"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"}
|
package/lib/module/index.js
CHANGED
|
@@ -3,8 +3,10 @@ import { fixBase64EncodingOnKey } from "./utils/jwk";
|
|
|
3
3
|
// https://github.com/facebook/react-native/issues/24428
|
|
4
4
|
import "react-native-url-polyfill/auto";
|
|
5
5
|
import * as Credential from "./credential";
|
|
6
|
+
import * as CredentialsCatalogue from "./credentials-catalogue";
|
|
6
7
|
import * as PID from "./pid";
|
|
7
8
|
import * as SdJwt from "./sd-jwt";
|
|
9
|
+
import * as Mdoc from "./mdoc";
|
|
8
10
|
import * as Errors from "./utils/errors";
|
|
9
11
|
import * as WalletInstanceAttestation from "./wallet-instance-attestation";
|
|
10
12
|
import * as Trust from "./trust";
|
|
@@ -12,5 +14,5 @@ import * as WalletInstance from "./wallet-instance";
|
|
|
12
14
|
import * as Logging from "./utils/logging";
|
|
13
15
|
import { AuthorizationDetail, AuthorizationDetails } from "./utils/par";
|
|
14
16
|
import { createCryptoContextFor } from "./utils/crypto";
|
|
15
|
-
export { SdJwt, PID, Credential, WalletInstanceAttestation, WalletInstance, Errors, Trust, createCryptoContextFor, AuthorizationDetail, AuthorizationDetails, fixBase64EncodingOnKey, Logging };
|
|
17
|
+
export { SdJwt, Mdoc, PID, Credential, CredentialsCatalogue, WalletInstanceAttestation, WalletInstance, Errors, Trust, createCryptoContextFor, AuthorizationDetail, AuthorizationDetails, fixBase64EncodingOnKey, Logging };
|
|
16
18
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["fixBase64EncodingOnKey","Credential","PID","SdJwt","Errors","WalletInstanceAttestation","Trust","WalletInstance","Logging","AuthorizationDetail","AuthorizationDetails","createCryptoContextFor"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AACA,SAASA,sBAAsB,QAAQ,aAAa;AACpD;AACA;AACA,OAAO,gCAAgC;AAEvC,OAAO,KAAKC,UAAU,MAAM,cAAc;AAC1C,OAAO,KAAKC,GAAG,MAAM,OAAO;AAC5B,OAAO,KAAKC,KAAK,MAAM,UAAU;AACjC,OAAO,KAAKC,MAAM,MAAM,gBAAgB;AACxC,OAAO,KAAKC,yBAAyB,MAAM,+BAA+B;AAC1E,OAAO,KAAKC,KAAK,MAAM,SAAS;AAChC,OAAO,KAAKC,cAAc,MAAM,mBAAmB;AACnD,OAAO,KAAKC,OAAO,MAAM,iBAAiB;AAC1C,SAASC,mBAAmB,EAAEC,oBAAoB,QAAQ,aAAa;AACvE,SAASC,sBAAsB,QAAQ,gBAAgB;AAGvD,
|
|
1
|
+
{"version":3,"names":["fixBase64EncodingOnKey","Credential","CredentialsCatalogue","PID","SdJwt","Mdoc","Errors","WalletInstanceAttestation","Trust","WalletInstance","Logging","AuthorizationDetail","AuthorizationDetails","createCryptoContextFor"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AACA,SAASA,sBAAsB,QAAQ,aAAa;AACpD;AACA;AACA,OAAO,gCAAgC;AAEvC,OAAO,KAAKC,UAAU,MAAM,cAAc;AAC1C,OAAO,KAAKC,oBAAoB,MAAM,yBAAyB;AAC/D,OAAO,KAAKC,GAAG,MAAM,OAAO;AAC5B,OAAO,KAAKC,KAAK,MAAM,UAAU;AACjC,OAAO,KAAKC,IAAI,MAAM,QAAQ;AAC9B,OAAO,KAAKC,MAAM,MAAM,gBAAgB;AACxC,OAAO,KAAKC,yBAAyB,MAAM,+BAA+B;AAC1E,OAAO,KAAKC,KAAK,MAAM,SAAS;AAChC,OAAO,KAAKC,cAAc,MAAM,mBAAmB;AACnD,OAAO,KAAKC,OAAO,MAAM,iBAAiB;AAC1C,SAASC,mBAAmB,EAAEC,oBAAoB,QAAQ,aAAa;AACvE,SAASC,sBAAsB,QAAQ,gBAAgB;AAGvD,SACET,KAAK,EACLC,IAAI,EACJF,GAAG,EACHF,UAAU,EACVC,oBAAoB,EACpBK,yBAAyB,EACzBE,cAAc,EACdH,MAAM,EACNE,KAAK,EACLK,sBAAsB,EACtBF,mBAAmB,EACnBC,oBAAoB,EACpBZ,sBAAsB,EACtBU,OAAO"}
|
package/lib/module/mdoc/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { verifyCertificateChain } from "@pagopa/io-react-native-crypto";
|
|
|
4
4
|
import { MissingX509CertsError, X509ValidationError } from "../trust/errors";
|
|
5
5
|
import { IoWalletError } from "../utils/errors";
|
|
6
6
|
import { convertBase64DerToPem, getSigninJwkFromCert } from "../utils/crypto";
|
|
7
|
+
export * from "./utils";
|
|
7
8
|
export const verify = async (token, x509CertRoot) => {
|
|
8
9
|
var _issuerSigned$issuerA;
|
|
9
10
|
// get decoded data
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["CBOR","COSE","b64utob64","verifyCertificateChain","MissingX509CertsError","X509ValidationError","IoWalletError","convertBase64DerToPem","getSigninJwkFromCert","verify","token","x509CertRoot","_issuerSigned$issuerA","issuerSigned","decodeIssuerSigned","issuerAuth","unprotectedHeader","x5chain","Array","isArray","length","map","verifyX5chain","coseSign1","rawValue","verifyMdocSignature","options","arguments","undefined","connectTimeout","readTimeout","requireCrl","x509ValidationResult","isValid","validationStatus","errorMessage","x509ValidationStatus","x509ErrorMessage","cert","pemcert","jwk","x","y","signatureCorrect","Error"],"sourceRoot":"../../../src","sources":["mdoc/index.ts"],"mappings":"AAAA,SAASA,IAAI,EAAEC,IAAI,QAAQ,kCAAkC;AAC7D,SAASC,SAAS,QAAQ,WAAW;AACrC,SACEC,sBAAsB,QAIjB,gCAAgC;AACvC,SAASC,qBAAqB,EAAEC,mBAAmB,QAAQ,iBAAiB;AAC5E,SAASC,aAAa,QAAQ,iBAAiB;AAC/C,SAASC,qBAAqB,EAAEC,oBAAoB,QAAQ,iBAAiB;
|
|
1
|
+
{"version":3,"names":["CBOR","COSE","b64utob64","verifyCertificateChain","MissingX509CertsError","X509ValidationError","IoWalletError","convertBase64DerToPem","getSigninJwkFromCert","verify","token","x509CertRoot","_issuerSigned$issuerA","issuerSigned","decodeIssuerSigned","issuerAuth","unprotectedHeader","x5chain","Array","isArray","length","map","verifyX5chain","coseSign1","rawValue","verifyMdocSignature","options","arguments","undefined","connectTimeout","readTimeout","requireCrl","x509ValidationResult","isValid","validationStatus","errorMessage","x509ValidationStatus","x509ErrorMessage","cert","pemcert","jwk","x","y","signatureCorrect","Error"],"sourceRoot":"../../../src","sources":["mdoc/index.ts"],"mappings":"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"}
|
package/lib/module/mdoc/utils.js
CHANGED
|
@@ -1,7 +1,42 @@
|
|
|
1
|
+
import { CBOR } from "@pagopa/io-react-native-iso18013";
|
|
2
|
+
import { Verification } from "../sd-jwt/types";
|
|
3
|
+
import { MDOC_DEFAULT_NAMESPACE } from "./const";
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* @param namespace The mdoc credential `namespace`
|
|
3
7
|
* @param key The claim attribute key
|
|
4
8
|
* @returns A string consisting of the concatenation of the namespace and the claim key, separated by a colon
|
|
5
9
|
*/
|
|
6
10
|
export const getParsedCredentialClaimKey = (namespace, key) => `${namespace}:${key}`;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Extract and validate the `verification` claim from an mdoc parsed credential.
|
|
14
|
+
*
|
|
15
|
+
* This method is **synchronous**, so it requires a credential that was already parsed.
|
|
16
|
+
*
|
|
17
|
+
* @param parsedCredential The parsed mdoc credential
|
|
18
|
+
* @returns The verification claim or undefined if it wasn't found
|
|
19
|
+
*/
|
|
20
|
+
export const getVerificationFromParsedCredential = parsedCredential => {
|
|
21
|
+
var _parsedCredential$ver;
|
|
22
|
+
const verificationKey = getParsedCredentialClaimKey(`${MDOC_DEFAULT_NAMESPACE}.IT`, "verification");
|
|
23
|
+
const verification = (_parsedCredential$ver = parsedCredential[verificationKey]) === null || _parsedCredential$ver === void 0 ? void 0 : _parsedCredential$ver.value;
|
|
24
|
+
return verification ? Verification.parse(verification) : undefined;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Extract and validate the `verification` claim from an MDOC credential.
|
|
29
|
+
*
|
|
30
|
+
* This method is **asynchronous**. See {@link getVerificationFromParsedCredential} for the synchronous version.
|
|
31
|
+
*
|
|
32
|
+
* @param token The raw MDOC credential
|
|
33
|
+
* @returns The verification claim or undefined if it wasn't found
|
|
34
|
+
*/
|
|
35
|
+
export const getVerification = async token => {
|
|
36
|
+
var _namespace$find;
|
|
37
|
+
const issuerSigned = await CBOR.decodeIssuerSigned(token);
|
|
38
|
+
const namespace = issuerSigned.nameSpaces[`${MDOC_DEFAULT_NAMESPACE}.IT`];
|
|
39
|
+
const verification = namespace === null || namespace === void 0 || (_namespace$find = namespace.find(x => x.elementIdentifier === "verification")) === null || _namespace$find === void 0 ? void 0 : _namespace$find.elementValue;
|
|
40
|
+
return verification ? Verification.parse(verification) : undefined;
|
|
41
|
+
};
|
|
7
42
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["getParsedCredentialClaimKey","namespace","key"],"sourceRoot":"../../../src","sources":["mdoc/utils.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA,OAAO,
|
|
1
|
+
{"version":3,"names":["CBOR","Verification","MDOC_DEFAULT_NAMESPACE","getParsedCredentialClaimKey","namespace","key","getVerificationFromParsedCredential","parsedCredential","_parsedCredential$ver","verificationKey","verification","value","parse","undefined","getVerification","token","_namespace$find","issuerSigned","decodeIssuerSigned","nameSpaces","find","x","elementIdentifier","elementValue"],"sourceRoot":"../../../src","sources":["mdoc/utils.ts"],"mappings":"AAAA,SAASA,IAAI,QAAQ,kCAAkC;AACvD,SAASC,YAAY,QAAQ,iBAAiB;AAG9C,SAASC,sBAAsB,QAAQ,SAAS;;AAEhD;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,2BAA2B,GAAGA,CAACC,SAAiB,EAAEC,GAAW,KACvE,GAAED,SAAU,IAAGC,GAAI,EAAC;;AAEvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,mCAAmC,GAC9CC,gBAAmE,IAChE;EAAA,IAAAC,qBAAA;EACH,MAAMC,eAAe,GAAGN,2BAA2B,CAChD,GAAED,sBAAuB,KAAI,EAC9B,cACF,CAAC;EACD,MAAMQ,YAAY,IAAAF,qBAAA,GAAGD,gBAAgB,CAACE,eAAe,CAAC,cAAAD,qBAAA,uBAAjCA,qBAAA,CAAmCG,KAAK;EAC7D,OAAOD,YAAY,GAAGT,YAAY,CAACW,KAAK,CAACF,YAAY,CAAC,GAAGG,SAAS;AACpE,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,eAAe,GAAG,MAAOC,KAAa,IAAK;EAAA,IAAAC,eAAA;EACtD,MAAMC,YAAY,GAAG,MAAMjB,IAAI,CAACkB,kBAAkB,CAACH,KAAK,CAAC;EACzD,MAAMX,SAAS,GAAGa,YAAY,CAACE,UAAU,CAAE,GAAEjB,sBAAuB,KAAI,CAAC;EACzE,MAAMQ,YAAY,GAAGN,SAAS,aAATA,SAAS,gBAAAY,eAAA,GAATZ,SAAS,CAAEgB,IAAI,CACjCC,CAAC,IAAKA,CAAC,CAACC,iBAAiB,KAAK,cACjC,CAAC,cAAAN,eAAA,uBAFoBA,eAAA,CAElBO,YAAY;EAEf,OAAOb,YAAY,GAAGT,YAAY,CAACW,KAAK,CAACF,YAAY,CAAC,GAAGG,SAAS;AACpE,CAAC"}
|
|
@@ -22,14 +22,17 @@ const buildName = display => display.reduce((names, _ref) => {
|
|
|
22
22
|
};
|
|
23
23
|
}, {});
|
|
24
24
|
|
|
25
|
-
// Handles the case where the path key is `null`
|
|
25
|
+
// Handles the case where the path key is `null` (indicating an array)
|
|
26
26
|
const handleNullKeyCase = (currentObject, rest, sourceValue, displayData) => {
|
|
27
27
|
if (!Array.isArray(sourceValue)) return currentObject;
|
|
28
28
|
|
|
29
29
|
// We assert the type here because we know this branch handles PropertyNodes
|
|
30
30
|
const node = currentObject;
|
|
31
31
|
const existingValue = Array.isArray(node.value) ? node.value : [];
|
|
32
|
-
const mappedArray = sourceValue.map((item, idx) =>
|
|
32
|
+
const mappedArray = sourceValue.map((item, idx) =>
|
|
33
|
+
// When mapping over an array, recursively call with `skipMissingLeaves` set to `true`.
|
|
34
|
+
// This tells the function to skip optional keys inside these array objects.
|
|
35
|
+
createNestedProperty(existingValue[idx] || {}, rest, item, displayData, true));
|
|
33
36
|
return {
|
|
34
37
|
...node,
|
|
35
38
|
value: mappedArray,
|
|
@@ -38,7 +41,7 @@ const handleNullKeyCase = (currentObject, rest, sourceValue, displayData) => {
|
|
|
38
41
|
};
|
|
39
42
|
|
|
40
43
|
// Handles the case where the path key is a string
|
|
41
|
-
const handleStringKeyCase = (currentObject, key, rest, sourceValue, displayData) => {
|
|
44
|
+
const handleStringKeyCase = (currentObject, key, rest, sourceValue, displayData, skipMissingLeaves) => {
|
|
42
45
|
let nextSourceValue = sourceValue;
|
|
43
46
|
const isLeaf = rest.length === 0;
|
|
44
47
|
if (isObject(sourceValue)) {
|
|
@@ -51,7 +54,13 @@ const handleStringKeyCase = (currentObject, key, rest, sourceValue, displayData)
|
|
|
51
54
|
|
|
52
55
|
// Skip processing when the key is not found within the claim object
|
|
53
56
|
if (!(key in sourceValue)) {
|
|
54
|
-
//
|
|
57
|
+
// If the flag is set (we're inside an array), skip the missing key completely.
|
|
58
|
+
if (skipMissingLeaves) {
|
|
59
|
+
return currentObject;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// If the flag is NOT set, create the empty placeholder
|
|
63
|
+
// so that its children can be attached later.
|
|
55
64
|
if (isLeaf) {
|
|
56
65
|
return {
|
|
57
66
|
...currentObject,
|
|
@@ -82,7 +91,7 @@ const handleStringKeyCase = (currentObject, key, rest, sourceValue, displayData)
|
|
|
82
91
|
const nextObject = currentObject[key] || {};
|
|
83
92
|
return {
|
|
84
93
|
...currentObject,
|
|
85
|
-
[key]: createNestedProperty(nextObject, rest, nextSourceValue, displayData)
|
|
94
|
+
[key]: createNestedProperty(nextObject, rest, nextSourceValue, displayData, skipMissingLeaves)
|
|
86
95
|
};
|
|
87
96
|
};
|
|
88
97
|
|
|
@@ -101,15 +110,17 @@ const handleNumberKeyCase = (currentObject, key, rest, sourceValue, displayData)
|
|
|
101
110
|
* @param path - The path segments to follow.
|
|
102
111
|
* @param sourceValue - The raw value to place at the end of the path.
|
|
103
112
|
* @param displayData - The data for generating localized names.
|
|
113
|
+
* @param skipMissingLeaves - If true, skips optional keys when mapping over arrays.
|
|
104
114
|
* @returns The new object or array structure.
|
|
105
115
|
*/
|
|
106
|
-
export const createNestedProperty = (currentObject, path, sourceValue, displayData)
|
|
116
|
+
export const createNestedProperty = function (currentObject, path, sourceValue, displayData) {
|
|
117
|
+
let skipMissingLeaves = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
107
118
|
const [key, ...rest] = path;
|
|
108
119
|
switch (true) {
|
|
109
120
|
case key === null:
|
|
110
121
|
return handleNullKeyCase(currentObject, rest, sourceValue, displayData);
|
|
111
122
|
case typeof key === "string":
|
|
112
|
-
return handleStringKeyCase(currentObject, key, rest, sourceValue, displayData);
|
|
123
|
+
return handleStringKeyCase(currentObject, key, rest, sourceValue, displayData, skipMissingLeaves);
|
|
113
124
|
case typeof key === "number":
|
|
114
125
|
return handleNumberKeyCase(currentObject, key, rest, sourceValue, displayData);
|
|
115
126
|
default:
|
|
@@ -120,11 +131,11 @@ export const createNestedProperty = (currentObject, path, sourceValue, displayDa
|
|
|
120
131
|
// Handles the case where the next key in the path exists in the source object
|
|
121
132
|
const handleRestKey = (currentObject, key, rest, sourceValue, displayData) => {
|
|
122
133
|
const currentNode = currentObject[key] ?? {};
|
|
123
|
-
// Take the first key in the remaining path
|
|
124
134
|
const restKey = rest[0];
|
|
125
135
|
const nextSourceValue = sourceValue[restKey];
|
|
126
|
-
|
|
127
|
-
|
|
136
|
+
if (typeof nextSourceValue === "undefined") {
|
|
137
|
+
return currentObject;
|
|
138
|
+
}
|
|
128
139
|
return {
|
|
129
140
|
...currentObject,
|
|
130
141
|
[key]: {
|