@richard.fadiora/liveness-detection 4.3.7 → 4.3.8
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 +167 -232
- package/dist/angular/README.md +167 -232
- package/dist/index.cjs +1 -3
- package/dist/index.js +6 -643
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,294 +1,229 @@
|
|
|
1
1
|
# Liveness Detection SDK
|
|
2
2
|
|
|
3
|
-
A cross-framework **liveness detection SDK** that performs randomized user challenges and verifies real-user presence via a backend anti-spoofing API. Works with **React** and **Angular** via framework-specific wrappers while the **core engine is framework-agnostic**.
|
|
4
3
|
|
|
5
|
-
This version introduces:
|
|
6
4
|
|
|
7
|
-
- **
|
|
8
|
-
-
|
|
9
|
-
- **Configurable thresholds** for `Smile`, `Blink`, and `Turn_Head` challenges
|
|
10
|
-
- Sequential challenge execution with **strict timeout handling**
|
|
11
|
-
- Pause between steps for user feedback
|
|
12
|
-
- Cross-framework integration (React hook & Angular service)
|
|
5
|
+
A cross-framework **liveness detection SDK** that performs randomized user challenges and verifies real-user presence via a backend anti-spoofing API.
|
|
6
|
+
This package provides a **framework-agnostic core** with optimized wrappers for **React ⚛️** and **Angular 🅰️**.
|
|
13
7
|
|
|
14
|
-
|
|
8
|
+
* * *
|
|
9
|
+
|
|
10
|
+
## 🚀 Key Features in v4.3.8
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
* 📦 **Multi-Entry Support**: Dedicated subpaths for React and Angular to prevent framework leakage.
|
|
15
|
+
|
|
16
|
+
* 🎨 **Prop-Driven Styling**: Fully customizable UI using class name injection (Tailwind/Bootstrap friendly).
|
|
17
|
+
|
|
18
|
+
* 🧠 **Headless Mode**: Access core logic via hooks (React) or services (Angular) for 100% custom UI.
|
|
19
|
+
|
|
20
|
+
* 🅰️ **Standalone Angular Support**: Angular wrapper uses standalone components; no NgModules needed.
|
|
21
|
+
|
|
22
|
+
* 🔒 **Improved Security**: Enhanced challenge sequencing with strict timeout handling and backend frame verification.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
* * *
|
|
15
26
|
|
|
16
27
|
## 📌 Overview
|
|
17
28
|
|
|
29
|
+
|
|
30
|
+
|
|
18
31
|
This SDK strengthens identity verification by combining:
|
|
19
32
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
* 🎲 Randomized challenge-response validation
|
|
34
|
+
|
|
35
|
+
* 📋 Sequential challenge execution (Smile, Blink, Turn\_Head, Thumbs\_Up)
|
|
36
|
+
|
|
37
|
+
* 🧠 Real-time MediaPipe face & hand landmark detection
|
|
38
|
+
|
|
39
|
+
* 🛡️ Protection against presentation attacks (photo/video), glare, and replay attacks
|
|
40
|
+
|
|
27
41
|
|
|
28
|
-
|
|
42
|
+
* * *
|
|
29
43
|
|
|
30
|
-
|
|
31
|
-
- Screen glare attacks
|
|
32
|
-
- Video replay/injection attacks
|
|
44
|
+
## 📦 Installation & Imports
|
|
33
45
|
|
|
34
|
-
---
|
|
35
46
|
|
|
36
|
-
## ⚙️ Architecture
|
|
37
47
|
|
|
38
|
-
|
|
48
|
+
`npm install @richard.fadiora/liveness-detection`
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
- Handles:
|
|
42
|
-
- Challenge sequence generation
|
|
43
|
-
- MediaPipe face & hand model detection
|
|
44
|
-
- Challenge validation (`Smile`, `Blink`, `Turn_Head`, `Thumbs_Up`)
|
|
45
|
-
- Face cropping
|
|
46
|
-
- Detection loop
|
|
47
|
-
- Final frame capture and backend verification
|
|
48
|
-
- Can be used directly or via React/Angular wrappers
|
|
50
|
+
### Import Paths
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
#
|
|
51
53
|
|
|
52
|
-
|
|
|
53
|
-
|
|
54
|
-
|
|
|
55
|
-
|
|
|
54
|
+
| Target | Import Path |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| Pure Logic (Core) | @richard.fadiora/liveness-detection |
|
|
57
|
+
| React Wrapper ⚛️ | @richard.fadiora/liveness-detection/react |
|
|
58
|
+
| Angular Wrapper 🅰️ | @richard.fadiora/liveness-detection/angular |
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
These entry points ensure framework-specific code stays isolated and bundles remain small.
|
|
58
61
|
|
|
59
|
-
|
|
62
|
+
* * *
|
|
60
63
|
|
|
61
|
-
|
|
64
|
+
## 🧩 Framework Usage
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
- Timer starts immediately (default **60 seconds**, configurable via `duration`).
|
|
65
|
-
- Each challenge is verified sequentially, with a brief pause between steps for feedback.
|
|
66
|
-
- If the timer expires, the session terminates and no frames are sent to the backend.
|
|
66
|
+
### 🅰️ Angular Implementation (Standalone)
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
#
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
- Sequential verification ensures **no steps are skipped**.
|
|
72
|
-
- Developers can render custom UI via the **render prop** while using the same underlying logic.
|
|
73
|
-
- Challenge thresholds are configurable through props:
|
|
70
|
+
The Angular wrapper is now **standalone**. Import it directly into your component’s `imports` array without using a module:
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
72
|
+
import { Component } from '@angular/core';
|
|
73
|
+
import { LivenessComponent } from '@richard.fadiora/liveness-detection/angular';
|
|
74
|
+
|
|
75
|
+
@Component({
|
|
76
|
+
selector: 'app-verify',
|
|
77
|
+
standalone: true,
|
|
78
|
+
imports: \[LivenessComponent\],
|
|
79
|
+
template: \`
|
|
80
|
+
<LivenessCheck
|
|
81
|
+
\[apiUrl\]="'https://api.yoursite.com/verify'"
|
|
82
|
+
\[containerClass\]="'my-custom-container'"
|
|
83
|
+
\[buttonClass\]="'btn-primary'"
|
|
84
|
+
(onComplete)="handleSuccess($event)"
|
|
85
|
+
(onError)="handleError($event)">
|
|
86
|
+
</LivenessCheck>
|
|
87
|
+
\`
|
|
88
|
+
})
|
|
89
|
+
export class VerifyComponent {
|
|
90
|
+
|
|
91
|
+
handleSuccess(result: any) {
|
|
92
|
+
console.log("Image Captured:", result.image);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
handleError(error: any) {
|
|
96
|
+
console.error(error.reason);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
}
|
|
81
100
|
|
|
82
|
-
|
|
101
|
+
⚠️ **Important Rule:** Standalone components **must not** be declared in an NgModule. Doing so disables standalone behavior and can cause runtime errors.
|
|
83
102
|
|
|
84
|
-
|
|
85
|
-
- Frames sent to backend API (`apiUrl` prop).
|
|
86
|
-
- Backend performs spoof detection, glare detection, and video injection detection.
|
|
103
|
+
* * *
|
|
87
104
|
|
|
88
|
-
|
|
105
|
+
### ⚛️ React Implementation
|
|
89
106
|
|
|
90
|
-
|
|
107
|
+
#
|
|
91
108
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
109
|
+
import { LivenessSDK } from "@richard.fadiora/liveness-detection/react";
|
|
110
|
+
|
|
111
|
+
function App() {
|
|
112
|
+
return (
|
|
113
|
+
<LivenessSDK
|
|
114
|
+
apiUrl\="https://api.yoursite.com/verify"
|
|
115
|
+
classNames\={{ container: "p-4 bg-dark", video: "rounded-lg" }}
|
|
116
|
+
onComplete\={(res) => console.log("Success:", res.image)}
|
|
117
|
+
onError\={(err) => console.error(err.reason)}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
98
121
|
|
|
99
|
-
|
|
100
|
-
- UI shows failure message.
|
|
101
|
-
- `onError` callback is triggered:
|
|
102
|
-
```js
|
|
103
|
-
onError({ success: false, reason, skinConfidence: null });
|
|
104
|
-
```
|
|
105
|
-
- Component resets; user must start a new session.
|
|
122
|
+
* * *
|
|
106
123
|
|
|
107
|
-
|
|
124
|
+
## 🎨 Prop-Driven Styling
|
|
108
125
|
|
|
109
|
-
## 📦 Props
|
|
110
126
|
|
|
111
|
-
| Prop Name | Type | Required | Description |
|
|
112
|
-
|------------|-----------------------------|----------|-------------|
|
|
113
|
-
| `apiUrl` | `string` | Yes | Backend endpoint used for liveness verification |
|
|
114
|
-
| `onComplete` | `(result: object) => void` | Yes | Callback fired after verification succeeds |
|
|
115
|
-
| `onError` | `(result: object) => void` | Yes | Callback fired after verification fails |
|
|
116
|
-
| `duration` | `number` | No | Maximum time for all challenges (default: 60s) |
|
|
117
|
-
| `render` | `(sdk: object) => JSX.Element` | No | Optional render prop for full UI customization |
|
|
118
|
-
| `classNames` | `object` | No | Optional CSS class names to customize default UI |
|
|
119
|
-
| `smileThreshold` | `number` | No | Minimum smile width for Smile challenge |
|
|
120
|
-
| `blinkThreshold` | `number` | No | Maximum eye aspect ratio for Blink challenge |
|
|
121
|
-
| `minturnHeadThreshold` | `number` | No | Minimum yaw for Turn_Head challenge |
|
|
122
|
-
| `maxturnHeadThreshold` | `number` | No | Maximum yaw for Turn_Head challenge |
|
|
123
127
|
|
|
128
|
+
| Angular Input | React Prop | Description |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| containerClass | classNames.container | Main wrapper div |
|
|
131
|
+
| videoClass | classNames.webcam | The video element |
|
|
132
|
+
| buttonClass | classNames.button | The Start button |
|
|
133
|
+
| timerClass | classNames.timer | Countdown timer text |
|
|
134
|
+
| instructionBoxClass | classNames.challenge | Challenge instruction box |
|
|
135
|
+
| statusOverlayClass | classNames.overlay | Overlay during verification |
|
|
136
|
+
| errorMessageClass | classNames.error | Wrapper for error messages |
|
|
124
137
|
|
|
125
|
-
|
|
138
|
+
* * *
|
|
126
139
|
|
|
127
|
-
##
|
|
140
|
+
## ⚙️ Configuration & Thresholds
|
|
128
141
|
|
|
129
|
-
### Default UI
|
|
130
|
-
```jsx
|
|
131
|
-
import { LivenessSDK } from "@richard.fadiora/liveness-detection";
|
|
132
142
|
|
|
133
|
-
function App() {
|
|
134
|
-
return (
|
|
135
|
-
<LivenessSDK
|
|
136
|
-
apiUrl="https://your-backend-api.com/liveness-check"
|
|
137
|
-
onComplete={(result) => console.log("Success:", result)}
|
|
138
|
-
onError={(error) => console.log("Failed:", error.reason)}
|
|
139
|
-
duration={60}
|
|
140
|
-
/>
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
The `useLiveness` hook exposes the following values and control functions for managing the liveness detection session.
|
|
166
|
-
|
|
167
|
-
| Name | Type | Description |
|
|
168
|
-
|-----|------|-------------|
|
|
169
|
-
| `webcamRef` | `ref` | React ref attached to the webcam component. Provides access to the live video stream used for face and hand detection as well as frame capture for verification. |
|
|
170
|
-
| `status` | `string` | Represents the current state of the liveness session. Possible values include `loading`, `ready`, `capturing`, `verifying`, `success`, `error`, and `expired`. |
|
|
171
|
-
| `errorMsg` | `string` | Contains the error message displayed when the liveness verification fails or when the system encounters an issue. |
|
|
172
|
-
| `sequence` | `string[]` | The randomized sequence of liveness challenges selected for the current session. Three challenges are chosen from the challenge pool. |
|
|
173
|
-
| `currentStep` | `number` | The index of the current challenge being performed within the challenge sequence. |
|
|
174
|
-
| `timeLeft` | `number` | Remaining time (in seconds) before the session expires. The timer runs while the system is in the `capturing` state. |
|
|
175
|
-
| `isStepTransitioning` | `boolean` | Indicates whether the system is currently transitioning between challenges. Used to briefly pause detection and provide UI feedback after a challenge is completed. |
|
|
176
|
-
| `start` | `function` | Starts the liveness challenge session and begins the detection loop. |
|
|
177
|
-
| `reset` | `function` | Resets the entire session, including the timer, challenge sequence, step index, and error state. |
|
|
178
|
-
| `sendFinalProof` | `function` | Sends captured face frames to the backend verification API to perform the final liveness check. Normally triggered automatically after the last challenge is completed. |
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## 🎨 Styling with `classNames`
|
|
186
|
-
|
|
187
|
-
You can pass a `classNames` object to override the default UI classes:
|
|
188
|
-
```js
|
|
189
|
-
classNames={{
|
|
190
|
-
container: "liveness-container",
|
|
191
|
-
webcam: "liveness-webcam",
|
|
192
|
-
button: "liveness-button",
|
|
193
|
-
challenge: "liveness-challenge",
|
|
194
|
-
timer: "liveness-timer",
|
|
195
|
-
error: "liveness-error",
|
|
196
|
-
success: "liveness-success",
|
|
197
|
-
}}
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### CSS Example
|
|
201
|
-
```css
|
|
202
|
-
.liveness-container {
|
|
203
|
-
text-align: center;
|
|
204
|
-
background: #121212;
|
|
205
|
-
padding: 24px;
|
|
206
|
-
border-radius: 20px;
|
|
207
|
-
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
|
208
|
-
color: white;
|
|
209
|
-
}
|
|
210
|
-
.liveness-webcam {
|
|
211
|
-
border-radius: 20px;
|
|
212
|
-
border: 2px solid #007bff;
|
|
213
|
-
width: 100%;
|
|
214
|
-
}
|
|
215
|
-
.liveness-button {
|
|
216
|
-
padding: 12px 30px;
|
|
217
|
-
font-size: 16px;
|
|
218
|
-
font-weight: bold;
|
|
219
|
-
border-radius: 10px;
|
|
220
|
-
background: #28a745;
|
|
221
|
-
color: white;
|
|
222
|
-
border: none;
|
|
223
|
-
cursor: pointer;
|
|
224
|
-
margin-top: 10px;
|
|
225
|
-
}
|
|
226
|
-
.liveness-challenge {
|
|
227
|
-
margin: 5px 0;
|
|
228
|
-
font-weight: bold;
|
|
229
|
-
font-size: 40px;
|
|
230
|
-
}
|
|
231
|
-
.liveness-timer {
|
|
232
|
-
margin: 10px 0;
|
|
233
|
-
font-weight: bold;
|
|
234
|
-
font-size: 18px;
|
|
235
|
-
}
|
|
236
|
-
.liveness-error {
|
|
237
|
-
color: #ff4d4d;
|
|
238
|
-
margin-top: 20px;
|
|
144
|
+
| Prop Name | Default | Description |
|
|
145
|
+
| --- | --- | --- |
|
|
146
|
+
| duration | 60 | Total session time in seconds |
|
|
147
|
+
| smileThreshold | 0.20 | Minimum width for smile detection |
|
|
148
|
+
| blinkThreshold | 0.01 | Sensitivity for eye-closure detection |
|
|
149
|
+
| minturnHeadThreshold | 0.15 | Minimum yaw for right-turn detection |
|
|
150
|
+
| maxturnHeadThreshold | 0.85 | Maximum yaw for left-turn detection |
|
|
151
|
+
|
|
152
|
+
* * *
|
|
153
|
+
|
|
154
|
+
## ✅ Success & Failure Payload
|
|
155
|
+
|
|
156
|
+
### onComplete Result
|
|
157
|
+
|
|
158
|
+
#
|
|
159
|
+
|
|
160
|
+
{
|
|
161
|
+
success: true,
|
|
162
|
+
image: string, // Base64 encoded capture frame
|
|
163
|
+
skinConfidence: number // AI model confidence score
|
|
239
164
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
165
|
+
|
|
166
|
+
### onError Result
|
|
167
|
+
|
|
168
|
+
#
|
|
169
|
+
|
|
170
|
+
{
|
|
171
|
+
success: false,
|
|
172
|
+
reason: string, // "timeout", "challenge\_failed", "camera\_denied"
|
|
243
173
|
}
|
|
244
|
-
```
|
|
245
174
|
|
|
246
|
-
|
|
175
|
+
* * *
|
|
247
176
|
|
|
248
|
-
##
|
|
177
|
+
## 🛠️ Advanced: Headless Mode
|
|
249
178
|
|
|
250
|
-
- Maximum session duration: set via `duration` prop (default 60s).
|
|
251
|
-
- On timeout: challenge stops, state resets, backend verification is not triggered.
|
|
252
179
|
|
|
253
|
-
---
|
|
254
180
|
|
|
255
|
-
|
|
181
|
+
* **Angular 🅰️**: Inject `LivenessService` to access the `state$` observable.
|
|
182
|
+
|
|
183
|
+
* **React ⚛️**: Use `useLiveness` hook.
|
|
184
|
+
|
|
256
185
|
|
|
257
|
-
|
|
258
|
-
- **Server-side**: Frame-based spoof analysis, glare detection, video injection detection
|
|
259
|
-
- **Session control**: Timeout enforcement, manual restart on failure
|
|
260
|
-
- Reduces false positives and prevents replay attacks.
|
|
186
|
+
Allows full custom UI while using the detection engine.
|
|
261
187
|
|
|
262
|
-
|
|
188
|
+
* * *
|
|
263
189
|
|
|
264
|
-
##
|
|
190
|
+
## 🏗️ SDK Architecture
|
|
265
191
|
|
|
266
|
-
- All 3 challenges completed
|
|
267
|
-
- All 5 frames successfully sent to backend
|
|
268
|
-
- Backend confirms: no spoofing, no glare, human skin texture, no video injection
|
|
269
192
|
|
|
270
|
-
---
|
|
271
193
|
|
|
272
|
-
|
|
194
|
+
Layered design allows the same core detection engine to support multiple frameworks:
|
|
273
195
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
196
|
+
* **core**: `LivenessEngine.ts` handles webcam, landmark detection, challenge sequencing, frame capture, and backend verification
|
|
197
|
+
|
|
198
|
+
* **react**: React components + hooks handle UI and state
|
|
199
|
+
|
|
200
|
+
* **angular**: Standalone components + services handle UI and state
|
|
201
|
+
|
|
278
202
|
|
|
279
|
-
|
|
203
|
+
* * *
|
|
280
204
|
|
|
281
|
-
##
|
|
205
|
+
## 🔧 Integration Notes
|
|
282
206
|
|
|
283
|
-
- KYC verification flows
|
|
284
|
-
- Identity onboarding
|
|
285
|
-
- Account recovery
|
|
286
|
-
- Secure login
|
|
287
|
-
- Financial / compliance apps
|
|
288
207
|
|
|
289
|
-
|
|
208
|
+
|
|
209
|
+
* **MediaPipe Dependency**: If you see `TS2307: Cannot find module '@mediapipe/tasks-vision'`, run `npm install @mediapipe/tasks-vision`.
|
|
210
|
+
|
|
211
|
+
* **Angular Button Logic**: `[disabled]="!canStart"` — Angular inverts the boolean so button is enabled when `canStart = true`.
|
|
212
|
+
|
|
213
|
+
* **Webcam Permissions**: Required.
|
|
214
|
+
|
|
215
|
+
* **Timeout Rules**: Session resets if challenges aren’t completed within the configured duration.
|
|
216
|
+
|
|
217
|
+
* **Backend**: Accepts multiple frames for final spoof analysis. Endpoint must be `/v1/verify`
|
|
218
|
+
|
|
219
|
+
* **CORS**: Ensure API allows requests from your frontend domain.
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
* * *
|
|
290
223
|
|
|
291
224
|
## 👨💻 Maintainer
|
|
292
225
|
|
|
293
|
-
Fadiora Richard.
|
|
294
226
|
|
|
227
|
+
|
|
228
|
+
**Fadiora Richard**
|
|
229
|
+
Maintained by **Princeps Credit Systems Limited**
|