@mosip/react-inji-verify-sdk 0.12.0-beta → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -11,6 +11,14 @@ Inji Verify SDK is a library which exposes React components for integrating Inji
11
11
 
12
12
  [npm](https://www.npmjs.com/package/@mosip/react-inji-verify-sdk)
13
13
 
14
+ ## Peer Dependencies
15
+
16
+ | Name | Version |
17
+ |------------|---------|
18
+ | React | 18.2.0 |
19
+ | TypeScript | 4.9.5 |
20
+
21
+
14
22
  ## Local Publishing Guide
15
23
 
16
24
  Install the dependencies
@@ -23,6 +31,73 @@ Publish the npm package using Verdaccio
23
31
  We use [verdaccio](https://verdaccio.org/docs/what-is-verdaccio). `npm link` or `yarn link` won't work as we have peer dependencies. Follow the docs to setup Verdaccio. Then run
24
32
  `npm publish --registry http://localhost:<VERADACCIO_PORT>`
25
33
 
34
+ ## Components
35
+ #### OpenID4VPVerification
36
+
37
+ ##### Overview
38
+
39
+ The OPENID4VP UI Component is designed to facilitate the Verifiable Presentation (VP) verification process using the OpenID4VP specification. It interacts with the Relying Party UI, Verify Backend, and Wallet application to complete the verification process.
40
+
41
+ This document explains the sequence of operations performed by the component, along with the relevant API calls and callback handling.
42
+
43
+ ##### Sequence of Operations
44
+
45
+ ###### 1. Trigger (User Action)
46
+
47
+ The user initiates the verification process via the Relying Party UI by:
48
+ Clicking a "Verify" button. Opening the component where auto-verification is triggered.
49
+
50
+ ###### 2. Configuration (Relying Party Setup)
51
+
52
+ The Relying Party UI configures the OPENID4VP UI Component with the following parameters described [here]("#component-props")
53
+
54
+ ###### 3. VP Request Creation
55
+
56
+ The OPENID4VP UI Component sends a request to verifyServiceUrl/vp-request to initiate an Authorization Request. Either presentationDefinitionId or presentationDefinition must be provided in the request.
57
+
58
+ ###### 4. Authorization Request (from Backend)
59
+
60
+ The Verify Backend processes the VP request. Generates a transactionId if not provided. Constructs an Authorization Request following the OpenID4VP standard. Returns the Authorization Request response to the OPENID4VP UI Component.
61
+
62
+ ###### 5. QR Code Generation
63
+
64
+ The OPENID4VP UI Component generates a QR Code containing the Authorization Request Response. The QR Code is displayed to the user for scanning via their Wallet.
65
+
66
+ ###### 6. Status Polling (Background Check)
67
+
68
+ The component continuously polls the verifyServiceUrl/vp-request/{reqId}/status endpoint. Status values include:
69
+ `ACTIVE` → Waiting for user action.
70
+ `VP_SUBMITTED` → User has submitted the VP.
71
+ `EXPIRED` → QR code expired.
72
+
73
+ ###### 7. Wallet Interaction (User Action)
74
+
75
+ The user scans the QR Code with their Wallet. The Wallet extracts the presentation definition. Displays a list of matching Verifiable Credentials (VCs) available in the Wallet for user selection. Submits the selected VCs as a Verifiable Presentation (VP) Token to the Verify Backend.
76
+
77
+ ###### 8. VP Token Submission (from Wallet)
78
+
79
+ The Wallet authenticates the user (if required) and submits the VP Token to the Verify Backend.
80
+
81
+ ###### 9. Status Handling (/vp-request/{reqId}/status)
82
+
83
+ The OPENID4VP UI Component checks the status of the VP request:
84
+ - Case 1: QR Code Expired
85
+ If the status returns `EXPIRED`, then the `onQrCodeExpired()` callback is triggered. Which notifies the Relying Party UI that the verification request has expired.
86
+
87
+ - Case 2: VP Submitted
88
+ If the status returns `VP_SUBMITTED`, then the component requests the VP data from `verifyServiceUrl/vp-result/{txnId}`. This call retrieves the VP data. Once its retrieved the componnent validates the VP using the VC-Verifier library. Returns the validated verification result.
89
+ - onVpProcessed(data) Execution: The onVpProcessed(data) callback is triggered. Passes the validated verification result to the Relying Party UI.
90
+
91
+ - onVpReceived(txnId) Execution: The onVpReceived(txnId) callback is triggered. The Relying Party UI can now pass the txnId to its backend to fetch results from the Verify Backend.
92
+
93
+ ###### 10. Error Handling
94
+
95
+ If an error occurs before reaching `VP_SUBMITTED`, the `onError(error)` callback is triggered. Common errors include,
96
+ - Failure to generate QR code.
97
+ - Issues communicating with the backend.
98
+ - Timeout during status polling.
99
+ - Invalid VP submission.
100
+
26
101
  ## Integration Guide
27
102
 
28
103
  ### OpenID4VPVerification
@@ -138,11 +213,11 @@ verifyServiceUrl="https://injiverify-service.example.com/v1/verify"
138
213
 
139
214
  - **Simulate Wallet Scan** : Use a mobile wallet app that supports OpenID4VP, or use mock tools to scan the QR code.
140
215
 
141
- - **Trigger Expiry** : Don't scan the QR and wait for expiry to ensure onQrCodeExpired fires.
216
+ - **Trigger Expiry** : Dont scan the QR and wait for expiry to ensure onQrCodeExpired fires.
142
217
 
143
218
  - **Force Errors** :
144
- - Stop the backend or simulate a 500 error.
145
- - Try missing required props or using both callbacks to see validation.
219
+ - Stop the backend or simulate a 500 error.
220
+ - Try missing required props or using both callbacks to see validation.
146
221
 
147
222
 
148
223
  ### Compatibility & Scope
@@ -159,4 +234,4 @@ verifyServiceUrl="https://injiverify-service.example.com/v1/verify"
159
234
 
160
235
  - ❌ Angular, Vue, or other frontend frameworks
161
236
 
162
- - ❌ SSR frameworks like Next.js without customization
237
+ - ❌ SSR frameworks like Next.js without customization
package/dist/index.js CHANGED
@@ -56,7 +56,7 @@ eval("\n\nif (false) {} else {\n module.exports = __webpack_require__(/*! ./cjs
56
56
  \*************************************************************************/
57
57
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
58
58
 
59
- eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"./node_modules/react/jsx-runtime.js\");\n/* harmony import */ var qrcode_react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! qrcode.react */ \"./node_modules/qrcode.react/lib/esm/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\nvar __assign = (undefined && undefined.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n};\n\n\n\nvar OpenID4VPVerification = function (_a) {\n var triggerElement = _a.triggerElement, verifyServiceUrl = _a.verifyServiceUrl, protocol = _a.protocol, presentationDefinitionId = _a.presentationDefinitionId, presentationDefinition = _a.presentationDefinition, onVPReceived = _a.onVPReceived, onVPProcessed = _a.onVPProcessed, qrCodeStyles = _a.qrCodeStyles, onQrCodeExpired = _a.onQrCodeExpired, onError = _a.onError;\n var _b = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(null), txnId = _b[0], setTxnId = _b[1];\n var _c = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(null), reqId = _c[0], setReqId = _c[1];\n var _d = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(null), qrCodeData = _d[0], setQrCodeData = _d[1];\n var _e = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(false), loading = _e[0], setLoading = _e[1];\n var OPENID4VP_PROTOCOL = \"\".concat(protocol || \"openid4vp://\", \"authorize?\");\n var generateNonce = function () {\n return btoa(Date.now().toString());\n };\n var getPresentationDefinition = (0,react__WEBPACK_IMPORTED_MODULE_2__.useCallback)(function (data) {\n var params = new URLSearchParams();\n params.set(\"client_id\", data.authorizationDetails.clientId);\n params.set(\"response_type\", data.authorizationDetails.responseType);\n params.set(\"response_mode\", \"direct_post\");\n params.set(\"nonce\", data.authorizationDetails.nonce);\n params.set(\"state\", data.requestId);\n params.set(\"response_uri\", verifyServiceUrl + data.authorizationDetails.responseUri);\n if (data.authorizationDetails.presentationDefinitionUri) {\n params.set(\"presentation_definition_uri\", verifyServiceUrl + data.authorizationDetails.presentationDefinitionUri);\n }\n else {\n params.set(\"presentation_definition\", JSON.stringify(data.authorizationDetails.presentationDefinition));\n }\n params.set(\"client_metadata\", JSON.stringify({ client_name: window.location.origin, vp_formats: {} }));\n return params.toString();\n }, [verifyServiceUrl]);\n var fetchVpResult = (0,react__WEBPACK_IMPORTED_MODULE_2__.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {\n var response, vpVerificationResult, parsedVcResults, vpResult, error_1;\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n _a.trys.push([0, 4, , 5]);\n if (!onVPProcessed) return [3 /*break*/, 3];\n return [4 /*yield*/, fetch(\"\".concat(verifyServiceUrl, \"/vp-result/\").concat(txnId))];\n case 1:\n response = _a.sent();\n if (response.status !== 200)\n throw new Error(\"Failed to fetch VP result\");\n return [4 /*yield*/, response.json()];\n case 2:\n vpVerificationResult = _a.sent();\n parsedVcResults = vpVerificationResult.vcResults.map(function (vcResult) {\n return {\n vc: JSON.parse(vcResult.vc),\n vcStatus: vcResult.verificationStatus,\n };\n });\n vpResult = {\n vcResults: parsedVcResults,\n vpResultStatus: vpVerificationResult.vpResultStatus,\n };\n onVPProcessed(vpResult);\n setTxnId(null);\n setReqId(null);\n setQrCodeData(null);\n _a.label = 3;\n case 3:\n if (onVPReceived && txnId) {\n onVPReceived(txnId);\n setTxnId(null);\n setReqId(null);\n setQrCodeData(null);\n }\n return [3 /*break*/, 5];\n case 4:\n error_1 = _a.sent();\n onError(error_1);\n setTxnId(null);\n setReqId(null);\n setQrCodeData(null);\n setLoading(false);\n return [3 /*break*/, 5];\n case 5: return [2 /*return*/];\n }\n });\n }); }, [onVPProcessed, onVPReceived, onError, txnId, verifyServiceUrl]);\n var createVpRequest = (0,react__WEBPACK_IMPORTED_MODULE_2__.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {\n var requestBody, response, data, qrData, error_2;\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n if (!((presentationDefinition === null || presentationDefinition === void 0 ? void 0 : presentationDefinition.input_descriptors.length) !== 0)) return [3 /*break*/, 5];\n _a.label = 1;\n case 1:\n _a.trys.push([1, 4, , 5]);\n addStylesheetRules();\n setLoading(true);\n requestBody = {\n clientId: window.location.origin,\n nonce: generateNonce(),\n };\n if (txnId)\n requestBody.transactionId = txnId;\n if (presentationDefinitionId)\n requestBody.presentationDefinitionId = presentationDefinitionId;\n if (presentationDefinition)\n requestBody.presentationDefinition = presentationDefinition;\n return [4 /*yield*/, fetch(\"\".concat(verifyServiceUrl, \"/vp-request\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(requestBody),\n })];\n case 2:\n response = _a.sent();\n if (response.status !== 201)\n throw new Error(\"Failed to create VP request\");\n return [4 /*yield*/, response.json()];\n case 3:\n data = _a.sent();\n qrData = OPENID4VP_PROTOCOL + getPresentationDefinition(data);\n setTxnId(data.transactionId);\n setReqId(data.requestId);\n setQrCodeData(qrData);\n setLoading(false);\n return [3 /*break*/, 5];\n case 4:\n error_2 = _a.sent();\n setLoading(false);\n onError(error_2);\n return [3 /*break*/, 5];\n case 5: return [2 /*return*/];\n }\n });\n }); }, [\n presentationDefinition,\n txnId,\n presentationDefinitionId,\n verifyServiceUrl,\n OPENID4VP_PROTOCOL,\n getPresentationDefinition,\n onError,\n ]);\n var fetchStatus = (0,react__WEBPACK_IMPORTED_MODULE_2__.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {\n var response, data, error_3;\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n _a.trys.push([0, 3, , 4]);\n return [4 /*yield*/, fetch(\"\".concat(verifyServiceUrl, \"/vp-request/\").concat(reqId, \"/status\"))];\n case 1:\n response = _a.sent();\n if (response.status !== 200)\n throw new Error(\"Failed to fetch status\");\n return [4 /*yield*/, response.json()];\n case 2:\n data = _a.sent();\n if (data.status === \"ACTIVE\") {\n fetchStatus();\n }\n if (data.status === \"VP_SUBMITTED\") {\n fetchVpResult();\n }\n else if (data.status === \"EXPIRED\") {\n setTxnId(null);\n setReqId(null);\n setQrCodeData(null);\n onQrCodeExpired();\n }\n return [3 /*break*/, 4];\n case 3:\n error_3 = _a.sent();\n setLoading(false);\n onError(error_3);\n return [3 /*break*/, 4];\n case 4: return [2 /*return*/];\n }\n });\n }); }, [verifyServiceUrl, reqId, onQrCodeExpired, onError, fetchVpResult]);\n (0,react__WEBPACK_IMPORTED_MODULE_2__.useEffect)(function () {\n if (!presentationDefinitionId && !presentationDefinition) {\n throw new Error(\"Either presentationDefinitionId or presentationDefinition must be provided, but not both\");\n }\n if (presentationDefinitionId && presentationDefinition) {\n throw new Error(\"Both presentationDefinitionId and presentationDefinition cannot be provided simultaneously\");\n }\n if (!onVPReceived && !onVPProcessed) {\n throw new Error(\"Either onVpReceived or onVpProcessed must be provided, but not both\");\n }\n if (onVPReceived && onVPProcessed) {\n throw new Error(\"Both onVPReceived and onVPProcessed cannot be provided simultaneously\");\n }\n if (!onQrCodeExpired) {\n throw new Error(\"onQrCodeExpired callback is required\");\n }\n if (!onError) {\n throw new Error(\"onError callback is required\");\n }\n if (!triggerElement) {\n createVpRequest();\n }\n }, [\n createVpRequest,\n onError,\n onQrCodeExpired,\n onVPProcessed,\n onVPReceived,\n presentationDefinition,\n presentationDefinitionId,\n triggerElement,\n ]);\n (0,react__WEBPACK_IMPORTED_MODULE_2__.useEffect)(function () {\n if (reqId) {\n fetchStatus();\n }\n }, [fetchStatus, reqId]);\n function addStylesheetRules() {\n var keyframes = \"@keyframes spin {0% {transform: rotate(0deg);}100% {transform: rotate(360deg);}}\";\n var styleEl = document.createElement(\"style\");\n document.head.appendChild(styleEl);\n var styleSheet = styleEl.sheet;\n styleSheet === null || styleSheet === void 0 ? void 0 : styleSheet.insertRule(keyframes, 0);\n }\n return ((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", __assign({ style: {\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n minWidth: \"100%\",\n } }, { children: [triggerElement && !qrCodeData && !loading ? ((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", __assign({ onClick: createVpRequest, style: { cursor: \"pointer\" } }, { children: triggerElement }))) : null, loading && ((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", { style: {\n width: \"40px\",\n height: \"40px\",\n border: \"4px solid #ccc\",\n borderTop: \"4px solid #333\",\n borderRadius: \"50%\",\n animation: \"spin 1s linear infinite\",\n margin: \"20px auto\",\n } })), !loading && qrCodeData && ((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", __assign({ \"data-testid\": \"qr-code\" }, { children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(qrcode_react__WEBPACK_IMPORTED_MODULE_1__.QRCodeSVG, { value: qrCodeData, size: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.size) || 200, level: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.level) || \"L\", bgColor: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.bgColor) || \"#ffffff\", fgColor: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.fgColor) || \"#000000\", marginSize: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.margin) || 10, style: { borderRadius: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.borderRadius) || 10 } }) })))] })));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OpenID4VPVerification);\n\n\n//# sourceURL=webpack://@mosip/react-inji-verify-sdk/./src/components/openid4vp-verification/OpenID4VPVerification.tsx?");
59
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react/jsx-runtime */ \"./node_modules/react/jsx-runtime.js\");\n/* harmony import */ var qrcode_react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! qrcode.react */ \"./node_modules/qrcode.react/lib/esm/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\nvar __assign = (undefined && undefined.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __generator = (undefined && undefined.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n};\n\n\n\nvar OpenID4VPVerification = function (_a) {\n var triggerElement = _a.triggerElement, verifyServiceUrl = _a.verifyServiceUrl, protocol = _a.protocol, presentationDefinitionId = _a.presentationDefinitionId, presentationDefinition = _a.presentationDefinition, onVPReceived = _a.onVPReceived, onVPProcessed = _a.onVPProcessed, qrCodeStyles = _a.qrCodeStyles, onQrCodeExpired = _a.onQrCodeExpired, onError = _a.onError;\n var _b = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(null), txnId = _b[0], setTxnId = _b[1];\n var _c = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(null), reqId = _c[0], setReqId = _c[1];\n var _d = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(null), qrCodeData = _d[0], setQrCodeData = _d[1];\n var _e = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(false), loading = _e[0], setLoading = _e[1];\n var OPENID4VP_PROTOCOL = \"\".concat(protocol || \"openid4vp://\", \"authorize?\");\n var generateNonce = function () {\n return btoa(Date.now().toString());\n };\n var VPFormat = {\n ldp_vp: {\n proof_type: [\n \"Ed25519Signature2018\",\n \"Ed25519Signature2020\",\n \"RsaSignature2018\",\n ],\n },\n };\n var getPresentationDefinition = (0,react__WEBPACK_IMPORTED_MODULE_2__.useCallback)(function (data) {\n var params = new URLSearchParams();\n params.set(\"client_id\", data.authorizationDetails.clientId);\n params.set(\"response_type\", data.authorizationDetails.responseType);\n params.set(\"response_mode\", \"direct_post\");\n params.set(\"nonce\", data.authorizationDetails.nonce);\n params.set(\"state\", data.requestId);\n params.set(\"response_uri\", verifyServiceUrl + data.authorizationDetails.responseUri);\n if (data.authorizationDetails.presentationDefinitionUri) {\n params.set(\"presentation_definition_uri\", verifyServiceUrl + data.authorizationDetails.presentationDefinitionUri);\n }\n else {\n params.set(\"presentation_definition\", JSON.stringify(data.authorizationDetails.presentationDefinition));\n }\n params.set(\"client_metadata\", JSON.stringify({ client_name: window.location.origin, vp_formats: VPFormat }));\n return params.toString();\n }, [verifyServiceUrl]);\n var fetchVpResult = (0,react__WEBPACK_IMPORTED_MODULE_2__.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {\n var response, vpVerificationResult, parsedVcResults, vpResult, error_1;\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n _a.trys.push([0, 4, , 5]);\n if (!onVPProcessed) return [3 /*break*/, 3];\n return [4 /*yield*/, fetch(\"\".concat(verifyServiceUrl, \"/vp-result/\").concat(txnId))];\n case 1:\n response = _a.sent();\n if (response.status !== 200)\n throw new Error(\"Failed to fetch VP result\");\n return [4 /*yield*/, response.json()];\n case 2:\n vpVerificationResult = _a.sent();\n parsedVcResults = vpVerificationResult.vcResults.map(function (vcResult) {\n return {\n vc: JSON.parse(vcResult.vc),\n vcStatus: vcResult.verificationStatus,\n };\n });\n vpResult = {\n vcResults: parsedVcResults,\n vpResultStatus: vpVerificationResult.vpResultStatus,\n };\n onVPProcessed(vpResult);\n setTxnId(null);\n setReqId(null);\n setQrCodeData(null);\n _a.label = 3;\n case 3:\n if (onVPReceived && txnId) {\n onVPReceived(txnId);\n setTxnId(null);\n setReqId(null);\n setQrCodeData(null);\n }\n return [3 /*break*/, 5];\n case 4:\n error_1 = _a.sent();\n onError(error_1);\n setTxnId(null);\n setReqId(null);\n setQrCodeData(null);\n setLoading(false);\n return [3 /*break*/, 5];\n case 5: return [2 /*return*/];\n }\n });\n }); }, [onVPProcessed, onVPReceived, onError, txnId, verifyServiceUrl]);\n var createVpRequest = (0,react__WEBPACK_IMPORTED_MODULE_2__.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {\n var requestBody, response, data, qrData, error_2;\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n if (!((presentationDefinition === null || presentationDefinition === void 0 ? void 0 : presentationDefinition.input_descriptors.length) !== 0)) return [3 /*break*/, 5];\n _a.label = 1;\n case 1:\n _a.trys.push([1, 4, , 5]);\n addStylesheetRules();\n setLoading(true);\n requestBody = {\n clientId: window.location.origin,\n nonce: generateNonce(),\n };\n if (txnId)\n requestBody.transactionId = txnId;\n if (presentationDefinitionId)\n requestBody.presentationDefinitionId = presentationDefinitionId;\n if (presentationDefinition)\n requestBody.presentationDefinition = presentationDefinition;\n return [4 /*yield*/, fetch(\"\".concat(verifyServiceUrl, \"/vp-request\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(requestBody),\n })];\n case 2:\n response = _a.sent();\n if (response.status !== 201)\n throw new Error(\"Failed to create VP request\");\n return [4 /*yield*/, response.json()];\n case 3:\n data = _a.sent();\n qrData = OPENID4VP_PROTOCOL + getPresentationDefinition(data);\n setTxnId(data.transactionId);\n setReqId(data.requestId);\n setQrCodeData(qrData);\n setLoading(false);\n return [3 /*break*/, 5];\n case 4:\n error_2 = _a.sent();\n setLoading(false);\n onError(error_2);\n return [3 /*break*/, 5];\n case 5: return [2 /*return*/];\n }\n });\n }); }, [\n presentationDefinition,\n txnId,\n presentationDefinitionId,\n verifyServiceUrl,\n OPENID4VP_PROTOCOL,\n getPresentationDefinition,\n onError,\n ]);\n var fetchStatus = (0,react__WEBPACK_IMPORTED_MODULE_2__.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {\n var response, data, error_3;\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n _a.trys.push([0, 3, , 4]);\n return [4 /*yield*/, fetch(\"\".concat(verifyServiceUrl, \"/vp-request/\").concat(reqId, \"/status\"))];\n case 1:\n response = _a.sent();\n if (response.status !== 200)\n throw new Error(\"Failed to fetch status\");\n return [4 /*yield*/, response.json()];\n case 2:\n data = _a.sent();\n if (data.status === \"ACTIVE\") {\n fetchStatus();\n }\n if (data.status === \"VP_SUBMITTED\") {\n fetchVpResult();\n }\n else if (data.status === \"EXPIRED\") {\n setTxnId(null);\n setReqId(null);\n setQrCodeData(null);\n onQrCodeExpired();\n }\n return [3 /*break*/, 4];\n case 3:\n error_3 = _a.sent();\n setLoading(false);\n onError(error_3);\n return [3 /*break*/, 4];\n case 4: return [2 /*return*/];\n }\n });\n }); }, [verifyServiceUrl, reqId, onQrCodeExpired, onError, fetchVpResult]);\n (0,react__WEBPACK_IMPORTED_MODULE_2__.useEffect)(function () {\n if (!presentationDefinitionId && !presentationDefinition) {\n throw new Error(\"Either presentationDefinitionId or presentationDefinition must be provided, but not both\");\n }\n if (presentationDefinitionId && presentationDefinition) {\n throw new Error(\"Both presentationDefinitionId and presentationDefinition cannot be provided simultaneously\");\n }\n if (!onVPReceived && !onVPProcessed) {\n throw new Error(\"Either onVpReceived or onVpProcessed must be provided, but not both\");\n }\n if (onVPReceived && onVPProcessed) {\n throw new Error(\"Both onVPReceived and onVPProcessed cannot be provided simultaneously\");\n }\n if (!onQrCodeExpired) {\n throw new Error(\"onQrCodeExpired callback is required\");\n }\n if (!onError) {\n throw new Error(\"onError callback is required\");\n }\n if (!triggerElement) {\n createVpRequest();\n }\n }, [\n createVpRequest,\n onError,\n onQrCodeExpired,\n onVPProcessed,\n onVPReceived,\n presentationDefinition,\n presentationDefinitionId,\n triggerElement,\n ]);\n (0,react__WEBPACK_IMPORTED_MODULE_2__.useEffect)(function () {\n if (reqId) {\n fetchStatus();\n }\n }, [fetchStatus, reqId]);\n function addStylesheetRules() {\n var keyframes = \"@keyframes spin {0% {transform: rotate(0deg);}100% {transform: rotate(360deg);}}\";\n var styleEl = document.createElement(\"style\");\n document.head.appendChild(styleEl);\n var styleSheet = styleEl.sheet;\n styleSheet === null || styleSheet === void 0 ? void 0 : styleSheet.insertRule(keyframes, 0);\n }\n return ((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(\"div\", __assign({ style: {\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n minWidth: \"100%\",\n } }, { children: [triggerElement && !qrCodeData && !loading ? ((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", __assign({ onClick: createVpRequest, style: { cursor: \"pointer\" } }, { children: triggerElement }))) : null, loading && ((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", { style: {\n width: \"40px\",\n height: \"40px\",\n border: \"4px solid #ccc\",\n borderTop: \"4px solid #333\",\n borderRadius: \"50%\",\n animation: \"spin 1s linear infinite\",\n margin: \"20px auto\",\n } })), !loading && qrCodeData && ((0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(\"div\", __assign({ \"data-testid\": \"qr-code\" }, { children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(qrcode_react__WEBPACK_IMPORTED_MODULE_1__.QRCodeSVG, { value: qrCodeData, size: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.size) || 200, level: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.level) || \"L\", bgColor: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.bgColor) || \"#ffffff\", fgColor: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.fgColor) || \"#000000\", marginSize: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.margin) || 10, style: { borderRadius: (qrCodeStyles === null || qrCodeStyles === void 0 ? void 0 : qrCodeStyles.borderRadius) || 10 } }) })))] })));\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OpenID4VPVerification);\n\n\n//# sourceURL=webpack://@mosip/react-inji-verify-sdk/./src/components/openid4vp-verification/OpenID4VPVerification.tsx?");
60
60
 
61
61
  /***/ }),
62
62
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mosip/react-inji-verify-sdk",
3
- "version": "0.12.0-beta",
3
+ "version": "0.12.3",
4
4
  "description": "A react component library to perform Inji verify tasks, such as OpenId4VP sharing, Reading VC QR codes",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",