@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 +604 -120
- package/dist/components/openid4vp-verification/OpenID4VPVerification.types.d.ts +64 -10
- package/dist/components/qrcode-verification/QRCodeVerification.types.d.ts +36 -10
- package/dist/index.js +1 -1
- package/dist/utils/api.d.ts +10 -3
- package/dist/utils/constants.d.ts +0 -4
- package/dist/utils/utils.d.ts +5 -0
- package/package.json +2 -2
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
|
|
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
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
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
|
-
###
|
|
134
|
+
### Option A: QR Code Verification (Scan & Upload)
|
|
91
135
|
|
|
92
|
-
|
|
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
|
-
|
|
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
|
-
|
|
140
|
+
Follow these steps to integrate:
|
|
99
141
|
|
|
100
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
202
|
+
#### 2. Scanning a Verifiable Credential (VC) Using Device Camera
|
|
112
203
|
|
|
113
|
-
|
|
204
|
+
a. Client-side handling (onVCProcessed)
|
|
114
205
|
|
|
115
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
261
|
+
If `summariseResults = false`, the response will be:
|
|
150
262
|
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
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
|
-
|
|
293
|
+
Follow these steps to integrate:
|
|
294
|
+
|
|
295
|
+
#### Import & Usage
|
|
159
296
|
|
|
160
297
|
```javascript
|
|
161
|
-
|
|
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
|
-
####
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
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 | ✅
|
|
230
|
-
| `onError` | function | ✅
|
|
231
|
-
| `triggerElement` | React element | ❌
|
|
232
|
-
| `transactionId` | string | ❌
|
|
233
|
-
| `clientId` | string | ✅
|
|
234
|
-
| `acceptVPWithoutHolderProof` | boolean | ❌
|
|
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` |
|
|
246
|
-
| `isVPSubmissionSupported` |
|
|
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
|
|
251
|
-
|
|
252
|
-
| `protocol`
|
|
253
|
-
| `presentationDefinitionId` | string | - | Predefined verification template
|
|
254
|
-
| `presentationDefinition`
|
|
255
|
-
| `
|
|
256
|
-
| `
|
|
257
|
-
| `onQrCodeExpired`
|
|
258
|
-
| `isSameDeviceFlowEnabled`
|
|
259
|
-
| `qrCodeStyles`
|
|
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
|
|