@mattrglobal/verifier-sdk-web 2.1.2-unstable.99 → 2.2.0
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 +259 -90
- package/dist/lib/verifier-js-no-deps.cjs.js +64 -19
- package/dist/lib/verifier-js-no-deps.cjs.js.map +1 -1
- package/dist/lib/verifier-js.cjs.js +82 -19
- package/dist/lib/verifier-js.cjs.js.map +1 -1
- package/dist/typings/verifier/handleRedirectCallback.d.ts +2 -1
- package/dist/typings/verifier/requestCredentials.d.ts +8 -0
- package/dist/typings/verifier/types/credential-presentation.d.ts +6 -0
- package/dist/typings/verifier/types/verifier-web-sdk.d.ts +26 -3
- package/dist/typings/verifier/utils.d.ts +1 -1
- package/dist/verifier-js.development.js +81 -19
- package/dist/verifier-js.development.js.map +1 -1
- package/dist/verifier-js.production.esm.js +3 -3
- package/dist/verifier-js.production.esm.js.map +1 -1
- package/dist/verifier-js.production.js +3 -3
- package/dist/verifier-js.production.js.map +1 -1
- package/package.json +5 -3
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* Do Not Translate or Localize
|
|
8
8
|
*
|
|
9
9
|
* Bundle of @mattrglobal/verifier-sdk-web
|
|
10
|
-
* Generated: 2026-
|
|
11
|
-
* Version: 2.
|
|
10
|
+
* Generated: 2026-06-08
|
|
11
|
+
* Version: 2.2.0
|
|
12
12
|
* Dependencies:
|
|
13
13
|
*/
|
|
14
14
|
|
|
@@ -181,7 +181,8 @@ const PresentationResultRelaxValidator = v__namespace.object({
|
|
|
181
181
|
credentialQuery: v__namespace.optional(v__namespace.unknown()),
|
|
182
182
|
credentials: v__namespace.optional(v__namespace.unknown()),
|
|
183
183
|
credentialErrors: v__namespace.optional(v__namespace.unknown()),
|
|
184
|
-
error: v__namespace.optional(v__namespace.unknown())
|
|
184
|
+
error: v__namespace.optional(v__namespace.unknown()),
|
|
185
|
+
state: v__namespace.optional(v__namespace.string())
|
|
185
186
|
});
|
|
186
187
|
|
|
187
188
|
exports.Mode = void 0;
|
|
@@ -203,7 +204,8 @@ v__namespace.object({
|
|
|
203
204
|
challenge: v__namespace.string(),
|
|
204
205
|
redirectUri: v__namespace.optional(v__namespace.string()),
|
|
205
206
|
walletProviderId: v__namespace.optional(v__namespace.string()),
|
|
206
|
-
dcApiSupported: v__namespace.optional(v__namespace.boolean())
|
|
207
|
+
dcApiSupported: v__namespace.optional(v__namespace.boolean()),
|
|
208
|
+
state: v__namespace.optional(v__namespace.pipe(v__namespace.string(), v__namespace.minLength(1)))
|
|
207
209
|
});
|
|
208
210
|
|
|
209
211
|
const CreateSessionDigitalCredentialsValidator = v__namespace.object({
|
|
@@ -218,7 +220,8 @@ const CreateSessionOpenId4vpResponseValidator = v__namespace.object({
|
|
|
218
220
|
type: v__namespace.optional(v__namespace.literal(SessionType.Openid4vp)),
|
|
219
221
|
sessionId: v__namespace.string(),
|
|
220
222
|
sessionKey: v__namespace.string(),
|
|
221
|
-
sessionUrl: v__namespace.string()
|
|
223
|
+
sessionUrl: v__namespace.string(),
|
|
224
|
+
state: v__namespace.optional(v__namespace.string())
|
|
222
225
|
});
|
|
223
226
|
|
|
224
227
|
const CreateSessionResponseValidator = v__namespace.union([ CreateSessionDigitalCredentialsValidator, CreateSessionOpenId4vpResponseValidator ]);
|
|
@@ -246,11 +249,12 @@ var LocalStorageKey;
|
|
|
246
249
|
(function(LocalStorageKey) {
|
|
247
250
|
LocalStorageKey["challenge"] = "mattr_chg";
|
|
248
251
|
LocalStorageKey["sessionId"] = "mattr_sid";
|
|
252
|
+
LocalStorageKey["state"] = "mattr_st";
|
|
249
253
|
})(LocalStorageKey || (LocalStorageKey = {}));
|
|
250
254
|
|
|
251
255
|
const MATTR_SDK_VERSION_HEADER = "x-mattr-sdk-version";
|
|
252
256
|
|
|
253
|
-
const MATTR_SDK_VERSION_VALUE = "2.
|
|
257
|
+
const MATTR_SDK_VERSION_VALUE = "2.2.0";
|
|
254
258
|
|
|
255
259
|
var MessageEventDataType;
|
|
256
260
|
|
|
@@ -280,7 +284,8 @@ const OpenId4vpConfigAutoDetectOptionsValidator = v__namespace.object({
|
|
|
280
284
|
const RequestCredentialsOptionsValidator = v__namespace.object({
|
|
281
285
|
credentialQuery: v__namespace.pipe(v__namespace.array(CredentialQueryValidator), v__namespace.nonEmpty()),
|
|
282
286
|
challenge: v__namespace.optional(v__namespace.string()),
|
|
283
|
-
openid4vpConfiguration: v__namespace.optional(v__namespace.union([ OpenId4vpConfigSameDeviceOptionsValidator, OpenId4vpConfigCrossDeviceOptionsValidator, OpenId4vpConfigAutoDetectOptionsValidator ]))
|
|
287
|
+
openid4vpConfiguration: v__namespace.optional(v__namespace.union([ OpenId4vpConfigSameDeviceOptionsValidator, OpenId4vpConfigCrossDeviceOptionsValidator, OpenId4vpConfigAutoDetectOptionsValidator ])),
|
|
288
|
+
state: v__namespace.optional(v__namespace.pipe(v__namespace.string(), v__namespace.minLength(1, "state must not be empty")))
|
|
284
289
|
});
|
|
285
290
|
|
|
286
291
|
exports.RequestCredentialsErrorType = void 0;
|
|
@@ -303,6 +308,7 @@ var RequestCredentialsErrorMessage;
|
|
|
303
308
|
RequestCredentialsErrorMessage["DcApiResponseParseError"] = "Failed to parse response from Digital Credentials API";
|
|
304
309
|
RequestCredentialsErrorMessage["Abort"] = "User aborted the session";
|
|
305
310
|
RequestCredentialsErrorMessage["Timeout"] = "User session timeout";
|
|
311
|
+
RequestCredentialsErrorMessage["StateMismatch"] = "State mismatch between requested session and back-channel result";
|
|
306
312
|
})(RequestCredentialsErrorMessage || (RequestCredentialsErrorMessage = {}));
|
|
307
313
|
|
|
308
314
|
exports.AbortSessionErrorType = void 0;
|
|
@@ -492,18 +498,20 @@ const getHashParamValue = (hash, param) => {
|
|
|
492
498
|
return urlParams.get(param);
|
|
493
499
|
};
|
|
494
500
|
|
|
495
|
-
const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl, walletProviderId: walletProviderId, dcApiSupported: dcApiSupported, applicationId: applicationId}) => {
|
|
501
|
+
const createSession = async ({credentialQuery: credentialQuery, challenge: challenge, redirectUri: redirectUri, apiBaseUrl: apiBaseUrl, walletProviderId: walletProviderId, dcApiSupported: dcApiSupported, applicationId: applicationId, state: state}) => {
|
|
496
502
|
const openid4vpConfiguration = !!walletProviderId || !!redirectUri ? {
|
|
497
503
|
redirectUri: redirectUri,
|
|
498
504
|
walletProviderId: walletProviderId
|
|
499
505
|
} : undefined;
|
|
500
|
-
const postData = {
|
|
506
|
+
const postData = Object.assign({
|
|
501
507
|
credentialQuery: credentialQuery,
|
|
502
508
|
challenge: challenge,
|
|
503
509
|
applicationId: applicationId,
|
|
504
510
|
dcApiSupported: dcApiSupported,
|
|
505
511
|
openid4vpConfiguration: openid4vpConfiguration
|
|
506
|
-
}
|
|
512
|
+
}, state !== undefined ? {
|
|
513
|
+
state: state
|
|
514
|
+
} : {});
|
|
507
515
|
const responseResult = await safeFetch(`${apiBaseUrl}/v2/presentations/web/sessions`, {
|
|
508
516
|
method: "POST",
|
|
509
517
|
headers: {
|
|
@@ -621,7 +629,7 @@ const closeCrossDeviceModal = options => {
|
|
|
621
629
|
};
|
|
622
630
|
|
|
623
631
|
const receiveMessageHandler = options => async event => {
|
|
624
|
-
const {onComplete: onComplete, onFailure: onFailure, container: container, sessionId: sessionId, apiBaseUrl: apiBaseUrl, challenge: challenge} = options;
|
|
632
|
+
const {onComplete: onComplete, onFailure: onFailure, container: container, sessionId: sessionId, apiBaseUrl: apiBaseUrl, challenge: challenge, state: state} = options;
|
|
625
633
|
if (event.origin !== apiBaseUrl) {
|
|
626
634
|
return;
|
|
627
635
|
}
|
|
@@ -643,10 +651,22 @@ const receiveMessageHandler = options => async event => {
|
|
|
643
651
|
});
|
|
644
652
|
return;
|
|
645
653
|
}
|
|
654
|
+
const resultState = "challenge" in result.value ? result.value.state : undefined;
|
|
655
|
+
if (state !== undefined && resultState !== undefined && state !== resultState) {
|
|
656
|
+
onFailure({
|
|
657
|
+
type: exports.RequestCredentialsErrorType.RequestCredentialsFailed,
|
|
658
|
+
message: RequestCredentialsErrorMessage.StateMismatch
|
|
659
|
+
});
|
|
660
|
+
closeCrossDeviceModal({
|
|
661
|
+
container: container
|
|
662
|
+
});
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
646
665
|
onComplete({
|
|
647
666
|
result: "challenge" in result.value ? result.value : undefined,
|
|
648
667
|
sessionId: result.value.sessionId,
|
|
649
|
-
sessionCompletedInRedirect: false
|
|
668
|
+
sessionCompletedInRedirect: false,
|
|
669
|
+
state: resultState !== null && resultState !== void 0 ? resultState : state
|
|
650
670
|
});
|
|
651
671
|
closeCrossDeviceModal({
|
|
652
672
|
container: container
|
|
@@ -692,7 +712,7 @@ const openCrossDeviceModal = options => {
|
|
|
692
712
|
};
|
|
693
713
|
|
|
694
714
|
const requestCredentialsWithCrossDevice = async options => {
|
|
695
|
-
const {challenge: challenge, apiBaseUrl: apiBaseUrl, sessionUrl: sessionUrl, sessionId: sessionId, sessionKey: sessionKey} = options;
|
|
715
|
+
const {challenge: challenge, apiBaseUrl: apiBaseUrl, sessionUrl: sessionUrl, sessionId: sessionId, sessionKey: sessionKey, state: state} = options;
|
|
696
716
|
const container = openCrossDeviceModal({
|
|
697
717
|
sessionUrl: sessionUrl
|
|
698
718
|
});
|
|
@@ -716,6 +736,7 @@ const requestCredentialsWithCrossDevice = async options => {
|
|
|
716
736
|
sessionId: sessionId,
|
|
717
737
|
apiBaseUrl: apiBaseUrl,
|
|
718
738
|
challenge: challenge,
|
|
739
|
+
state: state,
|
|
719
740
|
onComplete: data => resolve(neverthrow.ok(data)),
|
|
720
741
|
onFailure: error => resolve(neverthrow.err(error))
|
|
721
742
|
});
|
|
@@ -903,13 +924,18 @@ var SameDeviceRequestCredentialsErrorMessage;
|
|
|
903
924
|
})(SameDeviceRequestCredentialsErrorMessage || (SameDeviceRequestCredentialsErrorMessage = {}));
|
|
904
925
|
|
|
905
926
|
const requestCredentialsSameDevice = async options => {
|
|
906
|
-
const {challenge: challenge, apiBaseUrl: apiBaseUrl, applicationId: applicationId, sessionUrl: sessionUrl, sessionKey: sessionKey, sessionId: sessionId} = options;
|
|
927
|
+
const {challenge: challenge, apiBaseUrl: apiBaseUrl, applicationId: applicationId, sessionUrl: sessionUrl, sessionKey: sessionKey, sessionId: sessionId, state: state} = options;
|
|
907
928
|
const abortController = setActiveSession({
|
|
908
929
|
sessionId: sessionId,
|
|
909
930
|
sessionKey: sessionKey
|
|
910
931
|
});
|
|
911
932
|
window.localStorage.setItem(LocalStorageKey.sessionId, sessionId);
|
|
912
933
|
window.localStorage.setItem(LocalStorageKey.challenge, challenge);
|
|
934
|
+
if (state !== undefined) {
|
|
935
|
+
window.localStorage.setItem(LocalStorageKey.state, state);
|
|
936
|
+
} else {
|
|
937
|
+
window.localStorage.removeItem(LocalStorageKey.state);
|
|
938
|
+
}
|
|
913
939
|
window.location.assign(sessionUrl);
|
|
914
940
|
await sleep(SESSION_STATUS_POLLING_INITIAL_DELAY_MS);
|
|
915
941
|
const checkResult = await withRetry((async () => {
|
|
@@ -960,7 +986,7 @@ const requestCredentials = async options => {
|
|
|
960
986
|
}
|
|
961
987
|
assertType(RequestCredentialsOptionsValidator, "Invalid request credential options")(options);
|
|
962
988
|
const {apiBaseUrl: apiBaseUrl, applicationId: applicationId} = initializeOptions;
|
|
963
|
-
const {challenge: challenge = generateChallenge(), credentialQuery: credentialQuery, openid4vpConfiguration: openid4vpConfiguration} = options;
|
|
989
|
+
const {challenge: challenge = generateChallenge(), credentialQuery: credentialQuery, openid4vpConfiguration: openid4vpConfiguration, state: state} = options;
|
|
964
990
|
const dcApiSupported = isDigitalCredentialsApiSupported();
|
|
965
991
|
const openId4VpRedirectUri = deriveOpenId4vpRedirectUri(openid4vpConfiguration);
|
|
966
992
|
const createSessionResult = await createSession({
|
|
@@ -970,7 +996,8 @@ const requestCredentials = async options => {
|
|
|
970
996
|
walletProviderId: (_a = openid4vpConfiguration === null || openid4vpConfiguration === void 0 ? void 0 : openid4vpConfiguration.walletProviderId) !== null && _a !== void 0 ? _a : undefined,
|
|
971
997
|
apiBaseUrl: apiBaseUrl,
|
|
972
998
|
applicationId: applicationId,
|
|
973
|
-
dcApiSupported: dcApiSupported
|
|
999
|
+
dcApiSupported: dcApiSupported,
|
|
1000
|
+
state: state
|
|
974
1001
|
});
|
|
975
1002
|
if (createSessionResult.isErr()) {
|
|
976
1003
|
return neverthrow.err({
|
|
@@ -1006,7 +1033,8 @@ const requestCredentials = async options => {
|
|
|
1006
1033
|
applicationId: applicationId,
|
|
1007
1034
|
sessionUrl: sessionUrl,
|
|
1008
1035
|
sessionKey: sessionKey,
|
|
1009
|
-
sessionId: sessionId
|
|
1036
|
+
sessionId: sessionId,
|
|
1037
|
+
state: state
|
|
1010
1038
|
});
|
|
1011
1039
|
}
|
|
1012
1040
|
return await requestCredentialsWithCrossDevice({
|
|
@@ -1014,7 +1042,8 @@ const requestCredentials = async options => {
|
|
|
1014
1042
|
apiBaseUrl: apiBaseUrl,
|
|
1015
1043
|
sessionUrl: sessionUrl,
|
|
1016
1044
|
sessionKey: sessionKey,
|
|
1017
|
-
sessionId: sessionId
|
|
1045
|
+
sessionId: sessionId,
|
|
1046
|
+
state: state
|
|
1018
1047
|
});
|
|
1019
1048
|
};
|
|
1020
1049
|
|
|
@@ -1047,9 +1076,11 @@ var HandleRedirectCallbackErrorMessage;
|
|
|
1047
1076
|
HandleRedirectCallbackErrorMessage["FailedToFindChallenge"] = "Failed to find challenge";
|
|
1048
1077
|
HandleRedirectCallbackErrorMessage["FailedToFindActiveSession"] = "Failed to find active session";
|
|
1049
1078
|
HandleRedirectCallbackErrorMessage["FailedToGetSessionResult"] = "Failed to get session result";
|
|
1079
|
+
HandleRedirectCallbackErrorMessage["StateMismatch"] = "State mismatch between stored session and back-channel result";
|
|
1050
1080
|
})(HandleRedirectCallbackErrorMessage || (HandleRedirectCallbackErrorMessage = {}));
|
|
1051
1081
|
|
|
1052
1082
|
const handleRedirectCallback = async () => {
|
|
1083
|
+
var _a;
|
|
1053
1084
|
const initializeOptions = getInitializeOptions();
|
|
1054
1085
|
if (!initializeOptions) {
|
|
1055
1086
|
throw new Exception(InitializeErrorMessage.SdkNotInitialized);
|
|
@@ -1064,6 +1095,7 @@ const handleRedirectCallback = async () => {
|
|
|
1064
1095
|
}
|
|
1065
1096
|
const sessionId = window.localStorage.getItem(LocalStorageKey.sessionId);
|
|
1066
1097
|
const challenge = window.localStorage.getItem(LocalStorageKey.challenge);
|
|
1098
|
+
const storedState = (_a = window.localStorage.getItem(LocalStorageKey.state)) !== null && _a !== void 0 ? _a : undefined;
|
|
1067
1099
|
if (!sessionId || !challenge) {
|
|
1068
1100
|
return neverthrow.err({
|
|
1069
1101
|
type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
|
|
@@ -1083,9 +1115,22 @@ const handleRedirectCallback = async () => {
|
|
|
1083
1115
|
cause: result.error
|
|
1084
1116
|
});
|
|
1085
1117
|
}
|
|
1118
|
+
const resultState = "challenge" in result.value ? result.value.state : undefined;
|
|
1119
|
+
if (storedState !== undefined && resultState !== undefined && storedState !== resultState) {
|
|
1120
|
+
window.localStorage.removeItem(LocalStorageKey.challenge);
|
|
1121
|
+
window.localStorage.removeItem(LocalStorageKey.sessionId);
|
|
1122
|
+
window.localStorage.removeItem(LocalStorageKey.state);
|
|
1123
|
+
return neverthrow.err({
|
|
1124
|
+
type: exports.HandleRedirectCallbackErrorType.HandleRedirectCallbackFailed,
|
|
1125
|
+
message: HandleRedirectCallbackErrorMessage.StateMismatch
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
const state = resultState !== null && resultState !== void 0 ? resultState : storedState;
|
|
1129
|
+
window.localStorage.removeItem(LocalStorageKey.state);
|
|
1086
1130
|
return neverthrow.ok({
|
|
1087
1131
|
result: "challenge" in result.value ? result.value : undefined,
|
|
1088
|
-
sessionId: result.value.sessionId
|
|
1132
|
+
sessionId: result.value.sessionId,
|
|
1133
|
+
state: state
|
|
1089
1134
|
});
|
|
1090
1135
|
};
|
|
1091
1136
|
|