@mattrglobal/verifier-sdk-web 1.1.1-unstable.15 → 1.1.1-unstable.154
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 +39 -24
- package/dist/lib/verifier-js-no-deps.cjs.js +573 -185
- package/dist/lib/verifier-js-no-deps.cjs.js.map +1 -1
- package/dist/lib/verifier-js.cjs.js +699 -299
- package/dist/lib/verifier-js.cjs.js.map +1 -1
- package/dist/typings/common/safeFetch.d.ts +6 -3
- package/dist/typings/common/sleep.d.ts +1 -0
- package/dist/typings/index.d.ts +6 -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 +2 -0
- package/dist/typings/verifier/instanceContext.d.ts +7 -0
- package/dist/typings/verifier/requestCredentialsCrossDevice.d.ts +3 -47
- package/dist/typings/verifier/requestCredentialsDigitalCredentialsApi.d.ts +16 -0
- package/dist/typings/verifier/requestCredentialsSameDevice.d.ts +1 -1
- package/dist/typings/verifier/types/credential-presentation.d.ts +128 -20
- package/dist/typings/verifier/types/verifier-web-sdk.d.ts +126 -183
- package/dist/typings/verifier/utils.d.ts +25 -5
- package/dist/verifier-js.development.js +644 -281
- 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
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Do Not Translate or Localize
|
|
8
8
|
*
|
|
9
9
|
* Bundle of @mattrglobal/verifier-sdk-web
|
|
10
|
-
* Generated: 2025-
|
|
10
|
+
* Generated: 2025-05-18
|
|
11
11
|
* Version: 1.1.0
|
|
12
12
|
* Dependencies:
|
|
13
13
|
*/
|
|
@@ -89,47 +89,21 @@ const assertType = (validator, message) => data => {
|
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
-
var SafeFetchCommonRespondErrorType;
|
|
93
|
-
|
|
94
|
-
(function(SafeFetchCommonRespondErrorType) {
|
|
95
|
-
SafeFetchCommonRespondErrorType["UnexpectedRespond"] = "UnexpectedRespond";
|
|
96
|
-
})(SafeFetchCommonRespondErrorType || (SafeFetchCommonRespondErrorType = {}));
|
|
97
|
-
|
|
98
|
-
var SafeFetchErrorType;
|
|
99
|
-
|
|
100
|
-
(function(SafeFetchErrorType) {
|
|
101
|
-
SafeFetchErrorType["HttpError"] = "HttpError";
|
|
102
|
-
SafeFetchErrorType["UnknownError"] = "UnknownError";
|
|
103
|
-
})(SafeFetchErrorType || (SafeFetchErrorType = {}));
|
|
104
|
-
|
|
105
|
-
const safeFetch = async (input, init) => {
|
|
106
|
-
try {
|
|
107
|
-
const response = await fetch(input, init);
|
|
108
|
-
if (response.status > 299 || response.status < 200) {
|
|
109
|
-
return neverthrow.err({
|
|
110
|
-
type: SafeFetchErrorType.HttpError,
|
|
111
|
-
message: `HTTP error, status = ${response.status}`,
|
|
112
|
-
status: response.status
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
return neverthrow.ok(response);
|
|
116
|
-
} catch (error) {
|
|
117
|
-
return neverthrow.err({
|
|
118
|
-
type: SafeFetchErrorType.UnknownError,
|
|
119
|
-
message: "Unknown error",
|
|
120
|
-
cause: error
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
92
|
exports.MobileCredentialVerificationReasonType = void 0;
|
|
126
93
|
|
|
127
94
|
(function(MobileCredentialVerificationReasonType) {
|
|
128
|
-
MobileCredentialVerificationReasonType["
|
|
129
|
-
MobileCredentialVerificationReasonType["
|
|
130
|
-
MobileCredentialVerificationReasonType["
|
|
131
|
-
MobileCredentialVerificationReasonType["
|
|
132
|
-
MobileCredentialVerificationReasonType["
|
|
95
|
+
MobileCredentialVerificationReasonType["TrustedIssuerCertificateExpired"] = "TrustedIssuerCertificateExpired";
|
|
96
|
+
MobileCredentialVerificationReasonType["TrustedIssuerCertificateNotYetValid"] = "TrustedIssuerCertificateNotYetValid";
|
|
97
|
+
MobileCredentialVerificationReasonType["IssuerNotTrusted"] = "IssuerNotTrusted";
|
|
98
|
+
MobileCredentialVerificationReasonType["MobileCredentialInvalid"] = "MobileCredentialInvalid";
|
|
99
|
+
MobileCredentialVerificationReasonType["MobileCredentialExpired"] = "MobileCredentialExpired";
|
|
100
|
+
MobileCredentialVerificationReasonType["MobileCredentialNotYetValid"] = "MobileCredentialNotYetValid";
|
|
101
|
+
MobileCredentialVerificationReasonType["InvalidSignerCertificate"] = "InvalidSignerCertificate";
|
|
102
|
+
MobileCredentialVerificationReasonType["DeviceKeyInvalid"] = "DeviceKeyInvalid";
|
|
103
|
+
MobileCredentialVerificationReasonType["UnsupportedCurve"] = "UnsupportedCurve";
|
|
104
|
+
MobileCredentialVerificationReasonType["StatusRevoked"] = "StatusRevoked";
|
|
105
|
+
MobileCredentialVerificationReasonType["StatusSuspended"] = "StatusSuspended";
|
|
106
|
+
MobileCredentialVerificationReasonType["StatusUnknown"] = "StatusUnknown";
|
|
133
107
|
})(exports.MobileCredentialVerificationReasonType || (exports.MobileCredentialVerificationReasonType = {}));
|
|
134
108
|
|
|
135
109
|
exports.ClaimType = void 0;
|
|
@@ -164,6 +138,15 @@ exports.OpenidPresentationCredentialProfileSupported = void 0;
|
|
|
164
138
|
OpenidPresentationCredentialProfileSupported["MOBILE"] = "mobile";
|
|
165
139
|
})(exports.OpenidPresentationCredentialProfileSupported || (exports.OpenidPresentationCredentialProfileSupported = {}));
|
|
166
140
|
|
|
141
|
+
var PresentationStatusCode;
|
|
142
|
+
|
|
143
|
+
(function(PresentationStatusCode) {
|
|
144
|
+
PresentationStatusCode["AwaitingRequestRetrieval"] = "AwaitingRequestRetrieval";
|
|
145
|
+
PresentationStatusCode["AwaitingResponse"] = "AwaitingResponse";
|
|
146
|
+
PresentationStatusCode["ResponseSubmitted"] = "ResponseSubmitted";
|
|
147
|
+
PresentationStatusCode["ResultReady"] = "ResultReady";
|
|
148
|
+
})(PresentationStatusCode || (PresentationStatusCode = {}));
|
|
149
|
+
|
|
167
150
|
const CredentialQueryValidator = v__namespace.object({
|
|
168
151
|
profile: v__namespace.picklist([ exports.OpenidPresentationCredentialProfileSupported.MOBILE ]),
|
|
169
152
|
docType: v__namespace.string(),
|
|
@@ -191,18 +174,63 @@ const PresentationResultRelaxValidator = v__namespace.object({
|
|
|
191
174
|
error: v__namespace.optional(v__namespace.unknown())
|
|
192
175
|
});
|
|
193
176
|
|
|
177
|
+
exports.Mode = void 0;
|
|
178
|
+
|
|
179
|
+
(function(Mode) {
|
|
180
|
+
Mode["SameDevice"] = "sameDevice";
|
|
181
|
+
Mode["CrossDevice"] = "crossDevice";
|
|
182
|
+
})(exports.Mode || (exports.Mode = {}));
|
|
183
|
+
|
|
184
|
+
var SessionType;
|
|
185
|
+
|
|
186
|
+
(function(SessionType) {
|
|
187
|
+
SessionType["DigitalCredentialsApi"] = "digital-credentials-api";
|
|
188
|
+
SessionType["Openid4vp"] = "openid4vp";
|
|
189
|
+
})(SessionType || (SessionType = {}));
|
|
190
|
+
|
|
194
191
|
v__namespace.object({
|
|
195
192
|
credentialQuery: v__namespace.array(CredentialQueryValidator),
|
|
196
193
|
challenge: v__namespace.string(),
|
|
197
194
|
redirectUri: v__namespace.optional(v__namespace.string()),
|
|
198
|
-
walletProviderId: v__namespace.optional(v__namespace.string())
|
|
195
|
+
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
196
|
+
dcApiSupported: v__namespace.optional(v__namespace.boolean())
|
|
199
197
|
});
|
|
200
198
|
|
|
201
|
-
const
|
|
199
|
+
const CreateSessionDigitalCredentialsValidator = v__namespace.object({
|
|
200
|
+
type: v__namespace.literal(SessionType.DigitalCredentialsApi),
|
|
202
201
|
sessionId: v__namespace.string(),
|
|
202
|
+
sessionKey: v__namespace.string(),
|
|
203
|
+
sessionTtl: v__namespace.number(),
|
|
204
|
+
request: v__namespace.record(v__namespace.string(), v__namespace.any())
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const CreateSessionOpenId4vpResponseValidator = v__namespace.object({
|
|
208
|
+
type: v__namespace.optional(v__namespace.literal(SessionType.Openid4vp)),
|
|
209
|
+
sessionId: v__namespace.string(),
|
|
210
|
+
sessionKey: v__namespace.string(),
|
|
203
211
|
sessionUrl: v__namespace.string()
|
|
204
212
|
});
|
|
205
213
|
|
|
214
|
+
const CreateSessionResponseValidator = v__namespace.union([ CreateSessionDigitalCredentialsValidator, CreateSessionOpenId4vpResponseValidator ]);
|
|
215
|
+
|
|
216
|
+
v__namespace.object({
|
|
217
|
+
sessionId: v__namespace.string(),
|
|
218
|
+
sessionKey: v__namespace.string(),
|
|
219
|
+
apiBaseUrl: v__namespace.string()
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
v__namespace.object({
|
|
223
|
+
sessionId: v__namespace.string(),
|
|
224
|
+
sessionKey: v__namespace.string()
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const GetSessionStatusResponseValidator = v__namespace.union([ v__namespace.object({
|
|
228
|
+
status: v__namespace.picklist([ PresentationStatusCode.ResultReady ]),
|
|
229
|
+
responseCode: v__namespace.optional(v__namespace.string())
|
|
230
|
+
}), v__namespace.object({
|
|
231
|
+
status: v__namespace.string()
|
|
232
|
+
}) ]);
|
|
233
|
+
|
|
206
234
|
var LocalStorageKey;
|
|
207
235
|
|
|
208
236
|
(function(LocalStorageKey) {
|
|
@@ -210,12 +238,9 @@ var LocalStorageKey;
|
|
|
210
238
|
LocalStorageKey["sessionId"] = "mattr_sid";
|
|
211
239
|
})(LocalStorageKey || (LocalStorageKey = {}));
|
|
212
240
|
|
|
213
|
-
|
|
241
|
+
const MATTR_SDK_VERSION_HEADER = "x-mattr-sdk-version";
|
|
214
242
|
|
|
215
|
-
|
|
216
|
-
Mode["sameDevice"] = "sameDevice";
|
|
217
|
-
Mode["crossDevice"] = "crossDevice";
|
|
218
|
-
})(exports.Mode || (exports.Mode = {}));
|
|
243
|
+
const MATTR_SDK_VERSION_VALUE = "2.0.0";
|
|
219
244
|
|
|
220
245
|
var MessageEventDataType;
|
|
221
246
|
|
|
@@ -225,50 +250,106 @@ var MessageEventDataType;
|
|
|
225
250
|
MessageEventDataType["PresentationAbort"] = "PresentationAbort";
|
|
226
251
|
})(MessageEventDataType || (MessageEventDataType = {}));
|
|
227
252
|
|
|
228
|
-
const
|
|
229
|
-
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
230
|
-
redirectUri: v__namespace.string(),
|
|
231
|
-
challenge: v__namespace.optional(v__namespace.string()),
|
|
253
|
+
const OpenId4vpConfigSameDeviceOptionsValidator = v__namespace.object({
|
|
232
254
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
233
|
-
mode: v__namespace.
|
|
255
|
+
mode: v__namespace.literal(exports.Mode.SameDevice),
|
|
256
|
+
redirectUri: v__namespace.string()
|
|
234
257
|
});
|
|
235
258
|
|
|
236
|
-
const
|
|
237
|
-
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
|
-
challenge: v__namespace.optional(v__namespace.string()),
|
|
259
|
+
const OpenId4vpConfigCrossDeviceOptionsValidator = v__namespace.object({
|
|
243
260
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
244
|
-
mode: v__namespace.
|
|
261
|
+
mode: v__namespace.literal(exports.Mode.CrossDevice)
|
|
245
262
|
});
|
|
246
263
|
|
|
247
|
-
const
|
|
248
|
-
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
|
-
redirectUri: v__namespace.string(),
|
|
254
|
-
challenge: v__namespace.optional(v__namespace.string()),
|
|
264
|
+
const OpenId4vpConfigAutoDetectOptionsValidator = v__namespace.object({
|
|
255
265
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
256
|
-
|
|
266
|
+
redirectUri: v__namespace.string(),
|
|
267
|
+
mode: v__namespace.optional(v__namespace.picklist([ exports.Mode.CrossDevice, exports.Mode.SameDevice ]))
|
|
257
268
|
});
|
|
258
269
|
|
|
259
|
-
const RequestCredentialsOptionsValidator = v__namespace.
|
|
270
|
+
const RequestCredentialsOptionsValidator = v__namespace.object({
|
|
271
|
+
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
272
|
+
challenge: v__namespace.optional(v__namespace.string()),
|
|
273
|
+
openid4vpConfiguration: v__namespace.optional(v__namespace.union([ OpenId4vpConfigSameDeviceOptionsValidator, OpenId4vpConfigCrossDeviceOptionsValidator, OpenId4vpConfigAutoDetectOptionsValidator ]))
|
|
274
|
+
});
|
|
260
275
|
|
|
261
276
|
exports.RequestCredentialsErrorType = void 0;
|
|
262
277
|
|
|
263
278
|
(function(RequestCredentialsErrorType) {
|
|
264
279
|
RequestCredentialsErrorType["RequestCredentialsFailed"] = "RequestCredentialsFailed";
|
|
280
|
+
RequestCredentialsErrorType["Timeout"] = "Timeout";
|
|
281
|
+
RequestCredentialsErrorType["Abort"] = "Abort";
|
|
265
282
|
})(exports.RequestCredentialsErrorType || (exports.RequestCredentialsErrorType = {}));
|
|
266
283
|
|
|
284
|
+
var RequestCredentialsErrorMessage;
|
|
285
|
+
|
|
286
|
+
(function(RequestCredentialsErrorMessage) {
|
|
287
|
+
RequestCredentialsErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
288
|
+
RequestCredentialsErrorMessage["FailedToGetSessionStatus"] = "Failed to get session status";
|
|
289
|
+
RequestCredentialsErrorMessage["FailedToCreateSession"] = "Failed to create session";
|
|
290
|
+
RequestCredentialsErrorMessage["FailedToVerifyCredentialResponse"] = "Failed to verify credential response";
|
|
291
|
+
RequestCredentialsErrorMessage["MissingOpenId4vpConfig"] = "Identified openid4vp session, but missing openId4vpConfiguration on `requestCredentials`";
|
|
292
|
+
RequestCredentialsErrorMessage["DcApiError"] = "Failed to request credentials with Digital Credentials API";
|
|
293
|
+
RequestCredentialsErrorMessage["DcApiResponseParseError"] = "Failed to parse response from Digital Credentials API";
|
|
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
|
|
|
315
|
+
var SafeFetchCommonResponseErrorType;
|
|
316
|
+
|
|
317
|
+
(function(SafeFetchCommonResponseErrorType) {
|
|
318
|
+
SafeFetchCommonResponseErrorType["UnexpectedResponse"] = "UnexpectedResponse";
|
|
319
|
+
})(SafeFetchCommonResponseErrorType || (SafeFetchCommonResponseErrorType = {}));
|
|
320
|
+
|
|
321
|
+
var SafeFetchErrorType;
|
|
322
|
+
|
|
323
|
+
(function(SafeFetchErrorType) {
|
|
324
|
+
SafeFetchErrorType["HttpError"] = "HttpError";
|
|
325
|
+
SafeFetchErrorType["UnknownError"] = "UnknownError";
|
|
326
|
+
})(SafeFetchErrorType || (SafeFetchErrorType = {}));
|
|
327
|
+
|
|
328
|
+
const safeFetch = async (input, init) => {
|
|
329
|
+
try {
|
|
330
|
+
const headers = Object.assign(Object.assign({}, init === null || init === void 0 ? void 0 : init.headers), {
|
|
331
|
+
[MATTR_SDK_VERSION_HEADER]: `verifier-sdk-web/${MATTR_SDK_VERSION_VALUE}`
|
|
332
|
+
});
|
|
333
|
+
const response = await fetch(input, Object.assign(Object.assign({}, init), {
|
|
334
|
+
headers: headers
|
|
335
|
+
}));
|
|
336
|
+
if (response.status > 299 || response.status < 200) {
|
|
337
|
+
return neverthrow.err({
|
|
338
|
+
type: SafeFetchErrorType.HttpError,
|
|
339
|
+
message: `HTTP error, status = ${response.status}`,
|
|
340
|
+
status: response.status
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
return neverthrow.ok(response);
|
|
344
|
+
} catch (error) {
|
|
345
|
+
return neverthrow.err({
|
|
346
|
+
type: SafeFetchErrorType.UnknownError,
|
|
347
|
+
message: "Unknown error",
|
|
348
|
+
cause: error
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
272
353
|
let initialiseOptions = undefined;
|
|
273
354
|
|
|
274
355
|
var InitialiseErrorMessage;
|
|
@@ -284,10 +365,71 @@ const initialise = options => {
|
|
|
284
365
|
|
|
285
366
|
const getInitialiseOptions = () => initialiseOptions;
|
|
286
367
|
|
|
368
|
+
let sessionAbortController = undefined;
|
|
369
|
+
|
|
370
|
+
let _sessionId = undefined;
|
|
371
|
+
|
|
372
|
+
let _sessionKey = undefined;
|
|
373
|
+
|
|
374
|
+
let _sessionTimeoutId = undefined;
|
|
375
|
+
|
|
376
|
+
const getActiveSession = () => {
|
|
377
|
+
const sessionId = _sessionId;
|
|
378
|
+
const sessionKey = _sessionKey;
|
|
379
|
+
const sessionTimeoutId = _sessionTimeoutId;
|
|
380
|
+
if (sessionId) {
|
|
381
|
+
return {
|
|
382
|
+
sessionId: sessionId,
|
|
383
|
+
sessionKey: sessionKey,
|
|
384
|
+
sessionTimeoutId: sessionTimeoutId
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
return undefined;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
const setActiveSession = session => {
|
|
391
|
+
const {sessionId: sessionId, sessionKey: sessionKey, sessionTimeoutId: sessionTimeoutId} = session;
|
|
392
|
+
_sessionId = sessionId;
|
|
393
|
+
_sessionKey = sessionKey;
|
|
394
|
+
_sessionTimeoutId = sessionTimeoutId;
|
|
395
|
+
const abortController = new AbortController;
|
|
396
|
+
sessionAbortController = abortController;
|
|
397
|
+
return abortController;
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
const removeActiveSession = () => {
|
|
401
|
+
sessionAbortController === null || sessionAbortController === void 0 ? void 0 : sessionAbortController.abort();
|
|
402
|
+
if (_sessionTimeoutId) {
|
|
403
|
+
window.clearTimeout(_sessionTimeoutId);
|
|
404
|
+
}
|
|
405
|
+
sessionAbortController = undefined;
|
|
406
|
+
_sessionKey = undefined;
|
|
407
|
+
_sessionId = undefined;
|
|
408
|
+
_sessionTimeoutId = undefined;
|
|
409
|
+
};
|
|
410
|
+
|
|
287
411
|
const defaultRetryDelay = attempt => Math.pow(2, attempt) * 1e3;
|
|
288
412
|
|
|
289
413
|
const defaultRetry = 2;
|
|
290
414
|
|
|
415
|
+
const withRetry = async (fn, options) => {
|
|
416
|
+
const {retries: retries = defaultRetry, retryDelay: retryDelay = defaultRetryDelay, attempt: attempt = 0} = options;
|
|
417
|
+
try {
|
|
418
|
+
return await fn();
|
|
419
|
+
} catch (err) {
|
|
420
|
+
if (retries > 0) {
|
|
421
|
+
const delay = typeof retryDelay === "function" ? retryDelay(attempt) : retryDelay;
|
|
422
|
+
await new Promise((resolve => setTimeout(resolve, delay)));
|
|
423
|
+
return await withRetry(fn, Object.assign(Object.assign({}, options), {
|
|
424
|
+
retries: retries - 1,
|
|
425
|
+
retryDelay: retryDelay,
|
|
426
|
+
attempt: attempt + 1
|
|
427
|
+
}));
|
|
428
|
+
}
|
|
429
|
+
throw err;
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
|
|
291
433
|
const withRetrySafeFetch = async (fn, options) => {
|
|
292
434
|
const {retries: retries = defaultRetry, retryDelay: retryDelay = defaultRetryDelay, attempt: attempt = 0, retryHttpStatus: retryHttpStatus} = options;
|
|
293
435
|
const result = await fn();
|
|
@@ -316,17 +458,15 @@ const getHashParamValue = (hash, param) => {
|
|
|
316
458
|
return urlParams.get(param);
|
|
317
459
|
};
|
|
318
460
|
|
|
319
|
-
const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl,
|
|
320
|
-
const postData =
|
|
461
|
+
const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl, walletProviderId: walletProviderId, dcApiSupported: dcApiSupported, applicationId: applicationId}) => {
|
|
462
|
+
const postData = {
|
|
321
463
|
credentialQuery: credentialQuery,
|
|
322
|
-
challenge: challenge
|
|
323
|
-
|
|
324
|
-
redirectUri: redirectUri
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
walletProviderId: walletProviderId
|
|
329
|
-
} : {});
|
|
464
|
+
challenge: challenge,
|
|
465
|
+
applicationId: applicationId,
|
|
466
|
+
redirectUri: redirectUri,
|
|
467
|
+
walletProviderId: walletProviderId,
|
|
468
|
+
dcApiSupported: dcApiSupported
|
|
469
|
+
};
|
|
330
470
|
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions`, {
|
|
331
471
|
method: "POST",
|
|
332
472
|
headers: {
|
|
@@ -340,8 +480,42 @@ const createSession = async ({credentialQuery: credentialQuery, challenge: chall
|
|
|
340
480
|
const data = await responseResult.value.json();
|
|
341
481
|
if (!isType(CreateSessionResponseValidator)(data)) {
|
|
342
482
|
return neverthrow.err({
|
|
343
|
-
type:
|
|
344
|
-
message: "Create session
|
|
483
|
+
type: SafeFetchCommonResponseErrorType.UnexpectedResponse,
|
|
484
|
+
message: "Create session returned unsupported response"
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
return neverthrow.ok(data);
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
const abortSession = async ({apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey}) => {
|
|
491
|
+
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/abort`, {
|
|
492
|
+
method: "POST",
|
|
493
|
+
headers: {
|
|
494
|
+
"Content-Type": "application/json",
|
|
495
|
+
Authorization: `Bearer ${sessionKey}`
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
if (responseResult.isErr()) {
|
|
499
|
+
return neverthrow.err(responseResult.error);
|
|
500
|
+
}
|
|
501
|
+
return neverthrow.ok(undefined);
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
const getSessionStatus = async ({apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey}) => {
|
|
505
|
+
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/status`, {
|
|
506
|
+
method: "GET",
|
|
507
|
+
headers: {
|
|
508
|
+
Authorization: `Bearer ${sessionKey}`
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
if (responseResult.isErr()) {
|
|
512
|
+
return neverthrow.err(responseResult.error);
|
|
513
|
+
}
|
|
514
|
+
const data = await responseResult.value.json();
|
|
515
|
+
if (!isType(GetSessionStatusResponseValidator)(data)) {
|
|
516
|
+
return neverthrow.err({
|
|
517
|
+
type: SafeFetchCommonResponseErrorType.UnexpectedResponse,
|
|
518
|
+
message: "Get session status return unsupported response"
|
|
345
519
|
});
|
|
346
520
|
}
|
|
347
521
|
return neverthrow.ok(data);
|
|
@@ -369,7 +543,7 @@ const exchangeSessionResult = async ({challenge: challenge, responseCode: respon
|
|
|
369
543
|
const data = await responseResult.value.json();
|
|
370
544
|
if (!isType(PresentationResultRelaxValidator)(data)) {
|
|
371
545
|
return neverthrow.err({
|
|
372
|
-
type:
|
|
546
|
+
type: SafeFetchCommonResponseErrorType.UnexpectedResponse,
|
|
373
547
|
message: "Exchange session result return unsupported response",
|
|
374
548
|
details: {
|
|
375
549
|
data: data
|
|
@@ -384,22 +558,7 @@ const isMobileDetect = userAgent => isMobile.isMobile({
|
|
|
384
558
|
tablet: false
|
|
385
559
|
});
|
|
386
560
|
|
|
387
|
-
|
|
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 = {}));
|
|
561
|
+
const getVersion = () => MATTR_SDK_VERSION_VALUE;
|
|
403
562
|
|
|
404
563
|
var WindowEventListenerType;
|
|
405
564
|
|
|
@@ -407,10 +566,13 @@ var WindowEventListenerType;
|
|
|
407
566
|
WindowEventListenerType["message"] = "message";
|
|
408
567
|
})(WindowEventListenerType || (WindowEventListenerType = {}));
|
|
409
568
|
|
|
410
|
-
let listener;
|
|
569
|
+
let listener = undefined;
|
|
411
570
|
|
|
412
571
|
const removeWindowMessageEventListener = () => {
|
|
413
|
-
|
|
572
|
+
if (listener) {
|
|
573
|
+
window.removeEventListener(WindowEventListenerType.message, listener, false);
|
|
574
|
+
}
|
|
575
|
+
listener = undefined;
|
|
414
576
|
};
|
|
415
577
|
|
|
416
578
|
const closeCrossDeviceModal = options => {
|
|
@@ -422,8 +584,7 @@ const closeCrossDeviceModal = options => {
|
|
|
422
584
|
};
|
|
423
585
|
|
|
424
586
|
const receiveMessageHandler = options => async event => {
|
|
425
|
-
const {
|
|
426
|
-
const {onComplete: onComplete, onFailure: onFailure} = crossDeviceCallback;
|
|
587
|
+
const {onComplete: onComplete, onFailure: onFailure, container: container, sessionId: sessionId, apiBaseUrl: apiBaseUrl, challenge: challenge} = options;
|
|
427
588
|
if (event.origin !== apiBaseUrl) {
|
|
428
589
|
return;
|
|
429
590
|
}
|
|
@@ -437,8 +598,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
437
598
|
});
|
|
438
599
|
if (result.isErr()) {
|
|
439
600
|
onFailure({
|
|
440
|
-
type: exports.
|
|
441
|
-
message:
|
|
601
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
602
|
+
message: RequestCredentialsErrorMessage.FailedToGetSessionResult
|
|
442
603
|
});
|
|
443
604
|
closeCrossDeviceModal({
|
|
444
605
|
container: container
|
|
@@ -446,8 +607,9 @@ const receiveMessageHandler = options => async event => {
|
|
|
446
607
|
return;
|
|
447
608
|
}
|
|
448
609
|
onComplete({
|
|
449
|
-
result: result.value,
|
|
450
|
-
sessionId: result.value.sessionId
|
|
610
|
+
result: "challenge" in result.value ? result.value : undefined,
|
|
611
|
+
sessionId: result.value.sessionId,
|
|
612
|
+
sessionCompletedInRedirect: false
|
|
451
613
|
});
|
|
452
614
|
closeCrossDeviceModal({
|
|
453
615
|
container: container
|
|
@@ -456,8 +618,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
456
618
|
}
|
|
457
619
|
if (event.data.type === MessageEventDataType.PresentationTimeout) {
|
|
458
620
|
onFailure({
|
|
459
|
-
type: exports.
|
|
460
|
-
message:
|
|
621
|
+
type: exports.RequestCredentialsErrorType.Timeout,
|
|
622
|
+
message: RequestCredentialsErrorMessage.Timeout
|
|
461
623
|
});
|
|
462
624
|
closeCrossDeviceModal({
|
|
463
625
|
container: container
|
|
@@ -466,8 +628,8 @@ const receiveMessageHandler = options => async event => {
|
|
|
466
628
|
}
|
|
467
629
|
if (event.data.type === MessageEventDataType.PresentationAbort) {
|
|
468
630
|
onFailure({
|
|
469
|
-
type: exports.
|
|
470
|
-
message:
|
|
631
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
632
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
471
633
|
});
|
|
472
634
|
closeCrossDeviceModal({
|
|
473
635
|
container: container
|
|
@@ -492,41 +654,198 @@ const openCrossDeviceModal = options => {
|
|
|
492
654
|
return modalContainer;
|
|
493
655
|
};
|
|
494
656
|
|
|
495
|
-
const
|
|
496
|
-
const {challenge: challenge,
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
657
|
+
const requestCredentialsWithCrossDevice = async options => {
|
|
658
|
+
const {challenge: challenge, apiBaseUrl: apiBaseUrl, sessionUrl: sessionUrl, sessionId: sessionId, sessionKey: sessionKey} = options;
|
|
659
|
+
const container = openCrossDeviceModal({
|
|
660
|
+
sessionUrl: sessionUrl
|
|
661
|
+
});
|
|
662
|
+
return await new Promise((resolve => {
|
|
663
|
+
const abortController = setActiveSession({
|
|
664
|
+
sessionId: sessionId,
|
|
665
|
+
sessionKey: sessionKey
|
|
666
|
+
});
|
|
667
|
+
abortController.signal.addEventListener("abort", (() => {
|
|
668
|
+
closeCrossDeviceModal({
|
|
669
|
+
container: container
|
|
670
|
+
});
|
|
671
|
+
resolve(neverthrow.err({
|
|
672
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
673
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
674
|
+
}));
|
|
675
|
+
}));
|
|
676
|
+
removeWindowMessageEventListener();
|
|
677
|
+
listener = receiveMessageHandler({
|
|
678
|
+
container: container,
|
|
679
|
+
sessionId: sessionId,
|
|
680
|
+
apiBaseUrl: apiBaseUrl,
|
|
681
|
+
challenge: challenge,
|
|
682
|
+
onComplete: data => resolve(neverthrow.ok(data)),
|
|
683
|
+
onFailure: error => resolve(neverthrow.err(error))
|
|
684
|
+
});
|
|
685
|
+
window.addEventListener(WindowEventListenerType.message, listener, false);
|
|
686
|
+
}));
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
const abortCredentialRequest = async () => {
|
|
690
|
+
const initialiseOptions = getInitialiseOptions();
|
|
691
|
+
if (!initialiseOptions) {
|
|
692
|
+
throw new Exception(InitialiseErrorMessage.SdkNotInitialised);
|
|
693
|
+
}
|
|
694
|
+
const {apiBaseUrl: apiBaseUrl} = initialiseOptions;
|
|
695
|
+
const session = getActiveSession();
|
|
696
|
+
if (!session || !session.sessionKey) {
|
|
697
|
+
return neverthrow.ok(undefined);
|
|
698
|
+
}
|
|
699
|
+
const {sessionId: sessionId, sessionKey: sessionKey} = session;
|
|
700
|
+
removeActiveSession();
|
|
701
|
+
const abortSessionResult = await abortSession({
|
|
501
702
|
apiBaseUrl: apiBaseUrl,
|
|
502
|
-
|
|
503
|
-
|
|
703
|
+
sessionId: sessionId,
|
|
704
|
+
sessionKey: sessionKey
|
|
504
705
|
});
|
|
505
|
-
if (
|
|
706
|
+
if (abortSessionResult.isErr()) {
|
|
506
707
|
return neverthrow.err({
|
|
507
|
-
type: exports.
|
|
508
|
-
message:
|
|
509
|
-
cause:
|
|
708
|
+
type: exports.AbortSessionErrorType.AbortSessionFailed,
|
|
709
|
+
message: AbortSessionErrorMessage.FailedToAbortSession,
|
|
710
|
+
cause: abortSessionResult.error
|
|
510
711
|
});
|
|
511
712
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
container: container,
|
|
713
|
+
return neverthrow.ok(undefined);
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
const requestCredentialsWithDigitalCredentialsApi = async options => {
|
|
717
|
+
const {apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey, challenge: challenge, request: request, sessionTtl: sessionTtl} = options;
|
|
718
|
+
const sessionTimeoutId = window.setTimeout((() => removeActiveSession()), sessionTtl * 1e3);
|
|
719
|
+
const abortController = setActiveSession({
|
|
520
720
|
sessionId: sessionId,
|
|
721
|
+
sessionKey: sessionKey,
|
|
722
|
+
sessionTimeoutId: sessionTimeoutId
|
|
723
|
+
});
|
|
724
|
+
const credentialResponseResult = await getCredentials(request, abortController);
|
|
725
|
+
if (credentialResponseResult.isErr()) {
|
|
726
|
+
await abortCredentialRequest();
|
|
727
|
+
return neverthrow.err(credentialResponseResult.error);
|
|
728
|
+
}
|
|
729
|
+
const credentialResponse = credentialResponseResult.value;
|
|
730
|
+
const parsedCredentialResponseResult = parseCredentialResponse(credentialResponse);
|
|
731
|
+
if (parsedCredentialResponseResult.isErr()) {
|
|
732
|
+
await abortCredentialRequest();
|
|
733
|
+
return neverthrow.err(parsedCredentialResponseResult.error);
|
|
734
|
+
}
|
|
735
|
+
const parsedCredentialResponse = parsedCredentialResponseResult.value;
|
|
736
|
+
const credentialVerificationResult = await verifyCredentialResponse({
|
|
521
737
|
apiBaseUrl: apiBaseUrl,
|
|
522
|
-
|
|
738
|
+
sessionId: sessionId,
|
|
739
|
+
sessionKey: sessionKey,
|
|
740
|
+
challenge: challenge,
|
|
741
|
+
protocol: parsedCredentialResponse.protocol,
|
|
742
|
+
data: parsedCredentialResponse.data
|
|
523
743
|
});
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
744
|
+
if (credentialVerificationResult.isErr()) {
|
|
745
|
+
return neverthrow.err({
|
|
746
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
747
|
+
message: RequestCredentialsErrorMessage.FailedToVerifyCredentialResponse,
|
|
748
|
+
cause: credentialVerificationResult.error
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
return neverthrow.ok(credentialVerificationResult.value);
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
const getCredentials = async (request, abortController) => {
|
|
755
|
+
try {
|
|
756
|
+
const credentialResponse = await navigator.credentials.get(Object.assign(Object.assign({}, request), {
|
|
757
|
+
signal: abortController.signal
|
|
758
|
+
}));
|
|
759
|
+
return neverthrow.ok(credentialResponse);
|
|
760
|
+
} catch (exception) {
|
|
761
|
+
return neverthrow.err({
|
|
762
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
763
|
+
message: RequestCredentialsErrorMessage.DcApiError,
|
|
764
|
+
cause: exception
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
const parseCredentialResponse = credentialResponse => {
|
|
770
|
+
if (!credentialResponse) {
|
|
771
|
+
return neverthrow.err({
|
|
772
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
773
|
+
message: RequestCredentialsErrorMessage.DcApiResponseParseError,
|
|
774
|
+
details: {
|
|
775
|
+
response: credentialResponse
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
if (typeof credentialResponse === "object") {
|
|
780
|
+
return neverthrow.ok(credentialResponse);
|
|
781
|
+
}
|
|
782
|
+
if (typeof credentialResponse === "string") {
|
|
783
|
+
try {
|
|
784
|
+
const parsed = JSON.parse(credentialResponse);
|
|
785
|
+
return neverthrow.ok(parsed);
|
|
786
|
+
} catch (_a) {
|
|
787
|
+
return neverthrow.err({
|
|
788
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
789
|
+
message: RequestCredentialsErrorMessage.DcApiResponseParseError,
|
|
790
|
+
details: {
|
|
791
|
+
response: credentialResponse
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
return neverthrow.err({
|
|
797
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
798
|
+
message: RequestCredentialsErrorMessage.DcApiResponseParseError,
|
|
799
|
+
details: {
|
|
800
|
+
response: credentialResponse
|
|
801
|
+
}
|
|
527
802
|
});
|
|
528
803
|
};
|
|
529
804
|
|
|
805
|
+
const verifyCredentialResponse = async options => {
|
|
806
|
+
const {apiBaseUrl: apiBaseUrl, sessionId: sessionId, sessionKey: sessionKey, challenge: challenge, protocol: protocol, data: data} = options;
|
|
807
|
+
const requestBody = {
|
|
808
|
+
protocol: protocol,
|
|
809
|
+
data: data,
|
|
810
|
+
challenge: challenge
|
|
811
|
+
};
|
|
812
|
+
const credentialVerificationResult = await safeFetch(`${apiBaseUrl}/v2/presentations/sessions/${sessionId}/dc-api/response`, {
|
|
813
|
+
method: "POST",
|
|
814
|
+
headers: {
|
|
815
|
+
"Content-Type": "application/json",
|
|
816
|
+
Authorization: `Bearer ${sessionKey}`
|
|
817
|
+
},
|
|
818
|
+
body: JSON.stringify(requestBody)
|
|
819
|
+
});
|
|
820
|
+
if (credentialVerificationResult.isErr()) {
|
|
821
|
+
return neverthrow.err(credentialVerificationResult.error);
|
|
822
|
+
}
|
|
823
|
+
const credentialVerificationResponse = await credentialVerificationResult.value.json();
|
|
824
|
+
if (!isType(PresentationResultRelaxValidator)(credentialVerificationResponse)) {
|
|
825
|
+
return neverthrow.err({
|
|
826
|
+
type: SafeFetchCommonResponseErrorType.UnexpectedResponse,
|
|
827
|
+
message: "Verify credential returned unsupported response",
|
|
828
|
+
details: {
|
|
829
|
+
response: credentialVerificationResponse
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
return neverthrow.ok(credentialVerificationResponse);
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
const isDigitalCredentialsApiSupported = () => {
|
|
837
|
+
var _a;
|
|
838
|
+
return "DigitalCredential" in window && typeof window.DigitalCredential === "function" && typeof ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.credentials) === null || _a === void 0 ? void 0 : _a.get) === "function";
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
const sleep = ms => new Promise((resolve => setTimeout(resolve, ms)));
|
|
842
|
+
|
|
843
|
+
const SESSION_STATUS_POLLING_MAX_RETRY = 1e3;
|
|
844
|
+
|
|
845
|
+
const SESSION_STATUS_POLLING_INTERVAL_MS = 3e3;
|
|
846
|
+
|
|
847
|
+
const SESSION_STATUS_POLLING_INITIAL_DELAY_MS = 3e3;
|
|
848
|
+
|
|
530
849
|
var SameDeviceRequestCredentialsErrorMessage;
|
|
531
850
|
|
|
532
851
|
(function(SameDeviceRequestCredentialsErrorMessage) {
|
|
@@ -535,65 +854,135 @@ var SameDeviceRequestCredentialsErrorMessage;
|
|
|
535
854
|
})(SameDeviceRequestCredentialsErrorMessage || (SameDeviceRequestCredentialsErrorMessage = {}));
|
|
536
855
|
|
|
537
856
|
const requestCredentialsSameDevice = async options => {
|
|
538
|
-
const {challenge: challenge,
|
|
539
|
-
const
|
|
857
|
+
const {challenge: challenge, apiBaseUrl: apiBaseUrl, applicationId: applicationId, sessionUrl: sessionUrl, sessionKey: sessionKey, sessionId: sessionId} = options;
|
|
858
|
+
const abortController = setActiveSession({
|
|
859
|
+
sessionId: sessionId,
|
|
860
|
+
sessionKey: sessionKey
|
|
861
|
+
});
|
|
862
|
+
window.localStorage.setItem(LocalStorageKey.sessionId, sessionId);
|
|
540
863
|
window.localStorage.setItem(LocalStorageKey.challenge, challenge);
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
864
|
+
window.location.assign(sessionUrl);
|
|
865
|
+
await sleep(SESSION_STATUS_POLLING_INITIAL_DELAY_MS);
|
|
866
|
+
const checkResult = await withRetry((async () => {
|
|
867
|
+
const statusResult = await getSessionStatus({
|
|
868
|
+
apiBaseUrl: apiBaseUrl,
|
|
869
|
+
applicationId: applicationId,
|
|
870
|
+
sessionId: sessionId,
|
|
871
|
+
sessionKey: sessionKey
|
|
546
872
|
});
|
|
873
|
+
if (abortController.signal.aborted) {
|
|
874
|
+
return neverthrow.err({
|
|
875
|
+
type: exports.RequestCredentialsErrorType.Abort,
|
|
876
|
+
message: RequestCredentialsErrorMessage.Abort
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
if (statusResult.isErr()) {
|
|
880
|
+
if (statusResult.error.status === 404) {
|
|
881
|
+
return neverthrow.err({
|
|
882
|
+
type: exports.RequestCredentialsErrorType.Timeout,
|
|
883
|
+
message: RequestCredentialsErrorMessage.Timeout
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
throw Error("Unexpected status response. Retry");
|
|
887
|
+
}
|
|
888
|
+
if (statusResult.value.status !== PresentationStatusCode.ResultReady) {
|
|
889
|
+
throw Error("Result is not ready. Retry");
|
|
890
|
+
}
|
|
891
|
+
return neverthrow.ok(undefined);
|
|
892
|
+
}), {
|
|
893
|
+
retries: SESSION_STATUS_POLLING_MAX_RETRY,
|
|
894
|
+
retryDelay: SESSION_STATUS_POLLING_INTERVAL_MS
|
|
895
|
+
});
|
|
896
|
+
if (checkResult.isErr()) {
|
|
897
|
+
return neverthrow.err(checkResult.error);
|
|
547
898
|
}
|
|
899
|
+
window.close();
|
|
900
|
+
return neverthrow.ok({
|
|
901
|
+
sessionId: sessionId,
|
|
902
|
+
sessionCompletedInRedirect: true
|
|
903
|
+
});
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
const requestCredentials = async options => {
|
|
907
|
+
var _a;
|
|
908
|
+
const initialiseOptions = getInitialiseOptions();
|
|
909
|
+
if (!initialiseOptions) {
|
|
910
|
+
throw new Exception(InitialiseErrorMessage.SdkNotInitialised);
|
|
911
|
+
}
|
|
912
|
+
assertType(RequestCredentialsOptionsValidator, "Invalid request credential options")(options);
|
|
913
|
+
const {apiBaseUrl: apiBaseUrl, applicationId: applicationId} = initialiseOptions;
|
|
914
|
+
const {challenge: challenge = generateChallenge(), credentialQuery: credentialQuery, openid4vpConfiguration: openid4vpConfiguration} = options;
|
|
915
|
+
const dcApiSupported = isDigitalCredentialsApiSupported();
|
|
916
|
+
const openId4VpRedirectUri = deriveOpenId4vpRedirectUri(openid4vpConfiguration);
|
|
548
917
|
const createSessionResult = await createSession({
|
|
549
918
|
credentialQuery: credentialQuery,
|
|
550
|
-
challenge:
|
|
551
|
-
redirectUri:
|
|
919
|
+
challenge: challenge,
|
|
920
|
+
redirectUri: openId4VpRedirectUri,
|
|
921
|
+
walletProviderId: (_a = openid4vpConfiguration === null || openid4vpConfiguration === void 0 ? void 0 : openid4vpConfiguration.walletProviderId) !== null && _a !== void 0 ? _a : undefined,
|
|
552
922
|
apiBaseUrl: apiBaseUrl,
|
|
553
923
|
applicationId: applicationId,
|
|
554
|
-
|
|
924
|
+
dcApiSupported: dcApiSupported
|
|
555
925
|
});
|
|
556
926
|
if (createSessionResult.isErr()) {
|
|
557
927
|
return neverthrow.err({
|
|
558
928
|
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
559
|
-
message:
|
|
929
|
+
message: RequestCredentialsErrorMessage.FailedToCreateSession,
|
|
560
930
|
cause: createSessionResult.error
|
|
561
931
|
});
|
|
562
932
|
}
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
933
|
+
const session = createSessionResult.value;
|
|
934
|
+
const {sessionKey: sessionKey, sessionId: sessionId} = session;
|
|
935
|
+
if (session.type === SessionType.DigitalCredentialsApi) {
|
|
936
|
+
const {request: request, sessionTtl: sessionTtl} = session;
|
|
937
|
+
return await requestCredentialsWithDigitalCredentialsApi({
|
|
938
|
+
apiBaseUrl: apiBaseUrl,
|
|
939
|
+
request: request,
|
|
940
|
+
sessionId: sessionId,
|
|
941
|
+
sessionKey: sessionKey,
|
|
942
|
+
challenge: challenge,
|
|
943
|
+
sessionTtl: sessionTtl
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
if (!openid4vpConfiguration) {
|
|
947
|
+
return neverthrow.err({
|
|
948
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
949
|
+
message: RequestCredentialsErrorMessage.MissingOpenId4vpConfig
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
const {sessionUrl: sessionUrl} = session;
|
|
953
|
+
if (openId4VpRedirectUri) {
|
|
954
|
+
return await requestCredentialsSameDevice({
|
|
955
|
+
challenge: challenge,
|
|
956
|
+
apiBaseUrl: apiBaseUrl,
|
|
957
|
+
applicationId: applicationId,
|
|
958
|
+
sessionUrl: sessionUrl,
|
|
959
|
+
sessionKey: sessionKey,
|
|
960
|
+
sessionId: sessionId
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
return await requestCredentialsWithCrossDevice({
|
|
964
|
+
challenge: challenge,
|
|
965
|
+
apiBaseUrl: apiBaseUrl,
|
|
966
|
+
sessionUrl: sessionUrl,
|
|
967
|
+
sessionKey: sessionKey,
|
|
567
968
|
sessionId: sessionId
|
|
568
969
|
});
|
|
569
970
|
};
|
|
570
971
|
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
if (!initialiseOptions) {
|
|
575
|
-
throw new Exception(InitialiseErrorMessage.SdkNotInitialised);
|
|
972
|
+
const deriveOpenId4vpRedirectUri = openid4vpConfiguration => {
|
|
973
|
+
if (!openid4vpConfiguration) {
|
|
974
|
+
return undefined;
|
|
576
975
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
initialiseOptions: initialiseOptions,
|
|
583
|
-
challenge: challenge,
|
|
584
|
-
mode: mode
|
|
585
|
-
}));
|
|
976
|
+
let detectedMode;
|
|
977
|
+
if (openid4vpConfiguration && openid4vpConfiguration.mode) {
|
|
978
|
+
detectedMode = openid4vpConfiguration.mode;
|
|
979
|
+
} else {
|
|
980
|
+
detectedMode = isMobileDetect(navigator.userAgent) ? exports.Mode.SameDevice : exports.Mode.CrossDevice;
|
|
586
981
|
}
|
|
587
|
-
if (
|
|
588
|
-
return
|
|
589
|
-
initialiseOptions: initialiseOptions,
|
|
590
|
-
challenge: challenge,
|
|
591
|
-
mode: mode
|
|
592
|
-
}));
|
|
982
|
+
if (detectedMode === exports.Mode.SameDevice && !isType(OpenId4vpConfigCrossDeviceOptionsValidator)(openid4vpConfiguration) && openid4vpConfiguration.redirectUri) {
|
|
983
|
+
return openid4vpConfiguration.redirectUri;
|
|
593
984
|
}
|
|
594
|
-
|
|
595
|
-
data: options
|
|
596
|
-
});
|
|
985
|
+
return undefined;
|
|
597
986
|
};
|
|
598
987
|
|
|
599
988
|
exports.HandleRedirectCallbackErrorType = void 0;
|
|
@@ -607,7 +996,7 @@ var HandleRedirectCallbackErrorMessage;
|
|
|
607
996
|
(function(HandleRedirectCallbackErrorMessage) {
|
|
608
997
|
HandleRedirectCallbackErrorMessage["FailedToFindResponseCode"] = "Failed to find response code";
|
|
609
998
|
HandleRedirectCallbackErrorMessage["FailedToFindChallenge"] = "Failed to find challenge";
|
|
610
|
-
HandleRedirectCallbackErrorMessage["
|
|
999
|
+
HandleRedirectCallbackErrorMessage["FailedToFindActiveSession"] = "Failed to find active session";
|
|
611
1000
|
HandleRedirectCallbackErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
612
1001
|
})(HandleRedirectCallbackErrorMessage || (HandleRedirectCallbackErrorMessage = {}));
|
|
613
1002
|
|
|
@@ -624,18 +1013,12 @@ const handleRedirectCallback = async () => {
|
|
|
624
1013
|
message: HandleRedirectCallbackErrorMessage.FailedToFindResponseCode
|
|
625
1014
|
});
|
|
626
1015
|
}
|
|
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
1016
|
const sessionId = window.localStorage.getItem(LocalStorageKey.sessionId);
|
|
635
|
-
|
|
1017
|
+
const challenge = window.localStorage.getItem(LocalStorageKey.challenge);
|
|
1018
|
+
if (!sessionId || !challenge) {
|
|
636
1019
|
return neverthrow.err({
|
|
637
1020
|
type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
|
|
638
|
-
message: HandleRedirectCallbackErrorMessage.
|
|
1021
|
+
message: HandleRedirectCallbackErrorMessage.FailedToFindActiveSession
|
|
639
1022
|
});
|
|
640
1023
|
}
|
|
641
1024
|
const result = await exchangeSessionResult({
|
|
@@ -652,20 +1035,25 @@ const handleRedirectCallback = async () => {
|
|
|
652
1035
|
});
|
|
653
1036
|
}
|
|
654
1037
|
return neverthrow.ok({
|
|
655
|
-
result: result.value,
|
|
1038
|
+
result: "challenge" in result.value ? result.value : undefined,
|
|
656
1039
|
sessionId: result.value.sessionId
|
|
657
1040
|
});
|
|
658
1041
|
};
|
|
659
1042
|
|
|
660
1043
|
const utils = {
|
|
661
1044
|
generateChallenge: generateChallenge,
|
|
1045
|
+
getVersion: getVersion,
|
|
662
1046
|
unwrap: unwrap
|
|
663
1047
|
};
|
|
664
1048
|
|
|
1049
|
+
exports.abortCredentialRequest = abortCredentialRequest;
|
|
1050
|
+
|
|
665
1051
|
exports.handleRedirectCallback = handleRedirectCallback;
|
|
666
1052
|
|
|
667
1053
|
exports.initialise = initialise;
|
|
668
1054
|
|
|
1055
|
+
exports.isDigitalCredentialsApiSupported = isDigitalCredentialsApiSupported;
|
|
1056
|
+
|
|
669
1057
|
exports.requestCredentials = requestCredentials;
|
|
670
1058
|
|
|
671
1059
|
exports.utils = utils;
|