@mattrglobal/verifier-sdk-web 1.1.1-unstable.91 → 1.1.1-unstable.94
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 +12 -17
- package/dist/lib/verifier-js-no-deps.cjs.js +279 -92
- package/dist/lib/verifier-js-no-deps.cjs.js.map +1 -1
- package/dist/lib/verifier-js.cjs.js +269 -111
- package/dist/lib/verifier-js.cjs.js.map +1 -1
- package/dist/typings/common/safeFetch.d.ts +3 -1
- package/dist/typings/common/sleep.d.ts +1 -0
- package/dist/typings/index.d.ts +5 -6
- package/dist/typings/verifier/abortCredentialRequest.d.ts +6 -0
- package/dist/typings/verifier/handleRedirectCallback.d.ts +1 -1
- package/dist/typings/verifier/index.d.ts +1 -0
- package/dist/typings/verifier/instanceContext.d.ts +7 -0
- package/dist/typings/verifier/requestCredentialsCrossDevice.d.ts +3 -47
- package/dist/typings/verifier/requestCredentialsSameDevice.d.ts +1 -1
- package/dist/typings/verifier/types/credential-presentation.d.ts +31 -0
- package/dist/typings/verifier/types/verifier-web-sdk.d.ts +48 -58
- package/dist/typings/verifier/utils.d.ts +18 -2
- package/dist/verifier-js.development.js +245 -106
- package/dist/verifier-js.development.js.map +1 -1
- package/dist/verifier-js.production.esm.js +2 -2
- package/dist/verifier-js.production.esm.js.map +1 -1
- package/dist/verifier-js.production.js +2 -2
- package/dist/verifier-js.production.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -203,15 +203,13 @@ const result = await MATTRVerifierSDK.requestCredentials({
|
|
|
203
203
|
challenge: MATTRVerifierSDK.utils.generateChallenge(), // Pass a unique challenge
|
|
204
204
|
walletProviderId, // Define the wallet identifier
|
|
205
205
|
redirectUri, // Define the redirect URI (not required for cross-device only requests)
|
|
206
|
-
crossDeviceCallback: { // Define how to handle completion/failure of cross-device flows (not required for same-device only requests)
|
|
207
|
-
onComplete: (result) => {
|
|
208
|
-
console.info("<<< MATTRVerifierSDK.requestCredentials crossDeviceCallback.onComplete", result);
|
|
209
|
-
},
|
|
210
|
-
onFailure: (error) => {
|
|
211
|
-
console.info("<<< MATTRVerifierSDK.requestCredentials crossDeviceCallback.onFailure", error);
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
206
|
});
|
|
207
|
+
|
|
208
|
+
if (result.isErr()) {
|
|
209
|
+
console.info("<<< MATTRVerifierSDK.requestCredentials succeed", result.error);
|
|
210
|
+
} else {
|
|
211
|
+
console.info("<<< MATTRVerifierSDK.requestCredentials failure", result.value);
|
|
212
|
+
}
|
|
215
213
|
```
|
|
216
214
|
* `apiBaseUrl` : Replace with the [`tenant_url`](https://learn.mattr.global/docs/platform-management/authentication) of your MATTR VII verifier tenant.
|
|
217
215
|
* `credentialQuery`: The credential query to be used in the request.
|
|
@@ -219,7 +217,6 @@ const result = await MATTRVerifierSDK.requestCredentials({
|
|
|
219
217
|
* `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.
|
|
220
218
|
* `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).
|
|
221
219
|
* `redirectUri` Replace with a URI that matches one of the values in the [`redirectUris` array](https://learn.mattr.global/api-reference/latest/tag/mDocs-verification#operation/postVerifierApplication!path=openid4vpConfiguration/redirectUris&t=request) in the MATTR VII tenant's verifier application configuration.
|
|
222
|
-
* `crossDeviceCallback`: Defines how to handle completion (`onComplete`) or failure (`onFailure`) of the verification workflow.
|
|
223
220
|
|
|
224
221
|
## Request credentials with explicit same-device flow
|
|
225
222
|
|
|
@@ -253,15 +250,13 @@ const result = await MATTRVerifierSDK.requestCredentials({
|
|
|
253
250
|
challenge: MATTRVerifierSDK.utils.generateChallenge(),
|
|
254
251
|
walletProviderId,
|
|
255
252
|
mode: "crossDevice",
|
|
256
|
-
crossDeviceCallback: {
|
|
257
|
-
onComplete: (result) => {
|
|
258
|
-
console.info("<<< MATTRVerifierSDK.requestCredentials crossDeviceCallback.onComplete", result);
|
|
259
|
-
},
|
|
260
|
-
onFailure: (error) => {
|
|
261
|
-
console.info("<<< MATTRVerifierSDK.requestCredentials crossDeviceCallback.onFailure", error);
|
|
262
|
-
},
|
|
263
|
-
},
|
|
264
253
|
});
|
|
254
|
+
|
|
255
|
+
if (result.isErr()) {
|
|
256
|
+
console.info("<<< MATTRVerifierSDK.requestCredentials succeed", result.error);
|
|
257
|
+
} else {
|
|
258
|
+
console.info("<<< MATTRVerifierSDK.requestCredentials failure", result.value);
|
|
259
|
+
}
|
|
265
260
|
```
|
|
266
261
|
|
|
267
262
|
* `mode`: When set to `crossDevice`, the SDK will only support cross-device flow in this verification workflow.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Do Not Translate or Localize
|
|
8
8
|
*
|
|
9
9
|
* Bundle of @mattrglobal/verifier-sdk-web
|
|
10
|
-
* Generated: 2025-02-
|
|
10
|
+
* Generated: 2025-02-25
|
|
11
11
|
* Version: 1.1.0
|
|
12
12
|
* Dependencies:
|
|
13
13
|
*/
|
|
@@ -164,6 +164,15 @@ exports.OpenidPresentationCredentialProfileSupported = void 0;
|
|
|
164
164
|
OpenidPresentationCredentialProfileSupported["MOBILE"] = "mobile";
|
|
165
165
|
})(exports.OpenidPresentationCredentialProfileSupported || (exports.OpenidPresentationCredentialProfileSupported = {}));
|
|
166
166
|
|
|
167
|
+
var PresentationStatusCode;
|
|
168
|
+
|
|
169
|
+
(function(PresentationStatusCode) {
|
|
170
|
+
PresentationStatusCode["AwaitingRequestRetrieval"] = "AwaitingRequestRetrieval";
|
|
171
|
+
PresentationStatusCode["AwaitingResponse"] = "AwaitingResponse";
|
|
172
|
+
PresentationStatusCode["ResponseSubmitted"] = "ResponseSubmitted";
|
|
173
|
+
PresentationStatusCode["ResultReady"] = "ResultReady";
|
|
174
|
+
})(PresentationStatusCode || (PresentationStatusCode = {}));
|
|
175
|
+
|
|
167
176
|
const CredentialQueryValidator = v__namespace.object({
|
|
168
177
|
profile: v__namespace.picklist([ exports.OpenidPresentationCredentialProfileSupported.MOBILE ]),
|
|
169
178
|
docType: v__namespace.string(),
|
|
@@ -200,9 +209,27 @@ v__namespace.object({
|
|
|
200
209
|
|
|
201
210
|
const CreateSessionResponseValidator = v__namespace.object({
|
|
202
211
|
sessionId: v__namespace.string(),
|
|
212
|
+
sessionKey: v__namespace.string(),
|
|
203
213
|
sessionUrl: v__namespace.string()
|
|
204
214
|
});
|
|
205
215
|
|
|
216
|
+
v__namespace.object({
|
|
217
|
+
sessionId: v__namespace.string(),
|
|
218
|
+
sessionKey: v__namespace.string()
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
v__namespace.object({
|
|
222
|
+
sessionId: v__namespace.string(),
|
|
223
|
+
sessionKey: v__namespace.string()
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const GetSessionStatusResponseValidator = v__namespace.union([ v__namespace.object({
|
|
227
|
+
status: v__namespace.picklist([ PresentationStatusCode.ResultReady ]),
|
|
228
|
+
responseCode: v__namespace.optional(v__namespace.string())
|
|
229
|
+
}), v__namespace.object({
|
|
230
|
+
status: v__namespace.string()
|
|
231
|
+
}) ]);
|
|
232
|
+
|
|
206
233
|
var LocalStorageKey;
|
|
207
234
|
|
|
208
235
|
(function(LocalStorageKey) {
|
|
@@ -235,10 +262,6 @@ const RequestCredentialsSameDeviceOptionsValidator = v__namespace.object({
|
|
|
235
262
|
|
|
236
263
|
const RequestCredentialsCrossDeviceOptionsValidator = v__namespace.object({
|
|
237
264
|
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
238
|
-
crossDeviceCallback: v__namespace.object({
|
|
239
|
-
onComplete: v__namespace.function(),
|
|
240
|
-
onFailure: v__namespace.function()
|
|
241
|
-
}),
|
|
242
265
|
challenge: v__namespace.optional(v__namespace.string()),
|
|
243
266
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
244
267
|
mode: v__namespace.picklist([ exports.Mode.crossDevice ])
|
|
@@ -246,10 +269,6 @@ const RequestCredentialsCrossDeviceOptionsValidator = v__namespace.object({
|
|
|
246
269
|
|
|
247
270
|
const RequestCredentialsAutoDetectDeviceOptionsValidator = v__namespace.object({
|
|
248
271
|
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
249
|
-
crossDeviceCallback: v__namespace.object({
|
|
250
|
-
onComplete: v__namespace.function(),
|
|
251
|
-
onFailure: v__namespace.function()
|
|
252
|
-
}),
|
|
253
272
|
redirectUri: v__namespace.string(),
|
|
254
273
|
challenge: v__namespace.optional(v__namespace.string()),
|
|
255
274
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
@@ -262,11 +281,35 @@ exports.RequestCredentialsErrorType = void 0;
|
|
|
262
281
|
|
|
263
282
|
(function(RequestCredentialsErrorType) {
|
|
264
283
|
RequestCredentialsErrorType["RequestCredentialsFailed"] = "RequestCredentialsFailed";
|
|
284
|
+
RequestCredentialsErrorType["Timeout"] = "Timeout";
|
|
285
|
+
RequestCredentialsErrorType["Abort"] = "Abort";
|
|
265
286
|
})(exports.RequestCredentialsErrorType || (exports.RequestCredentialsErrorType = {}));
|
|
266
287
|
|
|
288
|
+
var RequestCredentialsErrorMessage;
|
|
289
|
+
|
|
290
|
+
(function(RequestCredentialsErrorMessage) {
|
|
291
|
+
RequestCredentialsErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
292
|
+
RequestCredentialsErrorMessage["FailedToGetSessionStatus"] = "Failed to get session status";
|
|
293
|
+
RequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
|
|
294
|
+
RequestCredentialsErrorMessage["Abort"] = "User aborted the session";
|
|
295
|
+
RequestCredentialsErrorMessage["Timeout"] = "User session timeout";
|
|
296
|
+
})(RequestCredentialsErrorMessage || (RequestCredentialsErrorMessage = {}));
|
|
297
|
+
|
|
298
|
+
exports.AbortSessionErrorType = void 0;
|
|
299
|
+
|
|
300
|
+
(function(AbortSessionErrorType) {
|
|
301
|
+
AbortSessionErrorType["AbortSessionFailed"] = "AbortSessionFailed";
|
|
302
|
+
})(exports.AbortSessionErrorType || (exports.AbortSessionErrorType = {}));
|
|
303
|
+
|
|
304
|
+
var AbortSessionErrorMessage;
|
|
305
|
+
|
|
306
|
+
(function(AbortSessionErrorMessage) {
|
|
307
|
+
AbortSessionErrorMessage["FailedToAbortSession"] = "Failed to abort session";
|
|
308
|
+
})(AbortSessionErrorMessage || (AbortSessionErrorMessage = {}));
|
|
309
|
+
|
|
267
310
|
const InitialiseOptionsValidator = v__namespace.object({
|
|
268
|
-
apiBaseUrl: v__namespace.string(),
|
|
269
|
-
applicationId: v__namespace.
|
|
311
|
+
apiBaseUrl: v__namespace.pipe(v__namespace.string(), v__namespace.nonEmpty("Must not be empty")),
|
|
312
|
+
applicationId: v__namespace.pipe(v__namespace.string(), v__namespace.nonEmpty("Must not be empty"))
|
|
270
313
|
});
|
|
271
314
|
|
|
272
315
|
let initialiseOptions = undefined;
|
|
@@ -284,10 +327,62 @@ const initialise = options => {
|
|
|
284
327
|
|
|
285
328
|
const getInitialiseOptions = () => initialiseOptions;
|
|
286
329
|
|
|
330
|
+
let sessionAbortController = undefined;
|
|
331
|
+
|
|
332
|
+
let _sessionId = undefined;
|
|
333
|
+
|
|
334
|
+
let _sessionKey = undefined;
|
|
335
|
+
|
|
336
|
+
const getActiveSession = () => {
|
|
337
|
+
const sessionId = _sessionId;
|
|
338
|
+
const sessionKey = _sessionKey;
|
|
339
|
+
if (sessionId) {
|
|
340
|
+
return {
|
|
341
|
+
sessionId: sessionId,
|
|
342
|
+
sessionKey: sessionKey
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
return undefined;
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
const setActiveSession = session => {
|
|
349
|
+
const {sessionId: sessionId, sessionKey: sessionKey} = session;
|
|
350
|
+
_sessionId = sessionId;
|
|
351
|
+
_sessionKey = sessionKey;
|
|
352
|
+
const abortController = new AbortController;
|
|
353
|
+
sessionAbortController = abortController;
|
|
354
|
+
return abortController;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const removeActiveSession = () => {
|
|
358
|
+
sessionAbortController === null || sessionAbortController === void 0 ? void 0 : sessionAbortController.abort();
|
|
359
|
+
sessionAbortController = undefined;
|
|
360
|
+
_sessionKey = undefined;
|
|
361
|
+
_sessionId = undefined;
|
|
362
|
+
};
|
|
363
|
+
|
|
287
364
|
const defaultRetryDelay = attempt => Math.pow(2, attempt) * 1e3;
|
|
288
365
|
|
|
289
366
|
const defaultRetry = 2;
|
|
290
367
|
|
|
368
|
+
const withRetry = async (fn, options) => {
|
|
369
|
+
const {retries: retries = defaultRetry, retryDelay: retryDelay = defaultRetryDelay, attempt: attempt = 0} = options;
|
|
370
|
+
try {
|
|
371
|
+
return await fn();
|
|
372
|
+
} catch (err) {
|
|
373
|
+
if (retries > 0) {
|
|
374
|
+
const delay = typeof retryDelay === "function" ? retryDelay(attempt) : retryDelay;
|
|
375
|
+
await new Promise((resolve => setTimeout(resolve, delay)));
|
|
376
|
+
return await withRetry(fn, Object.assign(Object.assign({}, options), {
|
|
377
|
+
retries: retries - 1,
|
|
378
|
+
retryDelay: retryDelay,
|
|
379
|
+
attempt: attempt + 1
|
|
380
|
+
}));
|
|
381
|
+
}
|
|
382
|
+
throw err;
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
|
|
291
386
|
const withRetrySafeFetch = async (fn, options) => {
|
|
292
387
|
const {retries: retries = defaultRetry, retryDelay: retryDelay = defaultRetryDelay, attempt: attempt = 0, retryHttpStatus: retryHttpStatus} = options;
|
|
293
388
|
const result = await fn();
|
|
@@ -317,13 +412,12 @@ const getHashParamValue = (hash, param) => {
|
|
|
317
412
|
};
|
|
318
413
|
|
|
319
414
|
const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl, applicationId: applicationId, walletProviderId: walletProviderId}) => {
|
|
320
|
-
const postData = Object.assign(Object.assign(
|
|
415
|
+
const postData = Object.assign(Object.assign({
|
|
321
416
|
credentialQuery: credentialQuery,
|
|
322
|
-
challenge: challenge
|
|
417
|
+
challenge: challenge,
|
|
418
|
+
applicationId: applicationId
|
|
323
419
|
}, redirectUri ? {
|
|
324
420
|
redirectUri: redirectUri
|
|
325
|
-
} : {}), applicationId ? {
|
|
326
|
-
applicationId: applicationId
|
|
327
421
|
} : {}), walletProviderId ? {
|
|
328
422
|
walletProviderId: walletProviderId
|
|
329
423
|
} : {});
|
|
@@ -347,6 +441,40 @@ const createSession = async ({credentialQuery: credentialQuery, challenge: chall
|
|
|
347
441
|
return neverthrow.ok(data);
|
|
348
442
|
};
|
|
349
443
|
|
|
444
|
+
const abortSession = async ({apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey}) => {
|
|
445
|
+
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/abort`, {
|
|
446
|
+
method: "POST",
|
|
447
|
+
headers: {
|
|
448
|
+
"Content-Type": "application/json",
|
|
449
|
+
Authorization: `Bearer ${sessionKey}`
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
if (responseResult.isErr()) {
|
|
453
|
+
return neverthrow.err(responseResult.error);
|
|
454
|
+
}
|
|
455
|
+
return neverthrow.ok(undefined);
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
const getSessionStatus = async ({apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey}) => {
|
|
459
|
+
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/status`, {
|
|
460
|
+
method: "GET",
|
|
461
|
+
headers: {
|
|
462
|
+
Authorization: `Bearer ${sessionKey}`
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
if (responseResult.isErr()) {
|
|
466
|
+
return neverthrow.err(responseResult.error);
|
|
467
|
+
}
|
|
468
|
+
const data = await responseResult.value.json();
|
|
469
|
+
if (!isType(GetSessionStatusResponseValidator)(data)) {
|
|
470
|
+
return neverthrow.err({
|
|
471
|
+
type: SafeFetchCommonRespondErrorType.UnexpectedRespond,
|
|
472
|
+
message: "Get session status return unsupported response"
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
return neverthrow.ok(data);
|
|
476
|
+
};
|
|
477
|
+
|
|
350
478
|
const exchangeSessionResult = async ({challenge: challenge, responseCode: responseCode, sessionId: sessionId, apiBaseUrl: apiBaseUrl}) => {
|
|
351
479
|
const postData = {
|
|
352
480
|
challenge: challenge,
|
|
@@ -384,33 +512,19 @@ const isMobileDetect = userAgent => isMobile.isMobile({
|
|
|
384
512
|
tablet: false
|
|
385
513
|
});
|
|
386
514
|
|
|
387
|
-
exports.CrossDeviceCallbackErrorType = void 0;
|
|
388
|
-
|
|
389
|
-
(function(CrossDeviceCallbackErrorType) {
|
|
390
|
-
CrossDeviceCallbackErrorType["Timeout"] = "Timeout";
|
|
391
|
-
CrossDeviceCallbackErrorType["Abort"] = "Abort";
|
|
392
|
-
CrossDeviceCallbackErrorType["RequestCredentialsFailed"] = "RequestCredentialsFailed";
|
|
393
|
-
})(exports.CrossDeviceCallbackErrorType || (exports.CrossDeviceCallbackErrorType = {}));
|
|
394
|
-
|
|
395
|
-
var CrossDeviceRequestCredentialsErrorMessage;
|
|
396
|
-
|
|
397
|
-
(function(CrossDeviceRequestCredentialsErrorMessage) {
|
|
398
|
-
CrossDeviceRequestCredentialsErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
399
|
-
CrossDeviceRequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
|
|
400
|
-
CrossDeviceRequestCredentialsErrorMessage["Abort"] = "User aborted the session";
|
|
401
|
-
CrossDeviceRequestCredentialsErrorMessage["Timeout"] = "User session timeout";
|
|
402
|
-
})(CrossDeviceRequestCredentialsErrorMessage || (CrossDeviceRequestCredentialsErrorMessage = {}));
|
|
403
|
-
|
|
404
515
|
var WindowEventListenerType;
|
|
405
516
|
|
|
406
517
|
(function(WindowEventListenerType) {
|
|
407
518
|
WindowEventListenerType["message"] = "message";
|
|
408
519
|
})(WindowEventListenerType || (WindowEventListenerType = {}));
|
|
409
520
|
|
|
410
|
-
let listener;
|
|
521
|
+
let listener = undefined;
|
|
411
522
|
|
|
412
523
|
const removeWindowMessageEventListener = () => {
|
|
413
|
-
|
|
524
|
+
if (listener) {
|
|
525
|
+
window.removeEventListener(WindowEventListenerType.message, listener, false);
|
|
526
|
+
}
|
|
527
|
+
listener = undefined;
|
|
414
528
|
};
|
|
415
529
|
|
|
416
530
|
const closeCrossDeviceModal = options => {
|
|
@@ -422,8 +536,7 @@ const closeCrossDeviceModal = options => {
|
|
|
422
536
|
};
|
|
423
537
|
|
|
424
538
|
const receiveMessageHandler = options => async event => {
|
|
425
|
-
const {
|
|
426
|
-
const {onComplete: onComplete, onFailure: onFailure} = crossDeviceCallback;
|
|
539
|
+
const {onComplete: onComplete, onFailure: onFailure, container: container, sessionId: sessionId, apiBaseUrl: apiBaseUrl, challenge: challenge} = options;
|
|
427
540
|
if (event.origin !== apiBaseUrl) {
|
|
428
541
|
return;
|
|
429
542
|
}
|
|
@@ -437,8 +550,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
437
550
|
});
|
|
438
551
|
if (result.isErr()) {
|
|
439
552
|
onFailure({
|
|
440
|
-
type: exports.
|
|
441
|
-
message:
|
|
553
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
554
|
+
message: RequestCredentialsErrorMessage.FailedToGetSessionResult
|
|
442
555
|
});
|
|
443
556
|
closeCrossDeviceModal({
|
|
444
557
|
container: container
|
|
@@ -446,8 +559,9 @@ const receiveMessageHandler = options => async event => {
|
|
|
446
559
|
return;
|
|
447
560
|
}
|
|
448
561
|
onComplete({
|
|
449
|
-
result: result.value,
|
|
450
|
-
sessionId: result.value.sessionId
|
|
562
|
+
result: "challenge" in result.value ? result.value : undefined,
|
|
563
|
+
sessionId: result.value.sessionId,
|
|
564
|
+
sessionCompletedInRedirect: false
|
|
451
565
|
});
|
|
452
566
|
closeCrossDeviceModal({
|
|
453
567
|
container: container
|
|
@@ -456,8 +570,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
456
570
|
}
|
|
457
571
|
if (event.data.type === MessageEventDataType.PresentationTimeout) {
|
|
458
572
|
onFailure({
|
|
459
|
-
type: exports.
|
|
460
|
-
message:
|
|
573
|
+
type: exports.RequestCredentialsErrorType.Timeout,
|
|
574
|
+
message: RequestCredentialsErrorMessage.Timeout
|
|
461
575
|
});
|
|
462
576
|
closeCrossDeviceModal({
|
|
463
577
|
container: container
|
|
@@ -466,8 +580,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
466
580
|
}
|
|
467
581
|
if (event.data.type === MessageEventDataType.PresentationAbort) {
|
|
468
582
|
onFailure({
|
|
469
|
-
type: exports.
|
|
470
|
-
message:
|
|
583
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
584
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
471
585
|
});
|
|
472
586
|
closeCrossDeviceModal({
|
|
473
587
|
container: container
|
|
@@ -493,7 +607,7 @@ const openCrossDeviceModal = options => {
|
|
|
493
607
|
};
|
|
494
608
|
|
|
495
609
|
const requestCredentialsCrossDevice = async options => {
|
|
496
|
-
const {challenge: challenge, walletProviderId: walletProviderId, credentialQuery: credentialQuery,
|
|
610
|
+
const {challenge: challenge, walletProviderId: walletProviderId, credentialQuery: credentialQuery, initialiseOptions: initialiseOptions} = options;
|
|
497
611
|
const {apiBaseUrl: apiBaseUrl, applicationId: applicationId} = initialiseOptions;
|
|
498
612
|
const createSessionResult = await createSession({
|
|
499
613
|
credentialQuery: credentialQuery,
|
|
@@ -505,28 +619,49 @@ const requestCredentialsCrossDevice = async options => {
|
|
|
505
619
|
if (createSessionResult.isErr()) {
|
|
506
620
|
return neverthrow.err({
|
|
507
621
|
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
508
|
-
message:
|
|
622
|
+
message: RequestCredentialsErrorMessage.FailedToCreateSession,
|
|
509
623
|
cause: createSessionResult.error
|
|
510
624
|
});
|
|
511
625
|
}
|
|
512
|
-
const {sessionUrl: sessionUrl, sessionId: sessionId} = createSessionResult.value;
|
|
626
|
+
const {sessionUrl: sessionUrl, sessionId: sessionId, sessionKey: sessionKey} = createSessionResult.value;
|
|
513
627
|
const container = openCrossDeviceModal({
|
|
514
|
-
sessionUrl: sessionUrl
|
|
515
|
-
crossDeviceCallback: crossDeviceCallback
|
|
516
|
-
});
|
|
517
|
-
listener = receiveMessageHandler({
|
|
518
|
-
crossDeviceCallback: crossDeviceCallback,
|
|
519
|
-
container: container,
|
|
520
|
-
sessionId: sessionId,
|
|
521
|
-
apiBaseUrl: apiBaseUrl,
|
|
522
|
-
challenge: challenge
|
|
523
|
-
});
|
|
524
|
-
window.addEventListener(WindowEventListenerType.message, listener, false);
|
|
525
|
-
return neverthrow.ok({
|
|
526
|
-
sessionId: sessionId
|
|
628
|
+
sessionUrl: sessionUrl
|
|
527
629
|
});
|
|
630
|
+
return await new Promise((resolve => {
|
|
631
|
+
const abortController = setActiveSession({
|
|
632
|
+
sessionId: sessionId,
|
|
633
|
+
sessionKey: sessionKey
|
|
634
|
+
});
|
|
635
|
+
abortController.signal.addEventListener("abort", (() => {
|
|
636
|
+
closeCrossDeviceModal({
|
|
637
|
+
container: container
|
|
638
|
+
});
|
|
639
|
+
resolve(neverthrow.err({
|
|
640
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
641
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
642
|
+
}));
|
|
643
|
+
}));
|
|
644
|
+
removeWindowMessageEventListener();
|
|
645
|
+
listener = receiveMessageHandler({
|
|
646
|
+
container: container,
|
|
647
|
+
sessionId: sessionId,
|
|
648
|
+
apiBaseUrl: apiBaseUrl,
|
|
649
|
+
challenge: challenge,
|
|
650
|
+
onComplete: data => resolve(neverthrow.ok(data)),
|
|
651
|
+
onFailure: error => resolve(neverthrow.err(error))
|
|
652
|
+
});
|
|
653
|
+
window.addEventListener(WindowEventListenerType.message, listener, false);
|
|
654
|
+
}));
|
|
528
655
|
};
|
|
529
656
|
|
|
657
|
+
const sleep = ms => new Promise((resolve => setTimeout(resolve, ms)));
|
|
658
|
+
|
|
659
|
+
const SESSION_STATUS_POLLING_MAX_RETRY = 1e3;
|
|
660
|
+
|
|
661
|
+
const SESSION_STATUS_POLLING_INTERVAL_MS = 3e3;
|
|
662
|
+
|
|
663
|
+
const SESSION_STATUS_POLLING_INITIAL_DELAY_MS = 3e3;
|
|
664
|
+
|
|
530
665
|
var SameDeviceRequestCredentialsErrorMessage;
|
|
531
666
|
|
|
532
667
|
(function(SameDeviceRequestCredentialsErrorMessage) {
|
|
@@ -537,17 +672,9 @@ var SameDeviceRequestCredentialsErrorMessage;
|
|
|
537
672
|
const requestCredentialsSameDevice = async options => {
|
|
538
673
|
const {challenge: challenge, credentialQuery: credentialQuery, redirectUri: redirectUri, walletProviderId: walletProviderId, initialiseOptions: initialiseOptions} = options;
|
|
539
674
|
const {apiBaseUrl: apiBaseUrl, applicationId: applicationId} = initialiseOptions;
|
|
540
|
-
window.localStorage.setItem(LocalStorageKey.challenge, challenge);
|
|
541
|
-
const storedChallenge = window.localStorage.getItem(LocalStorageKey.challenge);
|
|
542
|
-
if (!storedChallenge) {
|
|
543
|
-
return neverthrow.err({
|
|
544
|
-
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
545
|
-
message: SameDeviceRequestCredentialsErrorMessage.FailedToStoreChallenge
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
675
|
const createSessionResult = await createSession({
|
|
549
676
|
credentialQuery: credentialQuery,
|
|
550
|
-
challenge:
|
|
677
|
+
challenge: challenge,
|
|
551
678
|
redirectUri: redirectUri,
|
|
552
679
|
apiBaseUrl: apiBaseUrl,
|
|
553
680
|
applicationId: applicationId,
|
|
@@ -560,11 +687,52 @@ const requestCredentialsSameDevice = async options => {
|
|
|
560
687
|
cause: createSessionResult.error
|
|
561
688
|
});
|
|
562
689
|
}
|
|
563
|
-
const {sessionUrl: sessionUrl, sessionId: sessionId} = createSessionResult.value;
|
|
690
|
+
const {sessionUrl: sessionUrl, sessionKey: sessionKey, sessionId: sessionId} = createSessionResult.value;
|
|
691
|
+
const abortController = setActiveSession({
|
|
692
|
+
sessionId: sessionId,
|
|
693
|
+
sessionKey: sessionKey
|
|
694
|
+
});
|
|
564
695
|
window.localStorage.setItem(LocalStorageKey.sessionId, sessionId);
|
|
696
|
+
window.localStorage.setItem(LocalStorageKey.challenge, challenge);
|
|
565
697
|
window.location.assign(sessionUrl);
|
|
698
|
+
await sleep(SESSION_STATUS_POLLING_INITIAL_DELAY_MS);
|
|
699
|
+
const checkResult = await withRetry((async () => {
|
|
700
|
+
const statusResult = await getSessionStatus({
|
|
701
|
+
apiBaseUrl: apiBaseUrl,
|
|
702
|
+
applicationId: applicationId,
|
|
703
|
+
sessionId: sessionId,
|
|
704
|
+
sessionKey: sessionKey
|
|
705
|
+
});
|
|
706
|
+
if (abortController.signal.aborted) {
|
|
707
|
+
return neverthrow.err({
|
|
708
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
709
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
if (statusResult.isErr()) {
|
|
713
|
+
if (statusResult.error.status === 404) {
|
|
714
|
+
return neverthrow.err({
|
|
715
|
+
type: exports.RequestCredentialsErrorType.Timeout,
|
|
716
|
+
message: RequestCredentialsErrorMessage.Timeout
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
throw Error("Unexpected status response. Retry");
|
|
720
|
+
}
|
|
721
|
+
if (statusResult.value.status !== PresentationStatusCode.ResultReady) {
|
|
722
|
+
throw Error("Result is not ready. Retry");
|
|
723
|
+
}
|
|
724
|
+
return neverthrow.ok(undefined);
|
|
725
|
+
}), {
|
|
726
|
+
retries: SESSION_STATUS_POLLING_MAX_RETRY,
|
|
727
|
+
retryDelay: SESSION_STATUS_POLLING_INTERVAL_MS
|
|
728
|
+
});
|
|
729
|
+
if (checkResult.isErr()) {
|
|
730
|
+
return neverthrow.err(checkResult.error);
|
|
731
|
+
}
|
|
732
|
+
window.close();
|
|
566
733
|
return neverthrow.ok({
|
|
567
|
-
sessionId: sessionId
|
|
734
|
+
sessionId: sessionId,
|
|
735
|
+
sessionCompletedInRedirect: true
|
|
568
736
|
});
|
|
569
737
|
};
|
|
570
738
|
|
|
@@ -584,16 +752,11 @@ const requestCredentials = async options => {
|
|
|
584
752
|
mode: mode
|
|
585
753
|
}));
|
|
586
754
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
}));
|
|
593
|
-
}
|
|
594
|
-
throw new Exception("Invalid request credential options", {
|
|
595
|
-
data: options
|
|
596
|
-
});
|
|
755
|
+
return await requestCredentialsCrossDevice(Object.assign(Object.assign({}, options), {
|
|
756
|
+
initialiseOptions: initialiseOptions,
|
|
757
|
+
challenge: challenge,
|
|
758
|
+
mode: exports.Mode.crossDevice
|
|
759
|
+
}));
|
|
597
760
|
};
|
|
598
761
|
|
|
599
762
|
exports.HandleRedirectCallbackErrorType = void 0;
|
|
@@ -607,7 +770,7 @@ var HandleRedirectCallbackErrorMessage;
|
|
|
607
770
|
(function(HandleRedirectCallbackErrorMessage) {
|
|
608
771
|
HandleRedirectCallbackErrorMessage["FailedToFindResponseCode"] = "Failed to find response code";
|
|
609
772
|
HandleRedirectCallbackErrorMessage["FailedToFindChallenge"] = "Failed to find challenge";
|
|
610
|
-
HandleRedirectCallbackErrorMessage["
|
|
773
|
+
HandleRedirectCallbackErrorMessage["FailedToFindActiveSession"] = "Failed to find active session";
|
|
611
774
|
HandleRedirectCallbackErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
612
775
|
})(HandleRedirectCallbackErrorMessage || (HandleRedirectCallbackErrorMessage = {}));
|
|
613
776
|
|
|
@@ -624,18 +787,12 @@ const handleRedirectCallback = async () => {
|
|
|
624
787
|
message: HandleRedirectCallbackErrorMessage.FailedToFindResponseCode
|
|
625
788
|
});
|
|
626
789
|
}
|
|
627
|
-
const challenge = window.localStorage.getItem(LocalStorageKey.challenge);
|
|
628
|
-
if (!challenge) {
|
|
629
|
-
return neverthrow.err({
|
|
630
|
-
type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
|
|
631
|
-
message: HandleRedirectCallbackErrorMessage.FailedToFindChallenge
|
|
632
|
-
});
|
|
633
|
-
}
|
|
634
790
|
const sessionId = window.localStorage.getItem(LocalStorageKey.sessionId);
|
|
635
|
-
|
|
791
|
+
const challenge = window.localStorage.getItem(LocalStorageKey.challenge);
|
|
792
|
+
if (!sessionId || !challenge) {
|
|
636
793
|
return neverthrow.err({
|
|
637
794
|
type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
|
|
638
|
-
message: HandleRedirectCallbackErrorMessage.
|
|
795
|
+
message: HandleRedirectCallbackErrorMessage.FailedToFindActiveSession
|
|
639
796
|
});
|
|
640
797
|
}
|
|
641
798
|
const result = await exchangeSessionResult({
|
|
@@ -652,16 +809,46 @@ const handleRedirectCallback = async () => {
|
|
|
652
809
|
});
|
|
653
810
|
}
|
|
654
811
|
return neverthrow.ok({
|
|
655
|
-
result: result.value,
|
|
812
|
+
result: "challenge" in result.value ? result.value : undefined,
|
|
656
813
|
sessionId: result.value.sessionId
|
|
657
814
|
});
|
|
658
815
|
};
|
|
659
816
|
|
|
817
|
+
const abortCredentialRequest = async () => {
|
|
818
|
+
const initialiseOptions = getInitialiseOptions();
|
|
819
|
+
if (!initialiseOptions) {
|
|
820
|
+
throw new Exception(InitialiseErrorMessage.SdkNotInitialised);
|
|
821
|
+
}
|
|
822
|
+
const {apiBaseUrl: apiBaseUrl, applicationId: applicationId} = initialiseOptions;
|
|
823
|
+
const session = getActiveSession();
|
|
824
|
+
if (!session || !session.sessionKey) {
|
|
825
|
+
return neverthrow.ok(undefined);
|
|
826
|
+
}
|
|
827
|
+
const {sessionId: sessionId, sessionKey: sessionKey} = session;
|
|
828
|
+
removeActiveSession();
|
|
829
|
+
const abortSessionResult = await abortSession({
|
|
830
|
+
apiBaseUrl: apiBaseUrl,
|
|
831
|
+
applicationId: applicationId,
|
|
832
|
+
sessionId: sessionId,
|
|
833
|
+
sessionKey: sessionKey
|
|
834
|
+
});
|
|
835
|
+
if (abortSessionResult.isErr()) {
|
|
836
|
+
return neverthrow.err({
|
|
837
|
+
type: exports.AbortSessionErrorType.AbortSessionFailed,
|
|
838
|
+
message: AbortSessionErrorMessage.FailedToAbortSession,
|
|
839
|
+
cause: abortSessionResult.error
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
return neverthrow.ok(undefined);
|
|
843
|
+
};
|
|
844
|
+
|
|
660
845
|
const utils = {
|
|
661
846
|
generateChallenge: generateChallenge,
|
|
662
847
|
unwrap: unwrap
|
|
663
848
|
};
|
|
664
849
|
|
|
850
|
+
exports.abortCredentialRequest = abortCredentialRequest;
|
|
851
|
+
|
|
665
852
|
exports.handleRedirectCallback = handleRedirectCallback;
|
|
666
853
|
|
|
667
854
|
exports.initialise = initialise;
|