@mattrglobal/verifier-sdk-web 2.1.2-unstable.17 → 2.1.2-unstable.172

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 CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  # Table of Contents
4
4
 
5
+ - [verifier-sdk-web](#verifier-sdk-web)
6
+ - [Table of Contents](#table-of-contents)
5
7
  - [General](#general)
6
8
  - [Licensing](#licensing)
7
9
  - [Overview](#overview)
@@ -35,15 +37,21 @@ Request or download the
35
37
 
36
38
  ## Overview
37
39
 
38
- The Verifier Web SDK is a powerful tool for integrating online credential verification capabilities into your web applications. It enables secure and efficient verification of [mDocs](https://learn.mattr.global/docs/mdocs), supporting both [same-device](https://learn.mattr.global/docs/verification/online/mdocs/overview#same-device-verification-workflow) and [cross-device](https://learn.mattr.global/docs/verification/online/mdocs/overview#cross-device-verification-workflow) verification workflows. The SDK leverages the MATTR VII platform to handle credential presentation and verification processes.
40
+ The Verifier Web SDK is a powerful tool for integrating online credential verification capabilities into your web
41
+ applications. It enables secure and efficient verification of [mDocs](https://learn.mattr.global/docs/mdocs), supporting
42
+ both [same-device](https://learn.mattr.global/docs/verification/online/mdocs/overview#same-device-verification-workflow)
43
+ and
44
+ [cross-device](https://learn.mattr.global/docs/verification/online/mdocs/overview#cross-device-verification-workflow)
45
+ verification workflows. The SDK leverages the MATTR VII platform to handle credential presentation and verification
46
+ processes.
39
47
 
40
48
  ## Features
41
49
 
42
- * Simple integration into web applications.
43
- * Supports both same-device and cross-device presentation flows.
44
- * Secure handling of mDocs requests and responses.
45
- * Compliant with [ISO/IEC DTS 18013-7](https://www.iso.org/standard/82772.html).
46
- * Offers [DC API](https://wicg.github.io/digital-credentials/) support as a **tech-preview**.
50
+ - Simple integration into web applications.
51
+ - Supports both same-device and cross-device presentation flows.
52
+ - Secure handling of mDocs requests and responses.
53
+ - Compliant with [ISO/IEC DTS 18013-7](https://www.iso.org/standard/82772.html).
54
+ - Offers [DC API](https://wicg.github.io/digital-credentials/) support as a **tech-preview**.
47
55
 
48
56
  > In this SDK mDocs are referred to as Mobile Credentials.
49
57
 
@@ -51,8 +59,8 @@ The Verifier Web SDK is a powerful tool for integrating online credential verifi
51
59
 
52
60
  ## How to get access to the MATTR Pi Verifier Web SDK
53
61
 
54
- Refer to our [SDK Docs landing page](https://learn.mattr.global/guides/get-started-pi) for step-by-step instructions to gain access
55
- to any of our SDKs.
62
+ Refer to our [SDK Docs landing page](https://learn.mattr.global/guides/get-started-pi) for step-by-step instructions to
63
+ gain access to any of our SDKs.
56
64
 
57
65
  > Please [reach out](mailto:dev-support@mattr.global) if you need any assistance.
58
66
 
@@ -82,25 +90,28 @@ MATTRVerifierSDK.initialize(...);
82
90
  <script src="https://cdn.mattr.global/js/verifier-sdk-web/{VERSION}/verifier-js.production.js"></script>
83
91
  ```
84
92
 
85
- > This script will automatically pick up any SDK patch updates. You can lock your implementation to a specific patch version by replacing 1.0 with the specific version (e.g. https://cdn.mattr.global/js/verifier-sdk-web/1.0.1/verifier-js.production.js).
93
+ > This script will automatically pick up any SDK patch updates. You can lock your implementation to a specific patch
94
+ > version by replacing 1.0 with the specific version (e.g.
95
+ > https://cdn.mattr.global/js/verifier-sdk-web/1.0.1/verifier-js.production.js).
86
96
 
87
97
  2. Access SDK functions via global `MATTRVerifierSDK` object.
88
98
 
89
99
  ```javascript
90
- <script>
91
- MATTRVerifierSDK.initialize(...);
92
- </script>
100
+ <script>MATTRVerifierSDK.initialize(...);</script>
93
101
  ```
94
102
 
95
103
  # Usage
96
104
 
97
- The SDK can make a request to create a presentation session with a configured MATTR VII verifier tenant. This requires the following configurations and settings:
98
- * Initialize the SDK with the URL of the MATTR VII tenant that will handle the verification request.
99
- * Prepare a credential query that defines what claims are required for verification.
100
- * Generate a unique challenge for the presentation session.
101
- * Determine what presentation flows are supported in the session.
102
- * Define what wallets can be used to respond to the verification request.
103
- * Configure the URI the user will be redirected to when the verification workflow is completed (only required for same-device flows).
105
+ The SDK can make a request to create a presentation session with a configured MATTR VII verifier tenant. This requires
106
+ the following configurations and settings:
107
+
108
+ - Initialize the SDK with the URL of the MATTR VII tenant that will handle the verification request.
109
+ - Prepare a credential query that defines what claims are required for verification.
110
+ - Generate a unique challenge for the presentation session.
111
+ - Determine what presentation flows are supported in the session.
112
+ - Define what wallets can be used to respond to the verification request.
113
+ - Configure the URI the user will be redirected to when the verification workflow is completed (only required for
114
+ same-device flows).
104
115
 
105
116
  ## Initialize the SDK
106
117
 
@@ -111,96 +122,137 @@ MATTRVerifierSDK.initialize({ apiBaseUrl, applicationId });
111
122
  ```
112
123
 
113
124
  - `apiBaseUrl` (required): URL of the MATTR VII verifier tenant.
114
- - `applicationId` (required): Unique identifier of the verifier application. This must match the [`id`](https://learn.mattr.global/api-reference/latest/tag/Verifier-applications#operation/postVerifierApplication!c=201&path=0/id&t=response) parameter in the response returned when [creating a Verifier application](https://learn.mattr.global/api-reference/latest/tag/Verifier-applications#operation/postVerifierApplication) on the MATTR VII verifier tenant.
125
+ - `applicationId` (required): Unique identifier of the verifier application. This must match the
126
+ [`id`](https://learn.mattr.global/api-reference/latest/tag/Verifier-applications#operation/postVerifierApplication!c=201&path=0/id&t=response)
127
+ parameter in the response returned when
128
+ [creating a Verifier application](https://learn.mattr.global/api-reference/latest/tag/Verifier-applications#operation/postVerifierApplication)
129
+ on the MATTR VII verifier tenant.
115
130
 
116
131
  ## Prepare a credential query
117
132
 
118
- The following example credential query will request the `given_name`, `family_name`, `birth_date` and `portrait` claims from a `mobile` credential profile with `org.iso.18013.5.1.mDL` as a docType:
133
+ The following example credential query will request the `given_name`, `family_name`, `birth_date` and `portrait` claims
134
+ from a `mobile` credential profile with `org.iso.18013.5.1.mDL` as a docType:
119
135
 
120
136
  ```javascript
121
137
  const credentialQuery = [
122
138
  {
123
- "profile": "mobile",
124
- "docType": "org.iso.18013.5.1.mDL",
125
- "nameSpaces": {
139
+ profile: "mobile",
140
+ docType: "org.iso.18013.5.1.mDL",
141
+ nameSpaces: {
126
142
  "org.iso.18013.5.1": {
127
- "given_name": {
128
- "intentToRetain": false
143
+ given_name: {
144
+ intentToRetain: false,
145
+ },
146
+ family_name: {
147
+ intentToRetain: false,
129
148
  },
130
- "family_name": {
131
- "intentToRetain": false
149
+ birth_date: {
150
+ intentToRetain: false,
132
151
  },
133
- "birth_date": {
134
- "intentToRetain": false
152
+ portrait: {
153
+ intentToRetain: false,
135
154
  },
136
- "portrait": {
137
- "intentToRetain": false
155
+ resident_postal_code: {
156
+ intentToRetain: false,
138
157
  },
139
- "resident_postal_code": {
140
- "intentToRetain": false
141
- }
142
158
  },
143
- }
144
- }
159
+ },
160
+ },
145
161
  ];
146
162
  ```
147
- * `profile`: Credential format of the credential that will be verified. Currently only mobile (mDocs) is supported.
148
- * `docType`: the mDL’s type. Confirm with the certificate issuer for what docType they are issuing. Some common examples include:
149
- * Mobile Driver License (`org.iso.18013.5.1.mDL`).
150
- * PhotoID (`org.iso.23220.photoid.1`).
151
- * Mobile Vehicle Registration Card (`org.iso.7367.1.mVRC`).
152
- * Health certificate (`org.micov.vtr.1`).
153
- * `nameSpaces`: Each namespace corresponds to a group of claims included in the credential. These can be claims that are part of a specific standard, jurisdiction or any other reference. The namespace would usually correspond to the requested `docType`.
154
- * `intentToRetain` (Optional): When set to `true`, the holder will be indicated that the verifier intends to retain this claim beyond the verification workflow. Defaults to `false` when not specified.
155
-
156
- > The API supports including multiple query objects in the `credentialQuery` array in a single request. For simplicity, this example only includes a single query object.
157
163
 
158
- In this example the `credentialQuery` query will request for the `birthdate`, `portrait` and `resident_postal_code` claims from any credentials whose `profile` is `mobile` and `docType` is `org.iso.18013.5.1.mDL`.
164
+ - `profile`: Credential format of the credential that will be verified. Currently only mobile (mDocs) is supported.
165
+ - `docType`: the mDL’s type. Confirm with the certificate issuer for what docType they are issuing. Some common examples
166
+ include:
167
+ - Mobile Driver License (`org.iso.18013.5.1.mDL`).
168
+ - PhotoID (`org.iso.23220.photoid.1`).
169
+ - Mobile Vehicle Registration Card (`org.iso.7367.1.mVRC`).
170
+ - Health certificate (`org.micov.vtr.1`).
171
+ - `nameSpaces`: Each namespace corresponds to a group of claims included in the credential. These can be claims that are
172
+ part of a specific standard, jurisdiction or any other reference. The namespace would usually correspond to the
173
+ requested `docType`.
174
+ - `intentToRetain` (Optional): When set to `true`, the holder will be indicated that the verifier intends to retain
175
+ this claim beyond the verification workflow. Defaults to `false` when not specified.
176
+
177
+ > The API supports including multiple query objects in the `credentialQuery` array in a single request. For simplicity,
178
+ > this example only includes a single query object.
159
179
 
160
- It also sets `intentToRetain` as `false` for all claims, indicating to the holder that the verifier will not retain any of these claims.
180
+ In this example the `credentialQuery` query will request for the `birthdate`, `portrait` and `resident_postal_code`
181
+ claims from any credentials whose `profile` is `mobile` and `docType` is `org.iso.18013.5.1.mDL`.
161
182
 
162
- > While `intentToRetain` defaults to false, it is explicitly set to `false` in the example above for clarity purposes. If there is no intention to retain a claim, it is sufficient to simply exclude `intentToRetain` from the query.
183
+ It also sets `intentToRetain` as `false` for all claims, indicating to the holder that the verifier will not retain any
184
+ of these claims.
185
+
186
+ > While `intentToRetain` defaults to false, it is explicitly set to `false` in the example above for clarity purposes.
187
+ > If there is no intention to retain a claim, it is sufficient to simply exclude `intentToRetain` from the query.
163
188
 
164
189
  ## Generate challenge
165
190
 
166
- The Verifier Web SDK passes a unique challenge to the MATTR VII verifier tenant with every request to create a new presentation session. The purpose of the challenge is to ensure the security and integrity of the credential verification process by preventing replay attacks and verifying the authenticity of each request and response. You can either:
167
- * Generate this challenge by your backend and pass it to the SDK.
168
- * Generate it using the SDK built-in method.
191
+ The Verifier Web SDK passes a unique challenge to the MATTR VII verifier tenant with every request to create a new
192
+ presentation session. The purpose of the challenge is to ensure the security and integrity of the credential
193
+ verification process by preventing replay attacks and verifying the authenticity of each request and response. You can
194
+ either:
195
+
196
+ - Generate this challenge by your backend and pass it to the SDK.
197
+ - Generate it using the SDK built-in method.
169
198
 
170
- When the challenge is generated by your backend, you should use it to validate the verification results received from the MATTR VII verifier tenant.
199
+ When the challenge is generated by your backend, you should use it to validate the verification results received from
200
+ the MATTR VII verifier tenant.
171
201
 
172
202
  ## Determine supported presentation flows
173
203
 
174
- The **same-device flow** involves the user completing all steps on a single device, such as their smartphone. They initiate the credential request on the verifier's web app, are redirected to their wallet app to consent and present credentials, and then return to the verifier's web app with the results.
204
+ The **same-device flow** involves the user completing all steps on a single device, such as their smartphone. They
205
+ initiate the credential request on the verifier's web app, are redirected to their wallet app to consent and present
206
+ credentials, and then return to the verifier's web app with the results.
175
207
 
176
- In contrast, the **cross-device flow** starts on one device, like a laptop. When the user initiates the request, the web app responds by displaying a QR code. The user then scans this QR code with their smartphone, use their wallet app to present matching credentials, and the results are sent back to the verifier's web app.
208
+ In contrast, the **cross-device flow** starts on one device, like a laptop. When the user initiates the request, the web
209
+ app responds by displaying a QR code. The user then scans this QR code with their smartphone, use their wallet app to
210
+ present matching credentials, and the results are sent back to the verifier's web app.
177
211
 
178
- The main difference is that the same-device flow uses only one device for the entire process, while the cross-device flow uses two devices for added flexibility.
212
+ The main difference is that the same-device flow uses only one device for the entire process, while the cross-device
213
+ flow uses two devices for added flexibility.
179
214
 
180
215
  By default, the Verifier Web SDK automatically selects a flow based on the browser's user agent:
181
- * Same-device flows are used when the agent is a mobile device.
182
- * Cross-device flows are used in all other cases.
183
216
 
184
- This behavior can be explicitly overridden by specifying the desired mode in the SDK configuration, as shown in the [examples](#usage-examples) below.
217
+ - Same-device flows are used when the agent is a mobile device.
218
+ - Cross-device flows are used in all other cases.
219
+
220
+ This behavior can be explicitly overridden by specifying the desired mode in the SDK configuration, as shown in the
221
+ [examples](#request-credentials-examples) below.
185
222
 
186
223
  ## Define wallet identifiers
187
224
 
188
- You can define an identifier of a specific wallet you want to invoke with this verification request. The identifier defined by the SDK in the credential request must match one of the identifiers of a [wallet provider](https://learn.mattr.global/api-reference/latest/tag/Wallet-providers#operation/postWalletProvider!path=name&t=request) created on the MATTR VII verifier tenant.
189
- * If an identifier is provided and matches the `id` of one of the objects in the `walletProviders` array, the verifier tenant will invoke that specific wallet using its corresponding [`authorizationEndpoint`](https://learn.mattr.global/api-reference/latest/tag/Wallet-providers#operation/postWalletProvider!path=openid4vpConfiguration/authorizationEndpoint&t=request).
190
- * If an identifier is provided and does not match the `id` of any of the objects in the `walletProviders array`, the request will fail.
191
- * If an identifier is not provided, the verifier tenant will use `mdoc-openid4vp://` (default OID4VP scheme) to invoke any wallet.
225
+ You can define an identifier of a specific wallet you want to invoke with this verification request. The identifier
226
+ defined by the SDK in the credential request must match one of the identifiers of a
227
+ [wallet provider](https://learn.mattr.global/api-reference/latest/tag/Wallet-providers#operation/postWalletProvider!path=name&t=request)
228
+ created on the MATTR VII verifier tenant.
229
+
230
+ - If an identifier is provided and matches the `id` of one of the objects in the `walletProviders` array, the verifier
231
+ tenant will invoke that specific wallet using its corresponding
232
+ [`authorizationEndpoint`](https://learn.mattr.global/api-reference/latest/tag/Wallet-providers#operation/postWalletProvider!path=openid4vpConfiguration/authorizationEndpoint&t=request).
233
+ - If an identifier is provided and does not match the `id` of any of the objects in the `walletProviders array`, the
234
+ request will fail.
235
+ - If an identifier is not provided, the verifier tenant will use `mdoc-openid4vp://` (default OID4VP scheme) to invoke
236
+ any wallet.
192
237
 
193
238
  ## Configure redirectUri
194
239
 
195
- When using the same-device presentation flow, the SDK must define what URI to redirect the user to once they complete the verification workflow in their wallet app. This can be any URI (including custom URI schemes), and must match one of the values defined in the [`redirectUris` array](https://learn.mattr.global/api-reference/latest/tag/Verifier-applications#operation/postVerifierApplication!path=0/openid4vpConfiguration/redirectUris&t=request) when creating a verifier application.
240
+ When using the same-device presentation flow, the SDK must define what URI to redirect the user to once they complete
241
+ the verification workflow in their wallet app. This can be any URI (including custom URI schemes), and must match one of
242
+ the values defined in the
243
+ [`redirectUris` array](https://learn.mattr.global/api-reference/latest/tag/Verifier-applications#operation/postVerifierApplication!path=0/openid4vpConfiguration/redirectUris&t=request)
244
+ when creating a verifier application.
196
245
 
197
246
  ## Request credentials using the DC API
198
247
 
199
- > DC API support is currently offered as a **tech preview**. As such, functionality may be limited, may not work in all scenarios, and could change or break without prior notice.
248
+ > DC API support is currently offered as a **tech preview**. As such, functionality may be limited, may not work in all
249
+ > scenarios, and could change or break without prior notice.
200
250
 
201
- 1. Add the `dcApiConfiguration` object to your MATTR VII [verifier application configuration](https://learn.mattr.global/docs/verification/remote-verification-api-reference/verifier-applications#update-a-verifier-application).
251
+ 1. Add the `dcApiConfiguration` object to your MATTR VII
252
+ [verifier application configuration](https://learn.mattr.global/docs/verification/remote-verification-api-reference/verifier-applications#update-a-verifier-application).
202
253
 
203
- 2. Use the SDK's `isDigitalCredentialsApiSupported` method to determine if the user's browser supports the Digital Credentials API:
254
+ 2. Use the SDK's `isDigitalCredentialsApiSupported` method to determine if the user's browser supports the Digital
255
+ Credentials API:
204
256
 
205
257
  ```typescript
206
258
  import * as MattrVerifierSDK from "@mattrglobal/verifier-sdk-web";
@@ -243,9 +295,9 @@ const result = await MATTRVerifierSDK.requestCredentials({
243
295
  credentialQuery: credentialQuery, // Define what credential query to use
244
296
  challenge: MATTRVerifierSDK.utils.generateChallenge(), // Pass a unique challenge
245
297
  openid4vpConfiguration: {
246
- walletProviderId, // Define the wallet identifier
247
- redirectUri, // Define the redirect URI (not required for cross-device only requests)
248
- }
298
+ walletProviderId, // Define the wallet identifier
299
+ redirectUri, // Define the redirect URI (not required for cross-device only requests)
300
+ },
249
301
  });
250
302
 
251
303
  if (result.isErr()) {
@@ -254,12 +306,21 @@ if (result.isErr()) {
254
306
  console.info("<<< MATTRVerifierSDK.requestCredentials succeed", result.value);
255
307
  }
256
308
  ```
257
- * `apiBaseUrl` : Replace with the [`tenant_url`](https://learn.mattr.global/docs/platform-management/authentication) of your MATTR VII verifier tenant.
258
- * `credentialQuery`: The credential query to be used in the request.
259
- * `challenge`: The challenge that will be passed to the MATTR VII tenant with the request to create a presentation session. This example uses the SDK built-in method to generate the challenge, but you can replace it with a challenge generated by your backend system.
260
- * `walletProviderId`: Replace with a wallet identifier that matches one of the identifiers of a [wallet provider](https://learn.mattr.global/api-reference/latest/tag/Wallet-providers#operation/postWalletProvider!path=name&t=request) created on the MATTR VII verifier tenant..
261
- * `mode`: When omitted, the SDK defaults to automatically selecting a flow based on the browser's user agent (set to `undefined` in the example for clarity).
262
- * `redirectUri` Replace with a URI that matches one of the values in the [`redirectUris` array](https://learn.mattr.global/api-reference/latest/tag/Verifier-applications#operation/postVerifierApplication!path=0/openid4vpConfiguration/redirectUris&t=request) in the MATTR VII tenant's verifier application.
309
+
310
+ - `apiBaseUrl` : Replace with the [`tenant_url`](https://learn.mattr.global/docs/platform-management/authentication) of
311
+ your MATTR VII verifier tenant.
312
+ - `credentialQuery`: The credential query to be used in the request.
313
+ - `challenge`: The challenge that will be passed to the MATTR VII tenant with the request to create a presentation
314
+ session. This example uses the SDK built-in method to generate the challenge, but you can replace it with a challenge
315
+ generated by your backend system.
316
+ - `walletProviderId`: Replace with a wallet identifier that matches one of the identifiers of a
317
+ [wallet provider](https://learn.mattr.global/api-reference/latest/tag/Wallet-providers#operation/postWalletProvider!path=name&t=request)
318
+ created on the MATTR VII verifier tenant..
319
+ - `mode`: When omitted, the SDK defaults to automatically selecting a flow based on the browser's user agent (set to
320
+ `undefined` in the example for clarity).
321
+ - `redirectUri` Replace with a URI that matches one of the values in the
322
+ [`redirectUris` array](https://learn.mattr.global/api-reference/latest/tag/Verifier-applications#operation/postVerifierApplication!path=0/openid4vpConfiguration/redirectUris&t=request)
323
+ in the MATTR VII tenant's verifier application.
263
324
 
264
325
  ## Request credentials with explicit same-device flow
265
326
 
@@ -269,10 +330,10 @@ const result = await MATTRVerifierSDK.requestCredentials({
269
330
  credentialQuery: credentialQuery,
270
331
  challenge: MATTRVerifierSDK.utils.generateChallenge(),
271
332
  openid4vpConfiguration: {
272
- redirectUri,
273
- walletProviderId,
274
- mode: "sameDevice",
275
- }
333
+ redirectUri,
334
+ walletProviderId,
335
+ mode: "sameDevice",
336
+ },
276
337
  });
277
338
 
278
339
  // result can be retrieved on redirect uri page. for example
@@ -282,9 +343,9 @@ window.addEventListener("load", async () => {
282
343
  });
283
344
  ```
284
345
 
285
- * `mode`: When set to `sameDevice`, the SDK will only support same-device flow in this verification workflow.
286
- * Note that in this case you must define a `redirectUri`.
287
- * This example shows how you can redirect the user to page that will retrieve and display the verification results.
346
+ - `mode`: When set to `sameDevice`, the SDK will only support same-device flow in this verification workflow.
347
+ - Note that in this case you must define a `redirectUri`.
348
+ - This example shows how you can redirect the user to page that will retrieve and display the verification results.
288
349
 
289
350
  ## Request credentials with explicit cross-device flow
290
351
 
@@ -294,9 +355,9 @@ const result = await MATTRVerifierSDK.requestCredentials({
294
355
  credentialQuery: credentialQuery,
295
356
  challenge: MATTRVerifierSDK.utils.generateChallenge(),
296
357
  openid4vpConfiguration: {
297
- walletProviderId,
298
- mode: "crossDevice",
299
- }
358
+ walletProviderId,
359
+ mode: "crossDevice",
360
+ },
300
361
  });
301
362
 
302
363
  if (result.isErr()) {
@@ -306,8 +367,10 @@ if (result.isErr()) {
306
367
  }
307
368
  ```
308
369
 
309
- * `mode`: When set to `crossDevice`, the SDK will only support cross-device flow in this verification workflow.
310
- * Note that in this case you must define how to handle verification completion and failure.
370
+ - `mode`: When set to `crossDevice`, the SDK will only support cross-device flow in this verification workflow.
371
+ - Note that in this case you must define how to handle verification completion and failure.
311
372
 
312
373
  # Error Handling
313
- The SDK includes mechanisms for handling errors, such as invalid requests, session timeouts, and user aborts. Callbacks provide detailed error information to help diagnose and remedy issues.
374
+
375
+ The SDK includes mechanisms for handling errors, such as invalid requests, session timeouts, and user aborts. Callbacks
376
+ provide detailed error information to help diagnose and remedy issues.
@@ -7,7 +7,7 @@
7
7
  * Do Not Translate or Localize
8
8
  *
9
9
  * Bundle of @mattrglobal/verifier-sdk-web
10
- * Generated: 2026-02-16
10
+ * Generated: 2026-06-05
11
11
  * Version: 2.1.1
12
12
  * Dependencies:
13
13
  */
@@ -181,7 +181,8 @@ const PresentationResultRelaxValidator = v__namespace.object({
181
181
  credentialQuery: v__namespace.optional(v__namespace.unknown()),
182
182
  credentials: v__namespace.optional(v__namespace.unknown()),
183
183
  credentialErrors: v__namespace.optional(v__namespace.unknown()),
184
- error: v__namespace.optional(v__namespace.unknown())
184
+ error: v__namespace.optional(v__namespace.unknown()),
185
+ state: v__namespace.optional(v__namespace.string())
185
186
  });
186
187
 
187
188
  exports.Mode = void 0;
@@ -203,7 +204,8 @@ v__namespace.object({
203
204
  challenge: v__namespace.string(),
204
205
  redirectUri: v__namespace.optional(v__namespace.string()),
205
206
  walletProviderId: v__namespace.optional(v__namespace.string()),
206
- dcApiSupported: v__namespace.optional(v__namespace.boolean())
207
+ dcApiSupported: v__namespace.optional(v__namespace.boolean()),
208
+ state: v__namespace.optional(v__namespace.pipe(v__namespace.string(), v__namespace.minLength(1)))
207
209
  });
208
210
 
209
211
  const CreateSessionDigitalCredentialsValidator = v__namespace.object({
@@ -218,7 +220,8 @@ const CreateSessionOpenId4vpResponseValidator = v__namespace.object({
218
220
  type: v__namespace.optional(v__namespace.literal(SessionType.Openid4vp)),
219
221
  sessionId: v__namespace.string(),
220
222
  sessionKey: v__namespace.string(),
221
- sessionUrl: v__namespace.string()
223
+ sessionUrl: v__namespace.string(),
224
+ state: v__namespace.optional(v__namespace.string())
222
225
  });
223
226
 
224
227
  const CreateSessionResponseValidator = v__namespace.union([ CreateSessionDigitalCredentialsValidator, CreateSessionOpenId4vpResponseValidator ]);
@@ -246,6 +249,7 @@ var LocalStorageKey;
246
249
  (function(LocalStorageKey) {
247
250
  LocalStorageKey["challenge"] = "mattr_chg";
248
251
  LocalStorageKey["sessionId"] = "mattr_sid";
252
+ LocalStorageKey["state"] = "mattr_st";
249
253
  })(LocalStorageKey || (LocalStorageKey = {}));
250
254
 
251
255
  const MATTR_SDK_VERSION_HEADER = "x-mattr-sdk-version";
@@ -280,7 +284,8 @@ const OpenId4vpConfigAutoDetectOptionsValidator = v__namespace.object({
280
284
  const RequestCredentialsOptionsValidator = v__namespace.object({
281
285
  credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
282
286
  challenge: v__namespace.optional(v__namespace.string()),
283
- openid4vpConfiguration: v__namespace.optional(v__namespace.union([ OpenId4vpConfigSameDeviceOptionsValidator, OpenId4vpConfigCrossDeviceOptionsValidator, OpenId4vpConfigAutoDetectOptionsValidator ]))
287
+ openid4vpConfiguration: v__namespace.optional(v__namespace.union([ OpenId4vpConfigSameDeviceOptionsValidator, OpenId4vpConfigCrossDeviceOptionsValidator, OpenId4vpConfigAutoDetectOptionsValidator ])),
288
+ state: v__namespace.optional(v__namespace.pipe(v__namespace.string(), v__namespace.minLength(1, "state must not be empty")))
284
289
  });
285
290
 
286
291
  exports.RequestCredentialsErrorType = void 0;
@@ -303,6 +308,7 @@ var RequestCredentialsErrorMessage;
303
308
  RequestCredentialsErrorMessage["DcApiResponseParseError"] = "Failed to parse response from Digital Credentials API";
304
309
  RequestCredentialsErrorMessage["Abort"] = "User aborted the session";
305
310
  RequestCredentialsErrorMessage["Timeout"] = "User session timeout";
311
+ RequestCredentialsErrorMessage["StateMismatch"] = "State mismatch between requested session and back-channel result";
306
312
  })(RequestCredentialsErrorMessage || (RequestCredentialsErrorMessage = {}));
307
313
 
308
314
  exports.AbortSessionErrorType = void 0;
@@ -492,18 +498,20 @@ const getHashParamValue = (hash, param) => {
492
498
  return urlParams.get(param);
493
499
  };
494
500
 
495
- const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl, walletProviderId: walletProviderId, dcApiSupported: dcApiSupported, applicationId: applicationId}) => {
501
+ const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl, walletProviderId: walletProviderId, dcApiSupported: dcApiSupported, applicationId: applicationId, state: state}) => {
496
502
  const openid4vpConfiguration = !!walletProviderId || !!redirectUri ? {
497
503
  redirectUri: redirectUri,
498
504
  walletProviderId: walletProviderId
499
505
  } : undefined;
500
- const postData = {
506
+ const postData = Object.assign({
501
507
  credentialQuery: credentialQuery,
502
508
  challenge: challenge,
503
509
  applicationId: applicationId,
504
510
  dcApiSupported: dcApiSupported,
505
511
  openid4vpConfiguration: openid4vpConfiguration
506
- };
512
+ }, state !== undefined ? {
513
+ state: state
514
+ } : {});
507
515
  const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/web/sessions`, {
508
516
  method: "POST",
509
517
  headers: {
@@ -621,7 +629,7 @@ const closeCrossDeviceModal = options => {
621
629
  };
622
630
 
623
631
  const receiveMessageHandler = options => async event => {
624
- const {onComplete: onComplete, onFailure: onFailure, container: container, sessionId: sessionId, apiBaseUrl: apiBaseUrl, challenge: challenge} = options;
632
+ const {onComplete: onComplete, onFailure: onFailure, container: container, sessionId: sessionId, apiBaseUrl: apiBaseUrl, challenge: challenge, state: state} = options;
625
633
  if (event.origin !== apiBaseUrl) {
626
634
  return;
627
635
  }
@@ -643,10 +651,22 @@ const receiveMessageHandler = options => async event => {
643
651
  });
644
652
  return;
645
653
  }
654
+ const resultState = "challenge" in result.value ? result.value.state : undefined;
655
+ if (state !== undefined && resultState !== undefined && state !== resultState) {
656
+ onFailure({
657
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
658
+ message: RequestCredentialsErrorMessage.StateMismatch
659
+ });
660
+ closeCrossDeviceModal({
661
+ container: container
662
+ });
663
+ return;
664
+ }
646
665
  onComplete({
647
666
  result: "challenge" in result.value ? result.value : undefined,
648
667
  sessionId: result.value.sessionId,
649
- sessionCompletedInRedirect: false
668
+ sessionCompletedInRedirect: false,
669
+ state: resultState !== null && resultState !== void 0 ? resultState : state
650
670
  });
651
671
  closeCrossDeviceModal({
652
672
  container: container
@@ -692,7 +712,7 @@ const openCrossDeviceModal = options => {
692
712
  };
693
713
 
694
714
  const requestCredentialsWithCrossDevice = async options => {
695
- const {challenge: challenge, apiBaseUrl: apiBaseUrl, sessionUrl: sessionUrl, sessionId: sessionId, sessionKey: sessionKey} = options;
715
+ const {challenge: challenge, apiBaseUrl: apiBaseUrl, sessionUrl: sessionUrl, sessionId: sessionId, sessionKey: sessionKey, state: state} = options;
696
716
  const container = openCrossDeviceModal({
697
717
  sessionUrl: sessionUrl
698
718
  });
@@ -716,6 +736,7 @@ const requestCredentialsWithCrossDevice = async options => {
716
736
  sessionId: sessionId,
717
737
  apiBaseUrl: apiBaseUrl,
718
738
  challenge: challenge,
739
+ state: state,
719
740
  onComplete: data => resolve(neverthrow.ok(data)),
720
741
  onFailure: error => resolve(neverthrow.err(error))
721
742
  });
@@ -903,13 +924,18 @@ var SameDeviceRequestCredentialsErrorMessage;
903
924
  })(SameDeviceRequestCredentialsErrorMessage || (SameDeviceRequestCredentialsErrorMessage = {}));
904
925
 
905
926
  const requestCredentialsSameDevice = async options => {
906
- const {challenge: challenge, apiBaseUrl: apiBaseUrl, applicationId: applicationId, sessionUrl: sessionUrl, sessionKey: sessionKey, sessionId: sessionId} = options;
927
+ const {challenge: challenge, apiBaseUrl: apiBaseUrl, applicationId: applicationId, sessionUrl: sessionUrl, sessionKey: sessionKey, sessionId: sessionId, state: state} = options;
907
928
  const abortController = setActiveSession({
908
929
  sessionId: sessionId,
909
930
  sessionKey: sessionKey
910
931
  });
911
932
  window.localStorage.setItem(LocalStorageKey.sessionId, sessionId);
912
933
  window.localStorage.setItem(LocalStorageKey.challenge, challenge);
934
+ if (state !== undefined) {
935
+ window.localStorage.setItem(LocalStorageKey.state, state);
936
+ } else {
937
+ window.localStorage.removeItem(LocalStorageKey.state);
938
+ }
913
939
  window.location.assign(sessionUrl);
914
940
  await sleep(SESSION_STATUS_POLLING_INITIAL_DELAY_MS);
915
941
  const checkResult = await withRetry((async () => {
@@ -960,7 +986,7 @@ const requestCredentials = async options => {
960
986
  }
961
987
  assertType(RequestCredentialsOptionsValidator, "Invalid request credential options")(options);
962
988
  const {apiBaseUrl: apiBaseUrl, applicationId: applicationId} = initializeOptions;
963
- const {challenge: challenge = generateChallenge(), credentialQuery: credentialQuery, openid4vpConfiguration: openid4vpConfiguration} = options;
989
+ const {challenge: challenge = generateChallenge(), credentialQuery: credentialQuery, openid4vpConfiguration: openid4vpConfiguration, state: state} = options;
964
990
  const dcApiSupported = isDigitalCredentialsApiSupported();
965
991
  const openId4VpRedirectUri = deriveOpenId4vpRedirectUri(openid4vpConfiguration);
966
992
  const createSessionResult = await createSession({
@@ -970,7 +996,8 @@ const requestCredentials = async options => {
970
996
  walletProviderId: (_a = openid4vpConfiguration === null || openid4vpConfiguration === void 0 ? void 0 : openid4vpConfiguration.walletProviderId) !== null && _a !== void 0 ? _a : undefined,
971
997
  apiBaseUrl: apiBaseUrl,
972
998
  applicationId: applicationId,
973
- dcApiSupported: dcApiSupported
999
+ dcApiSupported: dcApiSupported,
1000
+ state: state
974
1001
  });
975
1002
  if (createSessionResult.isErr()) {
976
1003
  return neverthrow.err({
@@ -1006,7 +1033,8 @@ const requestCredentials = async options => {
1006
1033
  applicationId: applicationId,
1007
1034
  sessionUrl: sessionUrl,
1008
1035
  sessionKey: sessionKey,
1009
- sessionId: sessionId
1036
+ sessionId: sessionId,
1037
+ state: state
1010
1038
  });
1011
1039
  }
1012
1040
  return await requestCredentialsWithCrossDevice({
@@ -1014,7 +1042,8 @@ const requestCredentials = async options => {
1014
1042
  apiBaseUrl: apiBaseUrl,
1015
1043
  sessionUrl: sessionUrl,
1016
1044
  sessionKey: sessionKey,
1017
- sessionId: sessionId
1045
+ sessionId: sessionId,
1046
+ state: state
1018
1047
  });
1019
1048
  };
1020
1049
 
@@ -1047,9 +1076,11 @@ var HandleRedirectCallbackErrorMessage;
1047
1076
  HandleRedirectCallbackErrorMessage["FailedToFindChallenge"] = "Failed to find challenge";
1048
1077
  HandleRedirectCallbackErrorMessage["FailedToFindActiveSession"] = "Failed to find active session";
1049
1078
  HandleRedirectCallbackErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
1079
+ HandleRedirectCallbackErrorMessage["StateMismatch"] = "State mismatch between stored session and back-channel result";
1050
1080
  })(HandleRedirectCallbackErrorMessage || (HandleRedirectCallbackErrorMessage = {}));
1051
1081
 
1052
1082
  const handleRedirectCallback = async () => {
1083
+ var _a;
1053
1084
  const initializeOptions = getInitializeOptions();
1054
1085
  if (!initializeOptions) {
1055
1086
  throw new Exception(InitializeErrorMessage.SdkNotInitialized);
@@ -1064,6 +1095,7 @@ const handleRedirectCallback = async () => {
1064
1095
  }
1065
1096
  const sessionId = window.localStorage.getItem(LocalStorageKey.sessionId);
1066
1097
  const challenge = window.localStorage.getItem(LocalStorageKey.challenge);
1098
+ const storedState = (_a = window.localStorage.getItem(LocalStorageKey.state)) !== null && _a !== void 0 ? _a : undefined;
1067
1099
  if (!sessionId || !challenge) {
1068
1100
  return neverthrow.err({
1069
1101
  type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
@@ -1083,9 +1115,22 @@ const handleRedirectCallback = async () => {
1083
1115
  cause: result.error
1084
1116
  });
1085
1117
  }
1118
+ const resultState = "challenge" in result.value ? result.value.state : undefined;
1119
+ if (storedState !== undefined && resultState !== undefined && storedState !== resultState) {
1120
+ window.localStorage.removeItem(LocalStorageKey.challenge);
1121
+ window.localStorage.removeItem(LocalStorageKey.sessionId);
1122
+ window.localStorage.removeItem(LocalStorageKey.state);
1123
+ return neverthrow.err({
1124
+ type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
1125
+ message: HandleRedirectCallbackErrorMessage.StateMismatch
1126
+ });
1127
+ }
1128
+ const state = resultState !== null && resultState !== void 0 ? resultState : storedState;
1129
+ window.localStorage.removeItem(LocalStorageKey.state);
1086
1130
  return neverthrow.ok({
1087
1131
  result: "challenge" in result.value ? result.value : undefined,
1088
- sessionId: result.value.sessionId
1132
+ sessionId: result.value.sessionId,
1133
+ state: state
1089
1134
  });
1090
1135
  };
1091
1136