@injistack/react-inji-verify-sdk 0.18.0-beta.8 → 0.19.0-beta.1

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
@@ -2,6 +2,32 @@
2
2
 
3
3
  Inji Verify SDK provides ready-to-use **React components** to integrate [OpenID4VP](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html)-based **Verifiable Credential (VC) and Verifiable Presentation (VP) verification** into any React TypeScript web application.
4
4
 
5
+ ## Pre-requisites
6
+
7
+ ### What You Need:
8
+
9
+ 1. **A React project** (TypeScript recommended)
10
+ 2. **A verification backend** - You need a server that can verify credentials
11
+ 3. **Camera permissions** - For QR scanning features
12
+
13
+ ### Backend Requirements:
14
+
15
+ Your backend must support the OpenID4VP protocol. You can either:
16
+
17
+ - Use the official `inji-verify-service`
18
+ - Build your own following [this specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0-ID3.html)
19
+
20
+ **Important:** Your backend URL should look like:
21
+
22
+ ```
23
+ https://your-backend.com/v1/verify
24
+ ```
25
+
26
+ > **Note**
27
+ >
28
+ > - The SDK uses a session-based verification flow internally.
29
+ > - Session handling, redirects, and result fetching are managed by the SDK.
30
+ > - No manual handling of `transactionId` or browser storage is required.
5
31
  ## Usage Guide
6
32
 
7
33
  ### Step 1: Install the Package
@@ -10,7 +36,7 @@ Inji Verify SDK provides ready-to-use **React components** to integrate [OpenID4
10
36
  npm i @injistack/react-inji-verify-sdk
11
37
  ```
12
38
 
13
- ### Step 2: Import and Use
39
+ ### Step 2: Import & Usage
14
40
 
15
41
  ```javascript
16
42
  import {
@@ -19,7 +45,7 @@ import {
19
45
  } from "@injistack/react-inji-verify-sdk";
20
46
  ```
21
47
 
22
- ### Step 3: Choose Your Verification Method
48
+ ### Step 3: Choose Verification Method
23
49
 
24
50
  **Option A: QR Code Verification (Scan & Upload)**
25
51
 
@@ -27,16 +53,17 @@ import {
27
53
  function MyApp() {
28
54
  return (
29
55
  <QRCodeVerification
30
- verifyServiceUrl="https://your-backend.com/verify"
31
- onVCProcessed={(result) => {
32
- console.log("Verification complete:", result);
33
- // Handle the verification result here
34
- }}
35
- onError={(error) => {
36
- console.log("Something went wrong:", error);
37
- }}
38
- triggerElement={<button>📷 Scan ID Document</button>}
39
- clientId="CLIENT_ID"
56
+ triggerElement={triggerElement} //UI element used to start verification.
57
+ verifyServiceUrl="https://your-backend.com/v1/verify"
58
+ isEnableScan={false}
59
+ onVCProcessed={(result) => {
60
+ console.log("Verification complete:", result);
61
+ // Handle the verification result here
62
+ }}
63
+ onError={(error) => {
64
+ console.log("Something went wrong:", error);
65
+ }}
66
+ clientId="did:example:123456789" // DID example
40
67
  />
41
68
  );
42
69
  }
@@ -48,149 +75,597 @@ function MyApp() {
48
75
  function MyApp() {
49
76
  return (
50
77
  <OpenID4VPVerification
51
- verifyServiceUrl="https://your-backend.com/v1/verify"
52
- presentationDefinitionId="your-definition-id"
53
- onVpProcessed={(result) => {
54
- console.log("Wallet verification complete:", result);
55
- // Handle the verification result here
56
- }}
57
- onQrCodeExpired={() => alert("QR code expired, please try again")}
58
- onError={(error) => console.log("Error:", error)}
59
- triggerElement={<button>📱 Verify with Digital Wallet</button>}
60
- clientId="CLIENT_ID"
78
+ triggerElement={<button>Show QR for Wallet Scan</button>}
79
+ verifyServiceUrl="https://your-backend.com/v1/verify"
80
+ clientId="did:example:123456789" // DID example
81
+ presentationDefinitionId="your-definition-id"
82
+ isSameDeviceFlowEnabled={false} // QR code flow
83
+ onVPProcessed={(result) => {
84
+ console.log("VP processed:", result);
85
+ }}
86
+ onQrCodeExpired={() => {
87
+ console.log(" QR code expired - ask user to retry");
88
+ }}
89
+ onError={(error) => {
90
+ console.error("Verification error:", error);
91
+ }}
61
92
  />
62
93
  );
63
94
  }
64
95
  ```
65
96
 
66
- ## Response Received
97
+ ## Verification Response
98
+
99
+ Once verification is complete, the response depends on the `summariseResults` attribute (default = true)
100
+
101
+ If `summariseResults = true`, the response will be:
102
+
103
+ #### For QRCodeVerification (Upload / Scan):
67
104
 
68
- When verification is completed, the response received is as below:
69
105
 
70
106
  ```javascript
71
107
  {
72
- vcResults: [
108
+ "verificationStatus":"STATUS"
109
+ }
110
+ ```
111
+ #### For OpenID4VPVerification:
112
+ ```javascript
113
+ {
114
+ "vcResults": [
73
115
  {
74
- vc: { /* Your verified credential data */ },
75
- vcStatus: "SUCCESS" // or "INVALID", "EXPIRED"
116
+ "vc": { /* Your verified credential data */ },
117
+ "vcStatus": "SUCCESS" // or "INVALID", "EXPIRED"
76
118
  }
77
119
  ],
78
- vpResultStatus: "SUCCESS" // Overall verification status
120
+ "vpResultStatus": "SUCCESS" // Overall verification status
79
121
  }
80
122
  ```
81
123
 
82
124
  > **Security Recommendation**
83
125
  >
84
126
  > Avoid consuming results directly from VPProcessed or VCProcessed.
85
- > Instead, use VPReceived or VCReceived events to capture the txnId, then retrieve the verification results securely from your backend's verification service endpoint.
127
+ > Instead, use VPReceived or VCReceived events to capture the transactionId, then retrieve the verification results securely from your backend's verification service endpoint.
86
128
  > This ensures data integrity and prevents reliance on client-side verification data for final decisions.
87
129
 
88
- ## Pre-requisites
130
+ ## Detailed Component Guide
131
+ The following sections provide advanced usage and detailed configuration for each component.
132
+ > The package should already be installed as described in the Usage Guide.
89
133
 
90
- ### What You Need:
134
+ ### Option A: QR Code Verification (Scan & Upload)
91
135
 
92
- 1. **A React project** (TypeScript recommended)
93
- 2. **A verification backend** - You need a server that can verify credentials
94
- 3. **Camera permissions** - For QR scanning features
136
+ The QRCodeVerification component enables end-to-end Verifiable Credential (VC) verification using QR codes in Inji-Verify. It supports both camera-based scanning and file upload for QR code verification.
95
137
 
96
- ### Backend Requirements:
138
+ **Perfect for:** Scanning QR codes from documents, or uploading QR codes (PNG, JPEG, JPG, PDF) within the supported size range of 10 KB to 5 MB.
97
139
 
98
- Your backend must support the OpenID4VP protocol. You can either:
140
+ Follow these steps to integrate:
99
141
 
100
- - Use the official `inji-verify-service`
101
- - Build your own following [this specification](https://openid.net/specs/openid-4-verifiable-presentations-1_0-ID3.html)
142
+ #### Import & Usage
102
143
 
103
- **Important:** Your backend URL should look like:
144
+ ```javascript
145
+ import {QRCodeVerification} from "@injistack/react-inji-verify-sdk";
146
+ ```
147
+
148
+ #### 1. Uploading a Verifiable Credential (VC) for verification
149
+
150
+ a. Client-side handling (onVCProcessed)
104
151
 
152
+ ```javascript
153
+ function MyApp() {
154
+ return (
155
+ <QRCodeVerification
156
+ triggerElement={triggerElement} //UI element used to start verification.
157
+ verifyServiceUrl="https://your-backend.com/v1/verify"
158
+ isEnableScan={false}
159
+ onVCProcessed={(result) => {
160
+ console.log("Verification complete:", result);
161
+ // Handle the verification result here
162
+ }}
163
+ onError={(error) => {
164
+ console.log("Something went wrong:", error);
165
+ }}
166
+ clientId="did:example:123456789" // DID example
167
+ />
168
+ );
169
+ }
105
170
  ```
106
- https://your-backend.com
171
+ b. Server-to-server handling (onVCReceived)
172
+ ```javascript
173
+ function MyApp() {
174
+ return (
175
+ <QRCodeVerification
176
+ triggerElement={triggerElement}
177
+ verifyServiceUrl="https://your-backend.com/v1/verify"
178
+ isEnableScan={false}
179
+ onVCReceived={(transactionId) => {
180
+ //using the transactionId, one can securely fetch the result from service
181
+ console.log("VC received transactionId:", transactionId);
182
+ }}
183
+ onError={(error) => {
184
+ console.log("Something went wrong:", error);
185
+ }}
186
+ clientId="client-12345" // non-DID example
187
+ />
188
+ );
189
+ }
107
190
  ```
108
191
 
109
- ## 📖 Detailed Component Guide
192
+ > 🔁 **Verification Handling Modes**
193
+ >
194
+ > **Client-side Handling (`onVCProcessed` / `onVPProcessed`)**
195
+ > - SDK returns verification result directly to frontend
196
+ > - Faster and simple
197
+ >
198
+ > **Server-to-server Handling (`onVCReceived` / `onVPReceived`)**
199
+ > - SDK returns only `transactionId`
200
+ > - Backend fetches result securely
110
201
 
111
- ### QRCodeVerification Component
202
+ #### 2. Scanning a Verifiable Credential (VC) Using Device Camera
112
203
 
113
- **Perfect for:** Scanning QR codes from documents or uploading QR codes (PNG, JPEG, JPG, PDF)
204
+ a. Client-side handling (onVCProcessed)
114
205
 
115
- #### Basic Setup:
206
+ ```javascript
207
+ function MyApp() {
208
+ return (
209
+ <QRCodeVerification
210
+ scannerActive={scannerActive}
211
+ verifyServiceUrl="https://your-backend.com/v1/verify"
212
+ isEnableUpload={false}
213
+ onClose={onClose} // invoked when scanner is closed
214
+ onVCProcessed={(result) => {
215
+ console.log("Verification complete:", result);
216
+ // Handle the verification result here
217
+ }}
218
+ onError={(error) => {
219
+ console.log("Something went wrong:", error);
220
+ }}
221
+ clientId="did:example:123456789" // DID example
222
+ />
223
+ );
224
+ }
225
+ ```
226
+ b. Server-to-server handling (onVCReceived)
116
227
 
117
228
  ```javascript
118
- <QRCodeVerification
119
- verifyServiceUrl="https://your-backend.com"
120
- onVCProcessed={(result) => handleResult(result)}
121
- onError={(error) => handleError(error)}
122
- triggerElement={<button>Start Verification</button>}
123
- clientId="CLIENT_ID"
124
- />
229
+ function MyApp() {
230
+ return (
231
+ <QRCodeVerification
232
+ scannerActive={scannerActive}
233
+ verifyServiceUrl="https://your-backend.com/v1/verify"
234
+ isEnableUpload={false}
235
+ onClose={onClose} // invoked when scanner is closed
236
+ onVCReceived={(transactionId) => {
237
+ //using the transactionId, one can securely fetch the result from service
238
+ console.log("VC received transactionId:", transactionId);
239
+ }}
240
+ onError={(error) => {
241
+ console.log("Something went wrong:", error);
242
+ }}
243
+ clientId="did:example:123456789" // DID example
244
+ />
245
+ );
246
+ }
125
247
  ```
126
248
 
127
- #### All Available Options:
249
+ ### Verification Response
250
+
251
+ Once VC Verification is complete, the response depends on the `summariseResults` attribute (default = true)
252
+
253
+ If `summariseResults = true`, the response will be:
128
254
 
129
255
  ```javascript
130
- <QRCodeVerification
131
- // Required
132
- verifyServiceUrl="https://your-backend.com"
133
- onVCProcessed={(result) => console.log(result)} // OR use onVCReceived
134
- onError={(error) => console.log(error)}
135
- clientId="CLIENT_ID"
136
- // Optional
137
- triggerElement={<button>Custom Trigger</button>}
138
- transactionId="your-tracking-id" //Optional
139
- uploadButtonId="my-upload-btn"
140
- uploadButtonStyle={{ backgroundColor: "blue" }}
141
- isEnableUpload={true} // Allow file uploads
142
- isEnableScan={true} // Allow camera scanning
143
- isEnableZoom={true} // Allow camera zoom
144
- isVPSubmissionSupported={false} // This attribute indicates whether VP submission is supported in Inji OVP VC sharing flow. By default, it is false which means that VP token will be directly sent in response. If set to true, then VP token will be submitted to the VP_SUBMISSION_ URL.
145
- acceptVPWithoutHolderProof={false} // This attribute controls whether unsigned Verifiable Presentations (VPs without proof) are allowed in the Inji OVP VC sharing flow. By default, it is set to false, meaning unsigned VP tokens are not supported and an error is thrown if an unsigned VP is received. If set to true, VP tokens without a signature (proof) are allowed and can be verified. For data-share it is set to true by default.
146
- />
256
+ {
257
+ "verificationStatus":"STATUS"
258
+ }
147
259
  ```
148
260
 
149
- **Choose One Callback:**
261
+ If `summariseResults = false`, the response will be:
150
262
 
151
- - `onVCProcessed`: Get full verification results immediately
152
- - `onVCReceived`: Get just a transaction ID (your backend handles the rest)
263
+ ```javascript
264
+ {
265
+ "allChecksSuccessful": true,
266
+ "schemaAndSignatureCheck": { "valid": true, "error": null },
267
+ "expiryCheck": { "valid": true },
268
+ "statusChecks": [
269
+ { "purpose": "revocation", "valid": true, "error": null }
270
+ ],
271
+ "claims": {...}
272
+ }
273
+ ```
274
+
275
+ #### Response Fields Summary
153
276
 
154
- ### OpenID4VPVerification Component
277
+ | Property | Type | Description |
278
+ |---------------------------|---------|-----------------------------------------------------------|
279
+ | `allChecksSuccessful` | boolean | Final aggregated validation flag |
280
+ | `schemaAndSignatureCheck` | object | Validates schema and signature check |
281
+ | `expiryCheck` | object | If false, the credential is EXPIRED |
282
+ | `statusChecks` | array | Contains revocation and other status validations |
283
+ | `statusChecks.error` | object | If present, throws an error instead of returning a status |
284
+ | `statusChecks.purpose` | string | Identifies purpose (e.g., "revocation") |
285
+ | `statusChecks.valid` | boolean | If false for revocation → credential is revoked |
286
+ | `claims` | object | Includes all claims from credentialSubject |
287
+
288
+ ### Option B: OpenID4VP Verification
289
+ OpenID4VPVerification Component verifies Verifiable Presentations securely using OpenID4VP standards for both cross-device and same-device flows.
155
290
 
156
291
  **Perfect for:** Integrating with digital wallets (like mobile ID apps)
157
292
 
158
- #### Basic Setup:
293
+ Follow these steps to integrate:
294
+
295
+ #### Import & Usage
159
296
 
160
297
  ```javascript
161
- <OpenID4VPVerification
162
- verifyServiceUrl="https://your-backend.com"
163
- presentationDefinitionId="what-you-want-to-verify"
164
- onVpProcessed={(result) => handleResult(result)}
165
- onQrCodeExpired={() => alert("Please try again")}
166
- onError={(error) => handleError(error)}
167
- clientId="CLIENT_ID"
168
- />
298
+ import {OpenID4VPVerification} from "@injistack/react-inji-verify-sdk";
169
299
  ```
170
300
 
171
- #### With Presentation Definition:
301
+ #### 1. Cross-device flow (QR code scan from another device)
302
+ ```javascript
303
+ import { OpenID4VPVerification } from "@injistack/react-inji-verify-sdk";
304
+ export default function VerifyCrossDevice() {
305
+ return (
306
+ <OpenID4VPVerification
307
+ triggerElement={<button>Show QR for Wallet Scan</button>}
308
+ verifyServiceUrl="https://your-backend.com/v1/verify"
309
+ clientId="did:example:123456789" // DID example
310
+ presentationDefinition={{
311
+ id: "custom-verification",
312
+ purpose: "We need to verify your identity",
313
+ format: {
314
+ ldp_vc: {
315
+ proof_type: ["Ed25519Signature2020"],
316
+ },
317
+ },
318
+ input_descriptors: [
319
+ {
320
+ id: "id-card-check",
321
+ constraints: {
322
+ fields: [
323
+ {
324
+ path: ["$.type"],
325
+ filter: {
326
+ type: "object",
327
+ pattern: "DriverLicenseCredential",
328
+ },
329
+ },
330
+ ],
331
+ },
332
+ },
333
+ ],
334
+ }}
335
+ isSameDeviceFlowEnabled={false} // QR code flow
336
+ onVPProcessed={(result) => {
337
+ console.log("VP processed:", result);
338
+ }}
339
+ onQrCodeExpired={() => {
340
+ console.log(" QR code expired - ask user to retry");
341
+ }}
342
+ onError={(error) => {
343
+ console.error("Verification error:", error);
344
+ }}
345
+
346
+ />
347
+ );
348
+ }
349
+ ```
350
+ ```mermaid
351
+ sequenceDiagram
352
+ autonumber
353
+ participant UserBrowser as User Browser
354
+ participant VerifierBackend as Verifier Backend
355
+ participant MobileWallet as Wallet (Mobile)
356
+
357
+ UserBrowser->>VerifierBackend: Start verification(/vp-session-request,response_code_validation_required=false)
358
+
359
+ VerifierBackend->>VerifierBackend: Generate transaction_id and request_id
360
+ VerifierBackend-->>UserBrowser: Set HttpOnly Cookie (txn_id)
361
+ VerifierBackend-->>UserBrowser: Return OpenID4VP request + QR code
362
+
363
+ UserBrowser->>MobileWallet: User scans QR code
364
+
365
+ MobileWallet->>VerifierBackend: Submit vp_token + presentation_submission
366
+
367
+ loop Long Polling
368
+ UserBrowser->>VerifierBackend: GET /vp-request/{requestId}/status
369
+ VerifierBackend-->>UserBrowser: Pending
370
+ end
371
+
372
+ VerifierBackend-->>UserBrowser: Completed
373
+
374
+ UserBrowser->>VerifierBackend: GET /vp-session-results (Cookie txn_id automatically sent)
375
+
376
+ VerifierBackend->>VerifierBackend: Resolve txn_id from cookie
377
+ VerifierBackend->>VerifierBackend: Fetch transaction state
378
+
379
+ VerifierBackend-->>UserBrowser: Verification result
380
+ ```
381
+
382
+ #### 2. Same Device Flow with Mobile Wallet
383
+ Used when a native mobile wallet app is triggered via deep link.
172
384
 
173
385
  ```javascript
174
- <OpenID4VPVerification
175
- verifyServiceUrl="https://your-backend.com"
176
- presentationDefinition={"Refer Option 2 below"}
177
- onVpProcessed={(result) => console.log(result)}
178
- onQrCodeExpired={() => alert("QR expired")}
179
- onError={(error) => console.error(error)}
180
- triggerElement={<button>🔐 Verify Credentials</button>}
181
- clientId="CLIENT_ID"
182
- />
386
+ import { OpenID4VPVerification } from "@injistack/react-inji-verify-sdk";
387
+ export default function VerifySameDevice() {
388
+ return (
389
+ <OpenID4VPVerification
390
+ triggerElement={<button>Verify with Wallet</button>}
391
+ verifyServiceUrl="https://your-backend.com/v1/verify"
392
+ clientId="client-12345" // non-DID example
393
+ presentationDefinition={{
394
+ id: "custom-verification",
395
+ purpose: "We need to verify your identity",
396
+ format: {
397
+ ldp_vc: {
398
+ proof_type: ["Ed25519Signature2020"],
399
+ },
400
+ },
401
+ input_descriptors: [
402
+ {
403
+ id: "id-card-check",
404
+ constraints: {
405
+ fields: [
406
+ {
407
+ path: ["$.type"],
408
+ filter: {
409
+ type: "object",
410
+ pattern: "DriverLicenseCredential",
411
+ },
412
+ },
413
+ ],
414
+ },
415
+ },
416
+ ],
417
+ }}
418
+ isSameDeviceFlowEnabled={true} //default value
419
+ // No webWalletBaseUrl → triggers mobile wallet via deep link
420
+ onVPProcessed={(result) => {
421
+ console.log("VP processed:", result);
422
+ }}
423
+ onError={(error) => {
424
+ console.error("Verification error:", error);
425
+ }}
426
+ />
427
+ );
428
+ }
183
429
  ```
184
430
 
431
+ ```mermaid
432
+ sequenceDiagram
433
+ autonumber
434
+ participant UserBrowser as User Browser (Verifier App)
435
+ participant VerifierBackend as Verifier Backend
436
+ participant MobileWallet as Mobile Wallet App
437
+
438
+ UserBrowser->>VerifierBackend: Start verification(/vp-session-request,response_code_validation_required=false)
439
+
440
+ VerifierBackend->>VerifierBackend: Generate transaction_id and request_id
441
+ VerifierBackend-->>UserBrowser: Set HttpOnly Cookie (txn_id)
442
+ VerifierBackend-->>UserBrowser: Return OpenID4VP authorization request
443
+
444
+ UserBrowser->>MobileWallet: Open mobile wallet via deep link
445
+
446
+ MobileWallet->>VerifierBackend: Submit vp_token + presentation_submission
447
+
448
+ Note right of MobileWallet: User manually switches back to browser
449
+
450
+ loop Long Polling
451
+ UserBrowser->>VerifierBackend: GET /vp-request/{requestId}/status
452
+ VerifierBackend-->>UserBrowser: Pending
453
+ end
454
+
455
+ VerifierBackend-->>UserBrowser: Completed
456
+
457
+ UserBrowser->>VerifierBackend: GET /vp-session-results (Cookie txn_id automatically sent)
458
+
459
+ VerifierBackend->>VerifierBackend: Resolve txn_id from cookie
460
+ VerifierBackend->>VerifierBackend: Fetch transaction state
461
+
462
+ VerifierBackend-->>UserBrowser: Verification result
463
+ VerifierBackend-->>UserBrowser: Clear cookie (txn_id)
464
+ ```
465
+
466
+ #### 3. Same Device Flow with Web Wallet
467
+ Used when verification happens in a web-based wallet on the same device.
468
+
469
+ ```javascript
470
+ import { OpenID4VPVerification } from "@injistack/react-inji-verify-sdk";
471
+ export default function VerifySameDevice() {
472
+ return (
473
+ <OpenID4VPVerification
474
+ triggerElement={<button>Verify with Wallet</button>}
475
+ verifyServiceUrl="https://your-backend.com/v1/verify"
476
+ clientId="did:example:123456789" // DID example
477
+ presentationDefinition={{
478
+ id: "custom-verification",
479
+ purpose: "We need to verify your identity",
480
+ format: {
481
+ ldp_vc: {
482
+ proof_type: ["Ed25519Signature2020"],
483
+ },
484
+ },
485
+ input_descriptors: [
486
+ {
487
+ id: "id-card-check",
488
+ constraints: {
489
+ fields: [
490
+ {
491
+ path: ["$.type"],
492
+ filter: {
493
+ type: "object",
494
+ pattern: "DriverLicenseCredential",
495
+ },
496
+ },
497
+ ],
498
+ },
499
+ },
500
+ ],
501
+ }}
502
+ isSameDeviceFlowEnabled={true} //default value
503
+ webWalletBaseUrl="https://wallet.example.com" // required to support web-wallets
504
+ onVPProcessed={(result) => {
505
+ console.log("VP processed:", result);
506
+ }}
507
+ onError={(error) => {
508
+ console.error("Verification error:", error);
509
+ }}
510
+ />
511
+ );
512
+ }
513
+ ```
514
+
515
+ ```mermaid
516
+ sequenceDiagram
517
+ autonumber
518
+ participant UserBrowser as User Browser
519
+ participant VerifierBackend as Verifier Backend
520
+ participant WebWallet as Web Wallet
521
+
522
+ UserBrowser->>VerifierBackend: Start verification\n(/vp-session-request,\nresponse_code_validation_required=true)
523
+
524
+ VerifierBackend->>VerifierBackend: Generate transaction_id\nand request_id
525
+ VerifierBackend-->>UserBrowser: Set HttpOnly Cookie (txn_id)
526
+ VerifierBackend-->>UserBrowser: Return OpenID4VP authorization request
527
+
528
+ UserBrowser->>WebWallet: Open Web Wallet
529
+
530
+ WebWallet->>VerifierBackend: Submit vp_token + presentation_submission
531
+ VerifierBackend-->>WebWallet: Return response_code
532
+
533
+ WebWallet-->>UserBrowser: Redirect to redirect_uri
534
+
535
+ UserBrowser->>UserBrowser: Extract response_code
536
+
537
+ UserBrowser->>VerifierBackend: GET /vp-session-results?response_code=xyz\n(Cookie txn_id automatically sent)
538
+
539
+ VerifierBackend->>VerifierBackend: Validate response_code + txn_id
540
+ VerifierBackend->>VerifierBackend: Fetch transaction state
541
+
542
+ VerifierBackend-->>UserBrowser: Verification result
543
+ VerifierBackend-->>UserBrowser: Clear cookie (txn_id)
544
+ ```
545
+
546
+ > **NOTE**
547
+ >
548
+ > When webWalletBaseUrl is configured, we use web-wallets to support verification flow.
549
+ >In the absence of webWalletBaseUrl, the SDK falls back to a deep link mechanism to launch the native wallet application if any supported mobile wallet is installed.
550
+
551
+
552
+ #### 4. Server-to-server callback (onVPReceived)
553
+ ```javascript
554
+ import { OpenID4VPVerification } from "@injistack/react-inji-verify-sdk";
555
+
556
+ export default function VerifyServerToServer() {
557
+ return (
558
+ <OpenID4VPVerification
559
+ triggerElement={<button>Start Verification</button>}
560
+ verifyServiceUrl="https://your-backend.com/v1/verify"
561
+ clientId="did:example:123456789" // DID example
562
+ presentationDefinition={{
563
+ id: "custom-verification",
564
+ purpose: "We need to verify your identity",
565
+ format: {
566
+ ldp_vc: {
567
+ proof_type: ["Ed25519Signature2020"],
568
+ },
569
+ },
570
+ input_descriptors: [
571
+ {
572
+ id: "id-card-check",
573
+ constraints: {
574
+ fields: [
575
+ {
576
+ path: ["$.type"],
577
+ filter: {
578
+ type: "object",
579
+ pattern: "DriverLicenseCredential",
580
+ },
581
+ },
582
+ ],
583
+ },
584
+ },
585
+ ],
586
+ }}
587
+ isSameDeviceFlowEnabled={false}
588
+ onVPReceived={(transactionId) => {
589
+ //using the transactionId one can securely fetch the result from service
590
+ console.log("VP received transactionId:", transactionId);
591
+ }}
592
+ onQrCodeExpired={() => {
593
+ console.log("QR code expired");
594
+ }}
595
+ onError={(error) => {
596
+ console.error("Verification error:", error);
597
+ }}
598
+ />
599
+ );
600
+ }
601
+ ```
602
+
603
+ ### Verification Response
604
+
605
+ Once VP Verification is complete, the response depends on the `summariseResults` attribute (default = true)
606
+
607
+ If `summariseResults = true`, the response will be:
608
+
609
+ ```javascript
610
+ {
611
+ "vcResults": [
612
+ {
613
+ "vc": { /* verified credential data */ },
614
+ "vcStatus": "SUCCESS" // or "INVALID", "EXPIRED","REVOKED"
615
+ }
616
+ ],
617
+ "vpResultStatus": "SUCCESS" // or "INVALID" Overall verification status
618
+ }
619
+ ```
620
+
621
+ If `summariseResults = false`, the response will be:
622
+
623
+ ```javascript
624
+ {
625
+ "transactionId": "txn_11",
626
+ "allChecksSuccessful": true,
627
+ "credentialResults": [
628
+ {
629
+ "verifiableCredential": "{...}",
630
+ "allChecksSuccessful": true,
631
+ "holderProofCheck": { "valid": true, "error": null },
632
+ "schemaAndSignatureCheck": { "valid": true, "error": null },
633
+ "expiryCheck": { "valid": true },
634
+ "statusChecks": [
635
+ { "purpose": "revocation", "valid": true, "error": null }
636
+ ],
637
+ "claims": {..}
638
+ }
639
+ ]
640
+ }
641
+ ```
642
+
643
+ #### Response Fields Summary
644
+
645
+ | Property | Type | Description |
646
+ |---------------------------|---------|-----------------------------------------------------------|
647
+ | `allChecksSuccessful` | boolean | Final aggregated validation flag |
648
+ | `verifiableCredential` | string | The VC which needs to be verified |
649
+ | `holderProofCheck` | object | Validates if presenter owns the credential |
650
+ | `schemaAndSignatureCheck` | object | Validates schema and signature check |
651
+ | `expiryCheck` | object | If false, the credential is EXPIRED |
652
+ | `statusChecks` | array | Contains revocation and other status validations |
653
+ | `statusChecks.error` | object | If present, throws an error instead of returning a status |
654
+ | `statusChecks.purpose` | string | Identifies purpose (e.g., "revocation") |
655
+ | `statusChecks.valid` | boolean | If false for revocation → credential is revoked |
656
+ | `claims` | object | Includes all claims from credentialSubject |
657
+
658
+ ### Presentation Definition:
659
+
185
660
  #### Define What to Verify:
186
661
 
187
- **Option 1: Use a predefined template**
662
+ **Option 1: Use a predefined template ID**
188
663
 
189
664
  ```javascript
190
665
  presentationDefinitionId = "drivers-license-check";
191
666
  ```
192
667
 
193
- **Option 2: Define exactly what you want**
668
+ **Option 2: Define Presentation Definition**
194
669
 
195
670
  ```javascript
196
671
  presentationDefinition={{
@@ -219,44 +694,53 @@ presentationDefinition={{
219
694
  ],
220
695
  }}
221
696
  ```
697
+ > **NOTE**
698
+ >
699
+ > Only one of presentationDefinitionId or presentationDefinition should be provided at a time.
700
+ > It is recommended to use:
701
+ >- presentationDefinitionId when leveraging predefined templates.
702
+ >- presentationDefinition when custom verification requirements are needed.
222
703
 
223
704
  ## 🎛️ Component Options Reference
224
705
 
225
706
  ### Common Props (Both Components)
226
707
 
227
708
  | Property | Type | Required | Description |
228
- | ---------------------------- | ------------- | -------- | ------------------------------------------- |
229
- | `verifyServiceUrl` | string | ✅ | Backend verification URL |
230
- | `onError` | function | ✅ | Callback invoked when an error occurs |
231
- | `triggerElement` | React element | ❌ | Custom button/element to start verification |
232
- | `transactionId` | string | ❌ | Optional client-side tracking ID |
233
- | `clientId` | string | ✅ | Client identifier |
234
- | `acceptVPWithoutHolderProof` | boolean | ❌ | Allow unsigned Verifiable Presentations |
709
+ |------------------------------|---------------| ----- |---------------------------------------------|
710
+ | `verifyServiceUrl` | string | ✅ | Backend verification URL |
711
+ | `onError` | function | ✅ | Callback invoked when an error occurs |
712
+ | `triggerElement` | React element | ❌ | Custom button/element to start verification |
713
+ | `transactionId` | string | ❌ | Optional client-side tracking ID |
714
+ | `clientId` | string | ✅ | Client identifier (DID or Non-DID) |
715
+ | `acceptVPWithoutHolderProof` | boolean | ❌ | Allow unsigned Verifiable Presentations |
716
+ | `summariseResults` | boolean | ❌ | Decides format of SDK Response |
235
717
 
236
718
  ### QRCodeVerification Specific
237
719
 
238
- | Property | Type | Default | Description |
239
- | ------------------------- | -------- | ------- | ---------------------------- |
240
- | `onVCProcessed` | function | - | Get full results immediately |
241
- | `onVCReceived` | function | - | Get transaction ID only |
242
- | `isEnableUpload` | boolean | true | Allow file uploads |
243
- | `isEnableScan` | boolean | true | Allow camera scanning |
244
- | `isEnableZoom` | boolean | true | Allow camera zoom |
245
- | `uploadButtonStyle` | object | - | Custom upload button styling |
246
- | `isVPSubmissionSupported` | Boolean | false | Toggle VP submission support |
720
+ | Property | Type | Default | Description |
721
+ |---------------------------|----------|---------|--------------------------------------------|
722
+ | `onVCProcessed` | function | - | Get full results immediately |
723
+ | `onVCReceived` | function | - | Get transaction ID only |
724
+ | `isEnableUpload` | boolean | true | Allow file uploads |
725
+ | `isEnableScan` | boolean | true | Allow camera scanning |
726
+ | `isEnableZoom` | boolean | true | Allow camera zoom (for mobile and tablets) |
727
+ | `uploadButtonStyle` | string | - | Custom upload button styling |
728
+ | `isVPSubmissionSupported` | boolean | false | Toggle VP submission support |
729
+ | `vcVerificationV2Request` | object | - | contains request body for VC Verification |
247
730
 
248
731
  ### OpenID4VPVerification Specific
249
732
 
250
- | Property | Type | Default | Description |
251
- | -------------------------- | -------- | -------------- | ---------------------------------- |
252
- | `protocol` | string | "openid4vp://" | Protocol for QR codes (optional) |
253
- | `presentationDefinitionId` | string | - | Predefined verification template |
254
- | `presentationDefinition` | object | - | Custom verification rules |
255
- | `onVpProcessed` | function | - | Get full results immediately |
256
- | `onVpReceived` | function | - | Get transaction ID only |
257
- | `onQrCodeExpired` | function | - | Handle QR code expiration |
258
- | `isSameDeviceFlowEnabled` | boolean | true | Enable same-device flow (optional) |
259
- | `qrCodeStyles` | object | - | Customize QR code appearance |
733
+ | Property | Type | Default | Description |
734
+ |--------------------------| -------- |----------------|-------------------------------------------|
735
+ | `protocol` | string | "openid4vp://" | Protocol for QR codes (optional) |
736
+ | `presentationDefinitionId` | string | - | Predefined verification template |
737
+ | `presentationDefinition` | object | - | Custom verification rules |
738
+ | `onVPProcessed` | function | - | Get full results immediately |
739
+ | `onVPReceived` | function | - | Get transaction ID only |
740
+ | `onQrCodeExpired` | function | - | Handle QR code expiration |
741
+ | `isSameDeviceFlowEnabled` | boolean | true | Enable same-device flow (optional) |
742
+ | `qrCodeStyles` | object | - | Customize QR code appearance |
743
+ | `vpVerificationRequest` | object | - | contains request body for VP Verification |
260
744
 
261
745
  ## ⚠️ Important Limitations
262
746