@richard.fadiora/liveness-detection 3.0.1 → 3.0.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 +124 -122
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,129 +2,86 @@
|
|
|
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**, allowing you to fully control the UI while keeping the verification logic encapsulated.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
## Overview
|
|
9
|
+
## 📌 Overview
|
|
10
10
|
|
|
11
11
|
This component strengthens identity verification by combining:
|
|
12
12
|
|
|
13
|
-
- Randomized challenge-response validation
|
|
14
|
-
- Strict timeout enforcement
|
|
15
|
-
- Backend spoof detection
|
|
16
|
-
- Callback-based integration for easy usage
|
|
17
|
-
- Headless / fully customizable UI via render props
|
|
13
|
+
- Randomized challenge-response validation
|
|
14
|
+
- Strict timeout enforcement
|
|
15
|
+
- Backend spoof detection
|
|
16
|
+
- Callback-based integration for easy usage
|
|
17
|
+
- Headless / fully customizable UI via render props
|
|
18
18
|
|
|
19
19
|
It protects against:
|
|
20
20
|
|
|
21
|
-
- Presentation (photo) attacks
|
|
22
|
-
- Screen glare attacks
|
|
23
|
-
- Video replay/injection attacks
|
|
21
|
+
- Presentation (photo) attacks
|
|
22
|
+
- Screen glare attacks
|
|
23
|
+
- Video replay/injection attacks
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
27
|
-
## How It Works
|
|
27
|
+
## ⚙️ How It Works
|
|
28
28
|
|
|
29
|
-
### Challenge Initialization
|
|
29
|
+
### 1️⃣ Challenge Initialization
|
|
30
30
|
|
|
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.
|
|
31
|
+
- Randomly selects **3 challenges** from the pool: `Smile`, `Blink`, `Turn_Head`, `Thumbs_Up`.
|
|
32
|
+
- Timer starts immediately (default **60 seconds**, configurable via `duration`).
|
|
33
|
+
- Each challenge is verified sequentially, with a brief pause between steps for feedback.
|
|
35
34
|
- If the timer expires, the session terminates and no frames are sent to the backend.
|
|
36
35
|
|
|
37
|
-
### Challenge Execution
|
|
36
|
+
### 2️⃣ Challenge Execution
|
|
38
37
|
|
|
39
|
-
-
|
|
40
|
-
- Sequential verification ensures no steps are skipped
|
|
41
|
-
- Developers can
|
|
38
|
+
- Real-time validation using webcam input and MediaPipe models.
|
|
39
|
+
- Sequential verification ensures **no steps are skipped**.
|
|
40
|
+
- Developers can render custom UI via the **render prop** while using the same underlying logic.
|
|
42
41
|
|
|
43
|
-
### Backend Liveness Verification
|
|
42
|
+
### 3️⃣ Backend Liveness Verification
|
|
44
43
|
|
|
45
|
-
-
|
|
46
|
-
- Frames
|
|
47
|
-
-
|
|
48
|
-
- Spoof detection
|
|
49
|
-
- Glare detection
|
|
50
|
-
- Video injection detection
|
|
44
|
+
- Captures **5 frames** from the webcam after all challenges are complete.
|
|
45
|
+
- Frames sent to backend API (`apiUrl` prop).
|
|
46
|
+
- Backend performs spoof detection, glare detection, and video injection detection.
|
|
51
47
|
|
|
52
48
|
---
|
|
53
49
|
|
|
54
|
-
## Success & Failure Behavior
|
|
55
|
-
|
|
56
|
-
### If verification succeeds
|
|
57
|
-
|
|
58
|
-
- The UI (or custom render-prop component) can display success feedback.
|
|
59
|
-
- The `onComplete` callback is triggered:
|
|
50
|
+
## ✅ Success & Failure Behavior
|
|
60
51
|
|
|
52
|
+
### Success
|
|
53
|
+
- UI (or custom component) shows success feedback.
|
|
54
|
+
- `onComplete` callback is triggered:
|
|
61
55
|
```js
|
|
62
56
|
onComplete({ success: true, image: frame, skinConfidence });
|
|
63
57
|
```
|
|
64
58
|
|
|
65
|
-
###
|
|
66
|
-
|
|
67
|
-
-
|
|
68
|
-
- The `onError` callback is triggered:
|
|
69
|
-
|
|
59
|
+
### Failure
|
|
60
|
+
- UI shows failure message.
|
|
61
|
+
- `onError` callback is triggered:
|
|
70
62
|
```js
|
|
71
63
|
onError({ success: false, reason, skinConfidence: null });
|
|
72
64
|
```
|
|
73
|
-
|
|
74
|
-
- The component resets, requiring the user to start a new session.
|
|
65
|
+
- Component resets; user must start a new session.
|
|
75
66
|
|
|
76
67
|
---
|
|
77
68
|
|
|
78
|
-
## Props
|
|
69
|
+
## 📦 Props
|
|
79
70
|
|
|
80
|
-
| Prop Name
|
|
81
|
-
|
|
82
|
-
| `apiUrl`
|
|
83
|
-
| `onComplete` | `(result:
|
|
84
|
-
| `onError`
|
|
85
|
-
| `duration` | `
|
|
86
|
-
| render`
|
|
87
|
-
| `classNames` | `object`
|
|
71
|
+
| Prop Name | Type | Required | Description |
|
|
72
|
+
|------------|-----------------------------|----------|-------------|
|
|
73
|
+
| `apiUrl` | `string` | Yes | Backend endpoint used for liveness verification |
|
|
74
|
+
| `onComplete` | `(result: object) => void` | Yes | Callback fired after verification succeeds |
|
|
75
|
+
| `onError` | `(result: object) => void` | Yes | Callback fired after verification fails |
|
|
76
|
+
| `duration` | `number` | No | Maximum time for all challenges (default: 60s) |
|
|
77
|
+
| `render` | `(sdk: object) => JSX.Element` | No | Optional render prop for full UI customization |
|
|
78
|
+
| `classNames` | `object` | No | Optional CSS class names to customize default UI |
|
|
88
79
|
|
|
89
80
|
---
|
|
90
81
|
|
|
91
|
-
##
|
|
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
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
## Usage Examples
|
|
82
|
+
## 🧩 Usage Example
|
|
125
83
|
|
|
126
84
|
### Default UI
|
|
127
|
-
|
|
128
85
|
```jsx
|
|
129
86
|
import { LivenessSDK } from "@richard.fadiora/liveness-detection";
|
|
130
87
|
|
|
@@ -132,8 +89,8 @@ function App() {
|
|
|
132
89
|
return (
|
|
133
90
|
<LivenessSDK
|
|
134
91
|
apiUrl="https://your-backend-api.com/liveness-check"
|
|
135
|
-
onComplete={(result) => console.log("
|
|
136
|
-
onError={(error) => console.log("
|
|
92
|
+
onComplete={(result) => console.log("Success:", result)}
|
|
93
|
+
onError={(error) => console.log("Failed:", error.reason)}
|
|
137
94
|
duration={60}
|
|
138
95
|
/>
|
|
139
96
|
);
|
|
@@ -143,7 +100,6 @@ export default App;
|
|
|
143
100
|
```
|
|
144
101
|
|
|
145
102
|
### Headless / Custom UI
|
|
146
|
-
|
|
147
103
|
```jsx
|
|
148
104
|
<LivenessSDK
|
|
149
105
|
apiUrl="https://your-backend-api.com/liveness-check"
|
|
@@ -162,61 +118,107 @@ export default App;
|
|
|
162
118
|
|
|
163
119
|
---
|
|
164
120
|
|
|
165
|
-
##
|
|
121
|
+
## 🎨 Styling with `classNames`
|
|
166
122
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
-
|
|
123
|
+
You can pass a `classNames` object to override the default UI classes:
|
|
124
|
+
```js
|
|
125
|
+
classNames={{
|
|
126
|
+
container: "liveness-container",
|
|
127
|
+
webcam: "liveness-webcam",
|
|
128
|
+
button: "liveness-button",
|
|
129
|
+
timer: "liveness-timer",
|
|
130
|
+
error: "liveness-error",
|
|
131
|
+
success: "liveness-success",
|
|
132
|
+
}}
|
|
133
|
+
```
|
|
173
134
|
|
|
174
|
-
|
|
135
|
+
### CSS Example
|
|
136
|
+
```css
|
|
137
|
+
.liveness-container {
|
|
138
|
+
text-align: center;
|
|
139
|
+
background: #121212;
|
|
140
|
+
padding: 24px;
|
|
141
|
+
border-radius: 20px;
|
|
142
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
|
143
|
+
color: white;
|
|
144
|
+
}
|
|
145
|
+
.liveness-webcam {
|
|
146
|
+
border-radius: 20px;
|
|
147
|
+
border: 2px solid #007bff;
|
|
148
|
+
width: 100%;
|
|
149
|
+
}
|
|
150
|
+
.liveness-button {
|
|
151
|
+
padding: 12px 30px;
|
|
152
|
+
font-size: 16px;
|
|
153
|
+
font-weight: bold;
|
|
154
|
+
border-radius: 10px;
|
|
155
|
+
background: #28a745;
|
|
156
|
+
color: white;
|
|
157
|
+
border: none;
|
|
158
|
+
cursor: pointer;
|
|
159
|
+
margin-top: 10px;
|
|
160
|
+
}
|
|
161
|
+
.liveness-timer {
|
|
162
|
+
margin: 10px 0;
|
|
163
|
+
font-weight: bold;
|
|
164
|
+
font-size: 18px;
|
|
165
|
+
}
|
|
166
|
+
.liveness-error {
|
|
167
|
+
color: #ff4d4d;
|
|
168
|
+
margin-top: 20px;
|
|
169
|
+
}
|
|
170
|
+
.liveness-success {
|
|
171
|
+
color: #4caf50;
|
|
172
|
+
margin-top: 20px;
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
---
|
|
177
177
|
|
|
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
|
|
178
|
+
## ⏳ Timeout Rules
|
|
181
179
|
|
|
182
|
-
|
|
180
|
+
- Maximum session duration: set via `duration` prop (default 60s).
|
|
181
|
+
- On timeout: challenge stops, state resets, backend verification is not triggered.
|
|
183
182
|
|
|
184
183
|
---
|
|
185
184
|
|
|
186
|
-
##
|
|
185
|
+
## 🔐 Security Architecture
|
|
186
|
+
|
|
187
|
+
- **Client-side**: Randomized challenges, real-time gesture detection
|
|
188
|
+
- **Server-side**: Frame-based spoof analysis, glare detection, video injection detection
|
|
189
|
+
- **Session control**: Timeout enforcement, manual restart on failure
|
|
190
|
+
- Reduces false positives and prevents replay attacks.
|
|
191
|
+
|
|
192
|
+
---
|
|
187
193
|
|
|
188
|
-
|
|
194
|
+
## 📊 Verification Criteria
|
|
189
195
|
|
|
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
|
|
196
|
+
- All 3 challenges completed
|
|
197
|
+
- All 5 frames successfully sent to backend
|
|
198
|
+
- Backend confirms: no spoofing, no glare, human skin texture, no video injection
|
|
197
199
|
|
|
198
200
|
---
|
|
199
201
|
|
|
200
|
-
## Integration Notes
|
|
202
|
+
## 🏗️ Integration Notes
|
|
201
203
|
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
-
|
|
205
|
-
-
|
|
204
|
+
- Webcam permissions required
|
|
205
|
+
- Backend must accept 5 frames in expected format
|
|
206
|
+
- `apiUrl` must be reachable and have an endpoint `v1/verify`
|
|
207
|
+
- CORS must be configured properly
|
|
206
208
|
|
|
207
209
|
---
|
|
208
210
|
|
|
209
|
-
## Ideal Use Cases
|
|
211
|
+
## 🚀 Ideal Use Cases
|
|
210
212
|
|
|
211
|
-
- KYC verification flows
|
|
212
|
-
- Identity onboarding
|
|
213
|
-
- Account recovery
|
|
214
|
-
- Secure login
|
|
215
|
-
- Financial
|
|
213
|
+
- KYC verification flows
|
|
214
|
+
- Identity onboarding
|
|
215
|
+
- Account recovery
|
|
216
|
+
- Secure login
|
|
217
|
+
- Financial / compliance apps
|
|
216
218
|
|
|
217
219
|
---
|
|
218
220
|
|
|
219
|
-
## Maintainer
|
|
221
|
+
## 👨💻 Maintainer
|
|
220
222
|
|
|
221
|
-
Fadiora Richard
|
|
223
|
+
Fadiora Richard.
|
|
222
224
|
|