@richard.fadiora/liveness-detection 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -120
- package/dist/index.es.js +1487 -1483
- package/dist/index.umd.js +11 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,129 +2,104 @@
|
|
|
2
2
|
|
|
3
3
|
A React-based liveness detection component that performs randomized user challenges and verifies real-user presence via a backend anti-spoofing API.
|
|
4
4
|
|
|
5
|
-
This
|
|
5
|
+
This version introduces **headless mode**, **render-prop customization**, and robust **challenge sequencing**, **configurable thresholds** for `Smile`, `Blink`, and `Turn_Head` challenges
|
|
6
|
+
|
|
7
|
+
Pause between steps for user feedback
|
|
8
|
+
|
|
9
|
+
Sequential challenge execution with strict timeout handling allowing you to fully control the UI while keeping the verification logic encapsulated.
|
|
6
10
|
|
|
7
11
|
---
|
|
8
12
|
|
|
9
|
-
## Overview
|
|
13
|
+
## 📌 Overview
|
|
10
14
|
|
|
11
15
|
This component strengthens identity verification by combining:
|
|
12
16
|
|
|
13
|
-
- Randomized challenge-response validation
|
|
14
|
-
- Strict timeout enforcement
|
|
15
|
-
- Backend spoof detection
|
|
16
|
-
- Callback-based integration for easy usage
|
|
17
|
+
- Randomized challenge-response validation
|
|
18
|
+
- Strict timeout enforcement
|
|
19
|
+
- Backend spoof detection
|
|
20
|
+
- Callback-based integration for easy usage
|
|
17
21
|
- Headless / fully customizable UI via render props
|
|
22
|
+
- Configurable challenge thresholds to adapt difficulty
|
|
18
23
|
|
|
19
24
|
It protects against:
|
|
20
25
|
|
|
21
|
-
- Presentation (photo) attacks
|
|
22
|
-
- Screen glare attacks
|
|
23
|
-
- Video replay/injection attacks
|
|
26
|
+
- Presentation (photo) attacks
|
|
27
|
+
- Screen glare attacks
|
|
28
|
+
- Video replay/injection attacks
|
|
24
29
|
|
|
25
30
|
---
|
|
26
31
|
|
|
27
|
-
## How It Works
|
|
32
|
+
## ⚙️ How It Works
|
|
28
33
|
|
|
29
|
-
### Challenge Initialization
|
|
34
|
+
### 1️⃣ Challenge Initialization
|
|
30
35
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
- Each challenge is verified sequentially, with a brief pause between steps for
|
|
34
|
-
- The next challenge only begins after the current one is successfully completed.
|
|
36
|
+
- Randomly selects **3 challenges** from the pool: `Smile`, `Blink`, `Turn_Head`, `Thumbs_Up`.
|
|
37
|
+
- Timer starts immediately (default **60 seconds**, configurable via `duration`).
|
|
38
|
+
- Each challenge is verified sequentially, with a brief pause between steps for feedback.
|
|
35
39
|
- If the timer expires, the session terminates and no frames are sent to the backend.
|
|
36
40
|
|
|
37
|
-
### Challenge Execution
|
|
41
|
+
### 2️⃣ Challenge Execution
|
|
38
42
|
|
|
39
|
-
-
|
|
40
|
-
- Sequential verification ensures no steps are skipped
|
|
41
|
-
- Developers can
|
|
43
|
+
- Real-time validation using webcam input and MediaPipe models.
|
|
44
|
+
- Sequential verification ensures **no steps are skipped**.
|
|
45
|
+
- Developers can render custom UI via the **render prop** while using the same underlying logic.
|
|
46
|
+
- Challenge thresholds are configurable through props:
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
| Prop Name | Default | Description |
|
|
49
|
+
|-----------------------|---------|------------------------------------------|
|
|
50
|
+
| `smileThreshold` | 0.20 | Minimum smile width to count as valid |
|
|
51
|
+
| `blinkThreshold` | 0.01 | Maximum eye aspect ratio to count as blink |
|
|
52
|
+
| `minturnHeadThreshold`| 0.15 | Minimum yaw for right head turn detection |
|
|
53
|
+
| `maxturnHeadThreshold`| 0.85 | Maximum yaw for left head turn detection |
|
|
44
54
|
|
|
45
|
-
|
|
46
|
-
- Frames are sent to the backend API defined by the `apiUrl` prop.
|
|
47
|
-
- The backend performs:
|
|
48
|
-
- Spoof detection
|
|
49
|
-
- Glare detection
|
|
50
|
-
- Video injection detection
|
|
55
|
+
### 3️⃣ Backend Liveness Verification
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
- Captures **5 frames** from the webcam after all challenges are complete.
|
|
58
|
+
- Frames sent to backend API (`apiUrl` prop).
|
|
59
|
+
- Backend performs spoof detection, glare detection, and video injection detection.
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
### If verification succeeds
|
|
61
|
+
---
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
- The `onComplete` callback is triggered:
|
|
63
|
+
## ✅ Success & Failure Behavior
|
|
60
64
|
|
|
65
|
+
### Success
|
|
66
|
+
- UI (or custom component) shows success feedback.
|
|
67
|
+
- `onComplete` callback is triggered:
|
|
61
68
|
```js
|
|
62
69
|
onComplete({ success: true, image: frame, skinConfidence });
|
|
63
70
|
```
|
|
64
71
|
|
|
65
|
-
###
|
|
66
|
-
|
|
67
|
-
-
|
|
68
|
-
- The `onError` callback is triggered:
|
|
69
|
-
|
|
72
|
+
### Failure
|
|
73
|
+
- UI shows failure message.
|
|
74
|
+
- `onError` callback is triggered:
|
|
70
75
|
```js
|
|
71
76
|
onError({ success: false, reason, skinConfidence: null });
|
|
72
77
|
```
|
|
73
|
-
|
|
74
|
-
- The component resets, requiring the user to start a new session.
|
|
78
|
+
- Component resets; user must start a new session.
|
|
75
79
|
|
|
76
80
|
---
|
|
77
81
|
|
|
78
|
-
## Props
|
|
82
|
+
## 📦 Props
|
|
79
83
|
|
|
80
|
-
| Prop Name
|
|
81
|
-
|
|
82
|
-
| `apiUrl`
|
|
83
|
-
| `onComplete` | `(result:
|
|
84
|
-
| `onError`
|
|
85
|
-
| `duration` | `
|
|
86
|
-
| render`
|
|
87
|
-
| `classNames` | `object`
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
| Prop Name | Type | Required | Description |
|
|
85
|
+
|------------|-----------------------------|----------|-------------|
|
|
86
|
+
| `apiUrl` | `string` | Yes | Backend endpoint used for liveness verification |
|
|
87
|
+
| `onComplete` | `(result: object) => void` | Yes | Callback fired after verification succeeds |
|
|
88
|
+
| `onError` | `(result: object) => void` | Yes | Callback fired after verification fails |
|
|
89
|
+
| `duration` | `number` | No | Maximum time for all challenges (default: 60s) |
|
|
90
|
+
| `render` | `(sdk: object) => JSX.Element` | No | Optional render prop for full UI customization |
|
|
91
|
+
| `classNames` | `object` | No | Optional CSS class names to customize default UI |
|
|
92
|
+
| `smileThreshold` | `number` | No | Minimum smile width for Smile challenge |
|
|
93
|
+
| `blinkThreshold` | `number` | No | Maximum eye aspect ratio for Blink challenge |
|
|
94
|
+
| `minturnHeadThreshold` | `number` | No | Minimum yaw for Turn_Head challenge |
|
|
95
|
+
| `maxturnHeadThreshold` | `number` | No | Maximum yaw for Turn_Head challenge |
|
|
90
96
|
|
|
91
|
-
## Styling with `classNames`
|
|
92
|
-
|
|
93
|
-
The `classNames` object allows partial styling of the default UI without fully overriding it. Supported keys:
|
|
94
|
-
|
|
95
|
-
| Key | Element |
|
|
96
|
-
|------------|-----------------------------|
|
|
97
|
-
| `container` | The root wrapper div |
|
|
98
|
-
| `webcam` | The webcam video element |
|
|
99
|
-
| `button` | Start / Retry button |
|
|
100
|
-
| `timer` | Timer display |
|
|
101
|
-
| `error` | Error message display |
|
|
102
|
-
| `success` | Success message display |
|
|
103
|
-
|
|
104
|
-
### Example Usage
|
|
105
|
-
|
|
106
|
-
```jsx
|
|
107
|
-
<LivenessSDK
|
|
108
|
-
apiUrl="https://your-backend-api.com/liveness-check"
|
|
109
|
-
onComplete={handleComplete}
|
|
110
|
-
onError={handleError}
|
|
111
|
-
classNames={{
|
|
112
|
-
container: "my-liveness-container",
|
|
113
|
-
webcam: "my-webcam",
|
|
114
|
-
button: "my-button",
|
|
115
|
-
timer: "my-timer",
|
|
116
|
-
error: "my-error",
|
|
117
|
-
success: "my-success"
|
|
118
|
-
}}
|
|
119
|
-
/>
|
|
120
|
-
```
|
|
121
97
|
|
|
122
98
|
---
|
|
123
99
|
|
|
124
|
-
## Usage
|
|
100
|
+
## 🧩 Usage Example
|
|
125
101
|
|
|
126
102
|
### Default UI
|
|
127
|
-
|
|
128
103
|
```jsx
|
|
129
104
|
import { LivenessSDK } from "@richard.fadiora/liveness-detection";
|
|
130
105
|
|
|
@@ -132,8 +107,8 @@ function App() {
|
|
|
132
107
|
return (
|
|
133
108
|
<LivenessSDK
|
|
134
109
|
apiUrl="https://your-backend-api.com/liveness-check"
|
|
135
|
-
onComplete={(result) => console.log("
|
|
136
|
-
onError={(error) => console.log("
|
|
110
|
+
onComplete={(result) => console.log("Success:", result)}
|
|
111
|
+
onError={(error) => console.log("Failed:", error.reason)}
|
|
137
112
|
duration={60}
|
|
138
113
|
/>
|
|
139
114
|
);
|
|
@@ -143,7 +118,6 @@ export default App;
|
|
|
143
118
|
```
|
|
144
119
|
|
|
145
120
|
### Headless / Custom UI
|
|
146
|
-
|
|
147
121
|
```jsx
|
|
148
122
|
<LivenessSDK
|
|
149
123
|
apiUrl="https://your-backend-api.com/liveness-check"
|
|
@@ -162,61 +136,113 @@ export default App;
|
|
|
162
136
|
|
|
163
137
|
---
|
|
164
138
|
|
|
165
|
-
##
|
|
139
|
+
## 🎨 Styling with `classNames`
|
|
166
140
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
-
|
|
141
|
+
You can pass a `classNames` object to override the default UI classes:
|
|
142
|
+
```js
|
|
143
|
+
classNames={{
|
|
144
|
+
container: "liveness-container",
|
|
145
|
+
webcam: "liveness-webcam",
|
|
146
|
+
button: "liveness-button",
|
|
147
|
+
challenge: "liveness-challenge",
|
|
148
|
+
timer: "liveness-timer",
|
|
149
|
+
error: "liveness-error",
|
|
150
|
+
success: "liveness-success",
|
|
151
|
+
}}
|
|
152
|
+
```
|
|
173
153
|
|
|
174
|
-
|
|
154
|
+
### CSS Example
|
|
155
|
+
```css
|
|
156
|
+
.liveness-container {
|
|
157
|
+
text-align: center;
|
|
158
|
+
background: #121212;
|
|
159
|
+
padding: 24px;
|
|
160
|
+
border-radius: 20px;
|
|
161
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
|
162
|
+
color: white;
|
|
163
|
+
}
|
|
164
|
+
.liveness-webcam {
|
|
165
|
+
border-radius: 20px;
|
|
166
|
+
border: 2px solid #007bff;
|
|
167
|
+
width: 100%;
|
|
168
|
+
}
|
|
169
|
+
.liveness-button {
|
|
170
|
+
padding: 12px 30px;
|
|
171
|
+
font-size: 16px;
|
|
172
|
+
font-weight: bold;
|
|
173
|
+
border-radius: 10px;
|
|
174
|
+
background: #28a745;
|
|
175
|
+
color: white;
|
|
176
|
+
border: none;
|
|
177
|
+
cursor: pointer;
|
|
178
|
+
margin-top: 10px;
|
|
179
|
+
}
|
|
180
|
+
.liveness-challenge {
|
|
181
|
+
margin: 5px 0;
|
|
182
|
+
font-weight: bold;
|
|
183
|
+
font-size: 40px;
|
|
184
|
+
}
|
|
185
|
+
.liveness-timer {
|
|
186
|
+
margin: 10px 0;
|
|
187
|
+
font-weight: bold;
|
|
188
|
+
font-size: 18px;
|
|
189
|
+
}
|
|
190
|
+
.liveness-error {
|
|
191
|
+
color: #ff4d4d;
|
|
192
|
+
margin-top: 20px;
|
|
193
|
+
}
|
|
194
|
+
.liveness-success {
|
|
195
|
+
color: #4caf50;
|
|
196
|
+
margin-top: 20px;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
175
199
|
|
|
176
|
-
|
|
200
|
+
---
|
|
177
201
|
|
|
178
|
-
|
|
179
|
-
- **Server-side passive verification**: frame-based spoof analysis, glare detection, video injection detection
|
|
180
|
-
- **Strict session control**: timeout enforcement, restart requirement on failure
|
|
202
|
+
## ⏳ Timeout Rules
|
|
181
203
|
|
|
182
|
-
|
|
204
|
+
- Maximum session duration: set via `duration` prop (default 60s).
|
|
205
|
+
- On timeout: challenge stops, state resets, backend verification is not triggered.
|
|
183
206
|
|
|
184
207
|
---
|
|
185
208
|
|
|
186
|
-
##
|
|
209
|
+
## 🔐 Security Architecture
|
|
210
|
+
|
|
211
|
+
- **Client-side**: Randomized challenges, real-time gesture detection
|
|
212
|
+
- **Server-side**: Frame-based spoof analysis, glare detection, video injection detection
|
|
213
|
+
- **Session control**: Timeout enforcement, manual restart on failure
|
|
214
|
+
- Reduces false positives and prevents replay attacks.
|
|
215
|
+
|
|
216
|
+
---
|
|
187
217
|
|
|
188
|
-
|
|
218
|
+
## 📊 Verification Criteria
|
|
189
219
|
|
|
190
|
-
- All 3
|
|
191
|
-
- All 5 frames
|
|
192
|
-
- Backend confirms:
|
|
193
|
-
- No spoofing detected
|
|
194
|
-
- No glare detected
|
|
195
|
-
- Skin texture is human
|
|
196
|
-
- No video injection detected
|
|
220
|
+
- All 3 challenges completed
|
|
221
|
+
- All 5 frames successfully sent to backend
|
|
222
|
+
- Backend confirms: no spoofing, no glare, human skin texture, no video injection
|
|
197
223
|
|
|
198
224
|
---
|
|
199
225
|
|
|
200
|
-
## Integration Notes
|
|
226
|
+
## 🏗️ Integration Notes
|
|
201
227
|
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
-
|
|
205
|
-
-
|
|
228
|
+
- Webcam permissions required
|
|
229
|
+
- Backend must accept 5 frames in expected format
|
|
230
|
+
- `apiUrl` must be reachable and have an endpoint `/v1/verify`
|
|
231
|
+
- CORS must be configured properly
|
|
206
232
|
|
|
207
233
|
---
|
|
208
234
|
|
|
209
|
-
## Ideal Use Cases
|
|
235
|
+
## 🚀 Ideal Use Cases
|
|
210
236
|
|
|
211
|
-
- KYC verification flows
|
|
212
|
-
- Identity onboarding
|
|
213
|
-
- Account recovery
|
|
214
|
-
- Secure login
|
|
215
|
-
- Financial
|
|
237
|
+
- KYC verification flows
|
|
238
|
+
- Identity onboarding
|
|
239
|
+
- Account recovery
|
|
240
|
+
- Secure login
|
|
241
|
+
- Financial / compliance apps
|
|
216
242
|
|
|
217
243
|
---
|
|
218
244
|
|
|
219
|
-
## Maintainer
|
|
245
|
+
## 👨💻 Maintainer
|
|
220
246
|
|
|
221
|
-
Fadiora Richard
|
|
247
|
+
Fadiora Richard.
|
|
222
248
|
|