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

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.
@@ -7,5 +7,6 @@ export type { InitialiseOptions, RequestCredentialsOptions, RequestCredentialsSa
7
7
  declare const utils: {
8
8
  generateChallenge: () => string;
9
9
  unwrap: <T = unknown>(result: import("neverthrow").Result<T, unknown>, errMessage?: string) => T;
10
+ isDigitalCredentialsApiSupported: () => boolean;
10
11
  };
11
12
  export { initialise, requestCredentials, handleRedirectCallback, utils };
@@ -0,0 +1,7 @@
1
+ import { Result } from "neverthrow";
2
+ import { RequestCredentialsError, DigitalCredentialsApiRequestOptions, DigitalCredentialsApiRequestCredentialsResponse } from "./types";
3
+ export declare enum SameDeviceRequestCredentialsErrorMessage {
4
+ FailedToStoreChallenge = "Failed to store challenge",
5
+ FailedToCreateSession = "Failed to create session"
6
+ }
7
+ export declare const requestCredentialsDigitalCredentialsApi: (options: DigitalCredentialsApiRequestOptions) => Promise<Result<DigitalCredentialsApiRequestCredentialsResponse, RequestCredentialsError>>;
@@ -255,3 +255,11 @@ export declare const CreateSessionResponseValidator: v.ObjectSchema<{
255
255
  readonly sessionUrl: v.StringSchema<undefined>;
256
256
  }, undefined>;
257
257
  /*** session end ***/
258
+ export type CreateDigitalCredentialsApiSessionResponse = {
259
+ sessionId: string;
260
+ request: any;
261
+ };
262
+ export declare const CreateDigitalCredentialsApiSessionResponseValidator: v.ObjectSchema<{
263
+ readonly sessionId: v.StringSchema<undefined>;
264
+ readonly request: v.ObjectSchema<{}, undefined>;
265
+ }, undefined>;
@@ -61,6 +61,11 @@ export type CrossDeviceRequestCredentialsOptions = {
61
61
  mode: Mode.crossDevice;
62
62
  initialiseOptions: InitialiseOptions;
63
63
  };
64
+ export type DigitalCredentialsApiRequestOptions = {
65
+ credentialQuery: CredentialQuery[];
66
+ challenge: string;
67
+ initialiseOptions: InitialiseOptions;
68
+ };
64
69
  /**
65
70
  * Options for the same device requestCredentials function
66
71
  */
@@ -265,10 +270,17 @@ export type MessageEvent = {
265
270
  export type CrossDeviceRequestCredentialsResponse = {
266
271
  sessionId: string;
267
272
  };
273
+ /**
274
+ * The response from the digital credentials api requestCredentials function
275
+ */
276
+ export type DigitalCredentialsApiRequestCredentialsResponse = {
277
+ sessionId: string;
278
+ result: PresentationSessionResult;
279
+ };
268
280
  /**
269
281
  * The response from the requestCredentials function
270
282
  */
271
- export type RequestCredentialsResponse = SameDeviceRequestCredentialsResponse | CrossDeviceRequestCredentialsResponse;
283
+ export type RequestCredentialsResponse = SameDeviceRequestCredentialsResponse | CrossDeviceRequestCredentialsResponse | DigitalCredentialsApiRequestCredentialsResponse;
272
284
  /**
273
285
  * The error type for the requestCredentials function
274
286
  */
@@ -296,7 +308,11 @@ export type HandleRedirectCallbackResponse = {
296
308
  */
297
309
  export type InitialiseOptions = {
298
310
  apiBaseUrl: string;
311
+ enableDigitalCredentialsApiSameDeviceFlow?: boolean;
312
+ enableDigitalCredentialsApiCrossDeviceFlow?: boolean;
299
313
  };
300
314
  export declare const InitialiseOptionsValidator: v.ObjectSchema<{
301
315
  readonly apiBaseUrl: v.StringSchema<undefined>;
316
+ readonly enableDigitalCredentialsApiSameDeviceFlow: v.OptionalSchema<v.BooleanSchema<undefined>, never>;
317
+ readonly enableDigitalCredentialsApiCrossDeviceFlow: v.OptionalSchema<v.BooleanSchema<undefined>, never>;
302
318
  }, undefined>;
@@ -1,6 +1,6 @@
1
1
  import { Result } from "neverthrow";
2
2
  import { SafeFetchValidateRespondError } from "../common/safeFetch";
3
- import { CreateSessionRequest, CreateSessionResponse, ExchangeSessionResultResponse } from "./types";
3
+ import { CreateSessionRequest, CreateSessionResponse, ExchangeSessionResultResponse, CreateDigitalCredentialsApiSessionResponse } from "./types";
4
4
  /**
5
5
  * Generates a challenge string using the window.crypto API.
6
6
  *
@@ -50,3 +50,35 @@ export declare const exchangeSessionResult: ({ challenge, responseCode, sessionI
50
50
  * @returns A boolean indicating whether the user agent is a mobile device.
51
51
  */
52
52
  export declare const isMobileDetect: (userAgent: string) => boolean;
53
+ /**
54
+ * Detects if digital credentials api is available.
55
+ *
56
+ * @returns A boolean indicating whether the user agent supports the digital credential api.
57
+ */
58
+ export declare const isDigitalCredentialsApiSupported: () => boolean;
59
+ /**
60
+ * Creates a new digital credentials api session with the provided parameters.
61
+ *
62
+ * @param credentialQuery - The credential query for the session.
63
+ * @param challenge - The challenge for the session.
64
+ * @param apiBaseUrl - The base URL of the API.
65
+ * @returns A promise that resolves to a result containing either the created session response or an error.
66
+ */
67
+ export declare const createDigitalCredentialsApiSession: ({ credentialQuery, challenge, apiBaseUrl, }: CreateSessionRequest & {
68
+ apiBaseUrl: string;
69
+ }) => Promise<Result<CreateDigitalCredentialsApiSessionResponse, SafeFetchValidateRespondError>>;
70
+ /**
71
+ * Retrieves the result of a session using the provided parameters.
72
+ *
73
+ * @param challenge - The challenge for the session.
74
+ * @param sessionId - The ID of the session.
75
+ * @param response - The response from the digital credentials api.
76
+ * @param apiBaseUrl - The base URL of the API.
77
+ * @returns A promise that resolves to a result containing either the session result response or an error.
78
+ */
79
+ export declare const getDigitalCredentialsApiSessionResult: ({ challenge, sessionId, response, apiBaseUrl, }: {
80
+ challenge: string;
81
+ sessionId: string;
82
+ response: any;
83
+ apiBaseUrl: string;
84
+ }) => Promise<Result<any, SafeFetchValidateRespondError>>;
@@ -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-20
11
- * Version: 1.0.1
10
+ * Generated: 2024-10-21
11
+ * Version: 2.0.0-preview-digital-credential-api.2
12
12
  * Dependencies:
13
13
  *
14
14
  * neverthrow -- 4.3.0
@@ -1332,6 +1332,10 @@
1332
1332
  sessionId: string(),
1333
1333
  sessionUrl: string()
1334
1334
  });
1335
+ const CreateDigitalCredentialsApiSessionResponseValidator = object({
1336
+ sessionId: string(),
1337
+ request: object({})
1338
+ });
1335
1339
  var LocalStorageKey;
1336
1340
  (function(LocalStorageKey) {
1337
1341
  LocalStorageKey["challenge"] = "mattr_chg";
@@ -1382,7 +1386,9 @@
1382
1386
  RequestCredentialsErrorType["RequestCredentialsFailed"] = "RequestCredentialsFailed";
1383
1387
  })(exports.RequestCredentialsErrorType || (exports.RequestCredentialsErrorType = {}));
1384
1388
  const InitialiseOptionsValidator = object({
1385
- apiBaseUrl: string()
1389
+ apiBaseUrl: string(),
1390
+ enableDigitalCredentialsApiSameDeviceFlow: optional(_boolean()),
1391
+ enableDigitalCredentialsApiCrossDeviceFlow: optional(_boolean())
1386
1392
  });
1387
1393
  let initialiseOptions = undefined;
1388
1394
  var InitialiseErrorMessage;
@@ -1506,6 +1512,61 @@
1506
1512
  ua: userAgent,
1507
1513
  tablet: false
1508
1514
  });
1515
+ const isDigitalCredentialsApiSupported = () => {
1516
+ var _a;
1517
+ try {
1518
+ return typeof ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.identity) === null || _a === void 0 ? void 0 : _a.get) === "function";
1519
+ } catch (error) {
1520
+ return false;
1521
+ }
1522
+ };
1523
+ const createDigitalCredentialsApiSession = async ({credentialQuery: credentialQuery, challenge: challenge, apiBaseUrl: apiBaseUrl}) => {
1524
+ const postData = {
1525
+ credentialQuery: credentialQuery,
1526
+ challenge: challenge
1527
+ };
1528
+ const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/browserApi/request`, {
1529
+ method: "POST",
1530
+ headers: {
1531
+ "Content-Type": "application/json"
1532
+ },
1533
+ body: JSON.stringify(postData)
1534
+ });
1535
+ if (responseResult.isErr()) {
1536
+ return err(responseResult.error);
1537
+ }
1538
+ const data = await responseResult.value.json();
1539
+ if (!isType(CreateDigitalCredentialsApiSessionResponseValidator)(data)) {
1540
+ return err({
1541
+ type: SafeFetchCommonRespondErrorType.UnexpectedRespond,
1542
+ message: "Create digital credentials api session return unsupported response"
1543
+ });
1544
+ }
1545
+ return ok(data);
1546
+ };
1547
+ const getDigitalCredentialsApiSessionResult = async ({challenge: challenge, sessionId: sessionId, response: response, apiBaseUrl: apiBaseUrl}) => {
1548
+ const postData = {
1549
+ challenge: challenge,
1550
+ sessionId: sessionId,
1551
+ response: response
1552
+ };
1553
+ const fetchResultFn = async () => await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/browserApi/response`, {
1554
+ method: "POST",
1555
+ headers: {
1556
+ "Content-Type": "application/json"
1557
+ },
1558
+ body: JSON.stringify(postData)
1559
+ });
1560
+ const responseResult = await withRetrySafeFetch(fetchResultFn, {
1561
+ retries: 2,
1562
+ retryHttpStatus: 404
1563
+ });
1564
+ if (responseResult.isErr()) {
1565
+ return err(responseResult.error);
1566
+ }
1567
+ const data = await responseResult.value.json();
1568
+ return ok(data);
1569
+ };
1509
1570
  exports.CrossDeviceCallbackErrorType = void 0;
1510
1571
  (function(CrossDeviceCallbackErrorType) {
1511
1572
  CrossDeviceCallbackErrorType["Timeout"] = "Timeout";
@@ -1635,11 +1696,11 @@
1635
1696
  sessionId: sessionId
1636
1697
  });
1637
1698
  };
1638
- var SameDeviceRequestCredentialsErrorMessage;
1699
+ var SameDeviceRequestCredentialsErrorMessage$1;
1639
1700
  (function(SameDeviceRequestCredentialsErrorMessage) {
1640
1701
  SameDeviceRequestCredentialsErrorMessage["FailedToStoreChallenge"] = "Failed to store challenge";
1641
1702
  SameDeviceRequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
1642
- })(SameDeviceRequestCredentialsErrorMessage || (SameDeviceRequestCredentialsErrorMessage = {}));
1703
+ })(SameDeviceRequestCredentialsErrorMessage$1 || (SameDeviceRequestCredentialsErrorMessage$1 = {}));
1643
1704
  const requestCredentialsSameDevice = async options => {
1644
1705
  const {challenge: challenge, credentialQuery: credentialQuery, redirectUri: redirectUri, walletProviderId: walletProviderId, initialiseOptions: initialiseOptions} = options;
1645
1706
  const {apiBaseUrl: apiBaseUrl} = initialiseOptions;
@@ -1648,7 +1709,7 @@
1648
1709
  if (!storedChallenge) {
1649
1710
  return err({
1650
1711
  type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
1651
- message: SameDeviceRequestCredentialsErrorMessage.FailedToStoreChallenge
1712
+ message: SameDeviceRequestCredentialsErrorMessage$1.FailedToStoreChallenge
1652
1713
  });
1653
1714
  }
1654
1715
  const createSessionResult = await createSession({
@@ -1661,7 +1722,7 @@
1661
1722
  if (createSessionResult.isErr()) {
1662
1723
  return err({
1663
1724
  type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
1664
- message: SameDeviceRequestCredentialsErrorMessage.FailedToCreateSession,
1725
+ message: SameDeviceRequestCredentialsErrorMessage$1.FailedToCreateSession,
1665
1726
  cause: createSessionResult.error
1666
1727
  });
1667
1728
  }
@@ -1672,6 +1733,68 @@
1672
1733
  sessionId: sessionId
1673
1734
  });
1674
1735
  };
1736
+ var SameDeviceRequestCredentialsErrorMessage;
1737
+ (function(SameDeviceRequestCredentialsErrorMessage) {
1738
+ SameDeviceRequestCredentialsErrorMessage["FailedToStoreChallenge"] = "Failed to store challenge";
1739
+ SameDeviceRequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
1740
+ })(SameDeviceRequestCredentialsErrorMessage || (SameDeviceRequestCredentialsErrorMessage = {}));
1741
+ const requestCredentialsDigitalCredentialsApi = async options => {
1742
+ const {challenge: challenge, credentialQuery: credentialQuery, initialiseOptions: initialiseOptions} = options;
1743
+ const {apiBaseUrl: apiBaseUrl} = initialiseOptions;
1744
+ window.localStorage.setItem(LocalStorageKey.challenge, challenge);
1745
+ const storedChallenge = window.localStorage.getItem(LocalStorageKey.challenge);
1746
+ if (!storedChallenge) {
1747
+ return err({
1748
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
1749
+ message: SameDeviceRequestCredentialsErrorMessage.FailedToStoreChallenge
1750
+ });
1751
+ }
1752
+ const createSessionResult = await createDigitalCredentialsApiSession({
1753
+ credentialQuery: credentialQuery,
1754
+ challenge: storedChallenge,
1755
+ apiBaseUrl: apiBaseUrl
1756
+ });
1757
+ if (createSessionResult.isErr()) {
1758
+ return err({
1759
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
1760
+ message: SameDeviceRequestCredentialsErrorMessage.FailedToCreateSession,
1761
+ cause: createSessionResult.error
1762
+ });
1763
+ }
1764
+ const {request: request, sessionId: sessionId} = createSessionResult.value;
1765
+ window.localStorage.setItem(LocalStorageKey.sessionId, sessionId);
1766
+ let rawResponse;
1767
+ try {
1768
+ rawResponse = await navigator.identity.get(request);
1769
+ } catch (_a) {
1770
+ return err({
1771
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
1772
+ message: "Failed call to digital credentials api"
1773
+ });
1774
+ }
1775
+ let response;
1776
+ try {
1777
+ response = JSON.parse(rawResponse.data);
1778
+ } catch (_b) {
1779
+ response = rawResponse.data;
1780
+ }
1781
+ const result = await getDigitalCredentialsApiSessionResult({
1782
+ challenge: challenge,
1783
+ sessionId: sessionId,
1784
+ response: response,
1785
+ apiBaseUrl: apiBaseUrl
1786
+ });
1787
+ if (result.isOk()) {
1788
+ return ok({
1789
+ sessionId: sessionId,
1790
+ result: result.value
1791
+ });
1792
+ }
1793
+ return err({
1794
+ type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
1795
+ message: "Invalid response from digital credentials api"
1796
+ });
1797
+ };
1675
1798
  const requestCredentials = async options => {
1676
1799
  var _a;
1677
1800
  const initialiseOptions = getInitialiseOptions();
@@ -1681,6 +1804,24 @@
1681
1804
  assertType(RequestCredentialsOptionsValidator, "Invalid request credential options")(options);
1682
1805
  const {challenge: challenge = generateChallenge()} = options;
1683
1806
  const mode = (_a = options.mode) !== null && _a !== void 0 ? _a : isMobileDetect(navigator.userAgent) ? exports.Mode.sameDevice : exports.Mode.crossDevice;
1807
+ if (initialiseOptions.enableDigitalCredentialsApiCrossDeviceFlow && isDigitalCredentialsApiSupported() && mode === exports.Mode.crossDevice) {
1808
+ console.log("Digital Credentials API support found, proceeding with request using API in cross device flow");
1809
+ return await requestCredentialsDigitalCredentialsApi(Object.assign(Object.assign({}, options), {
1810
+ initialiseOptions: initialiseOptions,
1811
+ challenge: challenge
1812
+ }));
1813
+ } else if (initialiseOptions.enableDigitalCredentialsApiCrossDeviceFlow) {
1814
+ console.log("Digital Credentials API support not found, falling back to OpenID4VP");
1815
+ }
1816
+ if (initialiseOptions.enableDigitalCredentialsApiSameDeviceFlow && isDigitalCredentialsApiSupported() && mode === exports.Mode.sameDevice) {
1817
+ console.log("Digital Credentials API support found, proceeding with request using API in same device flow");
1818
+ return await requestCredentialsDigitalCredentialsApi(Object.assign(Object.assign({}, options), {
1819
+ initialiseOptions: initialiseOptions,
1820
+ challenge: challenge
1821
+ }));
1822
+ } else if (initialiseOptions.enableDigitalCredentialsApiSameDeviceFlow) {
1823
+ console.log("Digital Credentials API support not found, falling back to OpenID4VP");
1824
+ }
1684
1825
  if (mode === exports.Mode.sameDevice && "redirectUri" in options) {
1685
1826
  return await requestCredentialsSameDevice(Object.assign(Object.assign({}, options), {
1686
1827
  initialiseOptions: initialiseOptions,
@@ -1757,7 +1898,8 @@
1757
1898
  };
1758
1899
  const utils = {
1759
1900
  generateChallenge: generateChallenge,
1760
- unwrap: unwrap
1901
+ unwrap: unwrap,
1902
+ isDigitalCredentialsApiSupported: isDigitalCredentialsApiSupported
1761
1903
  };
1762
1904
  exports.handleRedirectCallback = handleRedirectCallback;
1763
1905
  exports.initialise = initialise;