@mattrglobal/verifier-sdk-web 1.0.2-unstable.98 → 2.0.0-preview-digital-credential-api.1

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,9 +2,10 @@
2
2
 
3
3
  # Table of Contents
4
4
 
5
- - [Licensing](#licensing)
6
- - [Overview](#overview)
7
- - [Features](#features)
5
+ - [General](#general)
6
+ - [Licensing](#licensing)
7
+ - [Overview](#overview)
8
+ - [Features](#features)
8
9
  - [Getting started](#getting-started)
9
10
  - [How to get access to the MATTR Pi Verifier Web SDK](#how-to-get-access-to-the-mattr-pi-verifier-web-sdk)
10
11
  - [Installation](#installation)
@@ -23,23 +24,27 @@
23
24
  - [Request credentials with explicit cross-device flow](#request-credentials-with-explicit-cross-device-flow)
24
25
  - [Error Handling](#error-handling)
25
26
 
26
- # Licensing
27
+ # General
28
+
29
+ ## Licensing
27
30
 
28
31
  Request or download the
29
32
  [MATTR Pi SDK Trial Licence Agreement](https://learn.mattr.global/docs/terms/mattr-pi-sdk-licence-agreement) and the
30
33
  [MATTR Customer Agreement](https://learn.mattr.global/docs/terms/customer-agreement) and review these terms carefully.
31
34
 
32
- # Overview
35
+ ## Overview
33
36
 
34
- 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 [Mobile Credentials](https://learn.mattr.global/docs/profiles/mobile), supporting both [same-device](https://learn.mattr.global/docs/profiles/mobile/verification-workflows/online#same-device-verification-workflow) and [cross-device](https://learn.mattr.global/docs/profiles/mobile/verification-workflows/online#cross-device-verification-workflow) verification workflows. The SDK leverages the MATTR VII platform to handle credential presentation and verification processes.
37
+ 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/formats/mdocs), supporting both [same-device](https://learn.mattr.global/docs/formats/mdocs/verification-workflows/online#same-device-verification-workflow) and [cross-device](https://learn.mattr.global/docs/formats/mdocs/verification-workflows/online#cross-device-verification-workflow) verification workflows. The SDK leverages the MATTR VII platform to handle credential presentation and verification processes.
35
38
 
36
- # Features
39
+ ## Features
37
40
 
38
41
  * Simple integration into web applications.
39
42
  * Supports both same-device and cross-device presentation flows.
40
- * Secure handling of credential requests and responses.
43
+ * Secure handling of mDocs requests and responses.
41
44
  * Compliant with [ISO/IEC DTS 18013-7](https://www.iso.org/standard/82772.html).
42
45
 
46
+ > In this SDK mDocs are referred to as Mobile Credentials.
47
+
43
48
  # Getting started
44
49
 
45
50
  ## How to get access to the MATTR Pi Verifier Web SDK
@@ -149,14 +154,14 @@ This behavior can be explicitly overridden by specifying the desired mode in the
149
154
 
150
155
  ## Define wallet identifiers
151
156
 
152
- 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 defined in the [`walletProviders` array](https://learn.mattr.global/api-reference/latest/tag/Mobile-Credentials-Verification#operation/putVerifierConfiguration!path=walletProviders/id&t=request) of the MATTR VII tenant's verifier configuration.
153
- * 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/Mobile-Credentials-Verification#operation/putVerifierConfiguration!path=walletProviders/authorizationEndpoint&t=request).
157
+ 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 defined in the [`walletProviders` array](https://learn.mattr.global/api-reference/latest/tag/mDocs-verification#operation/putVerifierConfiguration!path=walletProviders/id&t=request) of the MATTR VII tenant's verifier configuration.
158
+ * 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/mDocs-verification#operation/putVerifierConfiguration!path=walletProviders/authorizationEndpoint&t=request).
154
159
  * If an identifier is provided and does not match the `id` of any of the objects in the `walletProviders array`, the request will fail.
155
160
  * If an identifier is not provided, the verifier tenant will use `mdoc-openid4vp://` (default OID4VP scheme) to invoke any wallet.
156
161
 
157
162
  ## Configure redirectUri
158
163
 
159
- 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/latest/tag/Mobile-Credentials-Verification#operation/putVerifierConfiguration!path=redirectUris&t=request) in the MATTR VII tenant's verifier configuration.
164
+ 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/latest/tag/mDocs-verification#operation/putVerifierConfiguration!path=redirectUris&t=request) in the MATTR VII tenant's verifier configuration.
160
165
 
161
166
  # Request credentials examples
162
167
 
@@ -182,9 +187,9 @@ const result = await MATTRVerifierSDK.requestCredentials({
182
187
  * `apiBaseUrl` : Replace with the [`tenant_url`](https://learn.mattr.global/docs/security/authentication) of your MATTR VII verifier tenant.
183
188
  * `credentialQuery`: The credential query to be used in the request.
184
189
  * `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.
185
- * `walletProviderId`: Replace with a wallet identifier that matches one of the values in the [`walletProviders` array](https://learn.mattr.global/api-reference/latest/tag/Mobile-Credentials-Verification#operation/putVerifierConfiguration!path=walletProviders/id&t=request) of the MATTR VII tenant's verifier configuration.
190
+ * `walletProviderId`: Replace with a wallet identifier that matches one of the values in the [`walletProviders` array](https://learn.mattr.global/api-reference/latest/tag/mDocs-verification#operation/putVerifierConfiguration!path=walletProviders/id&t=request) of the MATTR VII tenant's verifier configuration.
186
191
  * `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).
187
- * `redirectUri` Replace with a URI that matches one of the values in the [`redirectUris` array](https://learn.mattr.global/latest/tag/Mobile-Credentials-Verification#operation/putVerifierConfiguration!path=redirectUris&t=request) in the MATTR VII tenant's verifier configuration.
192
+ * `redirectUri` Replace with a URI that matches one of the values in the [`redirectUris` array](https://learn.mattr.global/latest/tag/mDocs-verification#operation/putVerifierConfiguration!path=redirectUris&t=request) in the MATTR VII tenant's verifier configuration.
188
193
  * `crossDeviceCallback`: Defines how to handle completion (`onComplete`) or failure (`onFailure`) of the verification workflow.
189
194
 
190
195
  ## Request credentials with explicit same-device flow
@@ -7,8 +7,8 @@
7
7
  * Do Not Translate or Localize
8
8
  *
9
9
  * Bundle of @mattrglobal/verifier-sdk-web
10
- * Generated: 2024-10-18
11
- * Version: 1.0.1
10
+ * Generated: 2024-10-21
11
+ * Version: 2.0.0-preview-digital-credential-api.1
12
12
  * Dependencies:
13
13
  */
14
14
 
@@ -200,6 +200,11 @@ const CreateSessionResponseValidator = v__namespace.object({
200
200
  sessionUrl: v__namespace.string()
201
201
  });
202
202
 
203
+ const CreateDigitalCredentialsApiSessionResponseValidator = v__namespace.object({
204
+ sessionId: v__namespace.string(),
205
+ request: v__namespace.object({})
206
+ });
207
+
203
208
  var LocalStorageKey;
204
209
 
205
210
  (function(LocalStorageKey) {
@@ -262,7 +267,9 @@ exports.RequestCredentialsErrorType = void 0;
262
267
  })(exports.RequestCredentialsErrorType || (exports.RequestCredentialsErrorType = {}));
263
268
 
264
269
  const InitialiseOptionsValidator = v__namespace.object({
265
- apiBaseUrl: v__namespace.string()
270
+ apiBaseUrl: v__namespace.string(),
271
+ enableDigitalCredentialsApiSameDeviceFlow: v__namespace.optional(v__namespace.boolean()),
272
+ enableDigitalCredentialsApiCrossDeviceFlow: v__namespace.optional(v__namespace.boolean())
266
273
  });
267
274
 
268
275
  let initialiseOptions = undefined;
@@ -378,6 +385,64 @@ const isMobileDetect = userAgent => isMobile.isMobile({
378
385
  tablet: false
379
386
  });
380
387
 
388
+ const isDigitalCredentialsApiSupported = () => {
389
+ var _a;
390
+ try {
391
+ return typeof ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.identity) === null || _a === void 0 ? void 0 : _a.get) === "function";
392
+ } catch (error) {
393
+ return false;
394
+ }
395
+ };
396
+
397
+ const createDigitalCredentialsApiSession = async ({credentialQuery: credentialQuery, challenge: challenge, apiBaseUrl: apiBaseUrl}) => {
398
+ const postData = {
399
+ credentialQuery: credentialQuery,
400
+ challenge: challenge
401
+ };
402
+ const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/browserApi/request`, {
403
+ method: "POST",
404
+ headers: {
405
+ "Content-Type": "application/json"
406
+ },
407
+ body: JSON.stringify(postData)
408
+ });
409
+ if (responseResult.isErr()) {
410
+ return neverthrow.err(responseResult.error);
411
+ }
412
+ const data = await responseResult.value.json();
413
+ if (!isType(CreateDigitalCredentialsApiSessionResponseValidator)(data)) {
414
+ return neverthrow.err({
415
+ type: SafeFetchCommonRespondErrorType.UnexpectedRespond,
416
+ message: "Create digital credentials api session return unsupported response"
417
+ });
418
+ }
419
+ return neverthrow.ok(data);
420
+ };
421
+
422
+ const getDigitalCredentialsApiSessionResult = async ({challenge: challenge, sessionId: sessionId, response: response, apiBaseUrl: apiBaseUrl}) => {
423
+ const postData = {
424
+ challenge: challenge,
425
+ sessionId: sessionId,
426
+ response: response
427
+ };
428
+ const fetchResultFn = async () => await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/browserApi/response`, {
429
+ method: "POST",
430
+ headers: {
431
+ "Content-Type": "application/json"
432
+ },
433
+ body: JSON.stringify(postData)
434
+ });
435
+ const responseResult = await withRetrySafeFetch(fetchResultFn, {
436
+ retries: 2,
437
+ retryHttpStatus: 404
438
+ });
439
+ if (responseResult.isErr()) {
440
+ return neverthrow.err(responseResult.error);
441
+ }
442
+ const data = await responseResult.value.json();
443
+ return neverthrow.ok(data);
444
+ };
445
+
381
446
  exports.CrossDeviceCallbackErrorType = void 0;
382
447
 
383
448
  (function(CrossDeviceCallbackErrorType) {
@@ -519,12 +584,12 @@ const requestCredentialsCrossDevice = async options => {
519
584
  });
520
585
  };
521
586
 
522
- var SameDeviceRequestCredentialsErrorMessage;
587
+ var SameDeviceRequestCredentialsErrorMessage$1;
523
588
 
524
589
  (function(SameDeviceRequestCredentialsErrorMessage) {
525
590
  SameDeviceRequestCredentialsErrorMessage["FailedToStoreChallenge"] = "Failed to store challenge";
526
591
  SameDeviceRequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
527
- })(SameDeviceRequestCredentialsErrorMessage || (SameDeviceRequestCredentialsErrorMessage = {}));
592
+ })(SameDeviceRequestCredentialsErrorMessage$1 || (SameDeviceRequestCredentialsErrorMessage$1 = {}));
528
593
 
529
594
  const requestCredentialsSameDevice = async options => {
530
595
  const {challenge: challenge, credentialQuery: credentialQuery, redirectUri: redirectUri, walletProviderId: walletProviderId, initialiseOptions: initialiseOptions} = options;
@@ -534,7 +599,7 @@ const requestCredentialsSameDevice = async options => {
534
599
  if (!storedChallenge) {
535
600
  return neverthrow.err({
536
601
  type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
537
- message: SameDeviceRequestCredentialsErrorMessage.FailedToStoreChallenge
602
+ message: SameDeviceRequestCredentialsErrorMessage$1.FailedToStoreChallenge
538
603
  });
539
604
  }
540
605
  const createSessionResult = await createSession({
@@ -547,7 +612,7 @@ const requestCredentialsSameDevice = async options => {
547
612
  if (createSessionResult.isErr()) {
548
613
  return neverthrow.err({
549
614
  type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
550
- message: SameDeviceRequestCredentialsErrorMessage.FailedToCreateSession,
615
+ message: SameDeviceRequestCredentialsErrorMessage$1.FailedToCreateSession,
551
616
  cause: createSessionResult.error
552
617
  });
553
618
  }
@@ -559,6 +624,71 @@ const requestCredentialsSameDevice = async options => {
559
624
  });
560
625
  };
561
626
 
627
+ var SameDeviceRequestCredentialsErrorMessage;
628
+
629
+ (function(SameDeviceRequestCredentialsErrorMessage) {
630
+ SameDeviceRequestCredentialsErrorMessage["FailedToStoreChallenge"] = "Failed to store challenge";
631
+ SameDeviceRequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
632
+ })(SameDeviceRequestCredentialsErrorMessage || (SameDeviceRequestCredentialsErrorMessage = {}));
633
+
634
+ const requestCredentialsDigitalCredentialsApi = async options => {
635
+ const {challenge: challenge, credentialQuery: credentialQuery, initialiseOptions: initialiseOptions} = options;
636
+ const {apiBaseUrl: apiBaseUrl} = initialiseOptions;
637
+ window.localStorage.setItem(LocalStorageKey.challenge, challenge);
638
+ const storedChallenge = window.localStorage.getItem(LocalStorageKey.challenge);
639
+ if (!storedChallenge) {
640
+ return neverthrow.err({
641
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
642
+ message: SameDeviceRequestCredentialsErrorMessage.FailedToStoreChallenge
643
+ });
644
+ }
645
+ const createSessionResult = await createDigitalCredentialsApiSession({
646
+ credentialQuery: credentialQuery,
647
+ challenge: storedChallenge,
648
+ apiBaseUrl: apiBaseUrl
649
+ });
650
+ if (createSessionResult.isErr()) {
651
+ return neverthrow.err({
652
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
653
+ message: SameDeviceRequestCredentialsErrorMessage.FailedToCreateSession,
654
+ cause: createSessionResult.error
655
+ });
656
+ }
657
+ const {request: request, sessionId: sessionId} = createSessionResult.value;
658
+ window.localStorage.setItem(LocalStorageKey.sessionId, sessionId);
659
+ let rawResponse;
660
+ try {
661
+ rawResponse = await navigator.identity.get(request);
662
+ } catch (_a) {
663
+ return neverthrow.err({
664
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
665
+ message: "Failed call to digital credentials api"
666
+ });
667
+ }
668
+ let response;
669
+ try {
670
+ response = JSON.parse(rawResponse.data);
671
+ } catch (_b) {
672
+ response = rawResponse.data;
673
+ }
674
+ const result = await getDigitalCredentialsApiSessionResult({
675
+ challenge: challenge,
676
+ sessionId: sessionId,
677
+ response: response,
678
+ apiBaseUrl: apiBaseUrl
679
+ });
680
+ if (result.isOk()) {
681
+ return neverthrow.ok({
682
+ sessionId: sessionId,
683
+ result: result.value
684
+ });
685
+ }
686
+ return neverthrow.err({
687
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
688
+ message: "Invalid response from digital credentials api"
689
+ });
690
+ };
691
+
562
692
  const requestCredentials = async options => {
563
693
  var _a;
564
694
  const initialiseOptions = getInitialiseOptions();
@@ -568,6 +698,24 @@ const requestCredentials = async options => {
568
698
  assertType(RequestCredentialsOptionsValidator, "Invalid request credential options")(options);
569
699
  const {challenge: challenge = generateChallenge()} = options;
570
700
  const mode = (_a = options.mode) !== null && _a !== void 0 ? _a : isMobileDetect(navigator.userAgent) ? exports.Mode.sameDevice : exports.Mode.crossDevice;
701
+ if (initialiseOptions.enableDigitalCredentialsApiCrossDeviceFlow && isDigitalCredentialsApiSupported() && mode === exports.Mode.crossDevice) {
702
+ console.log("Digital Credentials API support found, proceeding with request using API in cross device flow");
703
+ return await requestCredentialsDigitalCredentialsApi(Object.assign(Object.assign({}, options), {
704
+ initialiseOptions: initialiseOptions,
705
+ challenge: challenge
706
+ }));
707
+ } else if (initialiseOptions.enableDigitalCredentialsApiCrossDeviceFlow) {
708
+ console.log("Digital Credentials API support not found, falling back to OpenID4VP");
709
+ }
710
+ if (initialiseOptions.enableDigitalCredentialsApiSameDeviceFlow && isDigitalCredentialsApiSupported() && mode === exports.Mode.sameDevice) {
711
+ console.log("Digital Credentials API support found, proceeding with request using API in same device flow");
712
+ return await requestCredentialsDigitalCredentialsApi(Object.assign(Object.assign({}, options), {
713
+ initialiseOptions: initialiseOptions,
714
+ challenge: challenge
715
+ }));
716
+ } else if (initialiseOptions.enableDigitalCredentialsApiSameDeviceFlow) {
717
+ console.log("Digital Credentials API support not found, falling back to OpenID4VP");
718
+ }
571
719
  if (mode === exports.Mode.sameDevice && "redirectUri" in options) {
572
720
  return await requestCredentialsSameDevice(Object.assign(Object.assign({}, options), {
573
721
  initialiseOptions: initialiseOptions,
@@ -650,7 +798,8 @@ const handleRedirectCallback = async () => {
650
798
 
651
799
  const utils = {
652
800
  generateChallenge: generateChallenge,
653
- unwrap: unwrap
801
+ unwrap: unwrap,
802
+ isDigitalCredentialsApiSupported: isDigitalCredentialsApiSupported
654
803
  };
655
804
 
656
805
  exports.handleRedirectCallback = handleRedirectCallback;