Enterprise Authentication
Repeated biometric authentication with enrollment templates for enterprise workforce management.
Enterprise Authentication is available for organizations with an active Enterprise plan. Contact Owl Eyes Team to enable authentication features for your organization.
Key Features
Multi-Capture Enrollment
Collect 3-5 face images for robust template creation with real-time quality feedback.
Fast Authentication
Single-capture face recognition with sub-2-second response times for seamless access.
Multi-Modal Biometrics
Optional voice authentication for enhanced security with face + voice fusion.
JavaScript SDK (Web)
Installation
npm install @owl-eyes/web-sdk // Or via CDN <script src="https://sdk.owl-eyes.com/v2/owl-eyes.js"></script>
OwlEyes.enroll() Method
Initiates the multi-capture enrollment flow for face and voice biometrics.
import OwlEyes from '@owl-eyes/web-sdk';
const owl = new OwlEyes({
clientId: 'YOUR_CLIENT_ID',
environment: 'production',
});
// POST /v1/enrollments
const enrollmentResult = await owl.enroll({
organizationId: 'org_abc123',
employeeId: 'emp_john_doe',
options: {
requireVoice: true, // Enable voice enrollment
minFaceCaptures: 3, // Minimum photos required
maxFaceCaptures: 5, // Maximum photos allowed
minVoiceSamples: 3, // Voice samples if required
maxVoiceSamples: 5,
showQualityFeedback: true, // Real-time quality guidance
allowRetry: true, // Allow retry per capture
},
metadata: {
department: 'Engineering',
location: 'NYC Office',
accessLevel: 'high',
},
// Callbacks
onCaptureStart: (type) => {
console.log(`Starting ${type} capture...`); // 'face' or 'voice'
},
onCaptureProgress: (progress) => {
// { type: 'face', current: 2, total: 5, quality: 87 }
updateProgressUI(progress);
},
onQualityFeedback: (feedback) => {
// { passed: false, issues: ['too_dark', 'blurry'], guidance: '...' }
showQualityGuidance(feedback);
},
onComplete: (result) => {
if (result.success) {
console.log('Enrollment complete!', result.data);
}
},
onError: (error) => {
console.error('Enrollment failed:', error.code, error.message);
},
});OwlEyes.authenticate() Method
Performs fast, single-capture authentication against enrolled templates.
// POST /v1/authenticate
const authResult = await owl.authenticate({
organizationId: 'org_abc123',
employeeId: 'emp_john_doe', // Employee claiming identity
options: {
requireVoice: false, // Face-only for speed
livenessMode: 'passive', // 'passive' | 'active' | 'both'
captureTimeout: 30, // Seconds
},
deviceContext: {
// Optional: helps detect fraud patterns
deviceId: getDeviceFingerprint(),
platform: 'web',
userAgent: navigator.userAgent,
},
onCapturing: () => {
showLoadingState();
},
onSuccess: (result) => {
if (result.decision === 'authenticated') {
// Access granted
console.log('Welcome!', result.employee);
redirectToApp();
} else if (result.decision === 'challenge_required') {
// Need to complete liveness challenge
handleLivenessChallenge(result.challenges);
} else if (result.decision === 'manual_review') {
showPendingReviewMessage();
}
},
onDenied: (result) => {
console.log('Access denied. Flags:', result.flags);
showAccessDeniedUI(result);
},
onError: (error) => {
handleAuthError(error);
},
});TypeScript Definitions
Enrollment Response
interface EnrollmentResponse {
success: boolean;
data: {
id: string; // Template ID
organizationId: string;
employeeId: string;
status: 'active' | 'pending_voice' | 'pending_quality_review' | 'failed';
source: 'from_verification' | 'standalone' | 'bulk_import';
faceQualityScore: number; // 0-100
voiceQualityScore: number | null;
captureQuality: CaptureQualityFeedback[];
voiceSampleQuality?: VoiceSampleQualityFeedback[];
enrolledAt: string; // ISO timestamp
flags: EnrollmentFlag[];
metadata?: Record<string, string>;
};
error?: {
code: EnrollmentErrorCode;
message: string;
details?: Record<string, unknown>;
};
}
interface CaptureQualityFeedback {
score: number; // 0-100
passed: boolean;
issues: FaceQualityIssue[];
guidance?: string;
}
type FaceQualityIssue =
| 'too_dark'
| 'too_bright'
| 'blurry'
| 'face_too_small'
| 'face_too_large'
| 'face_not_centered'
| 'multiple_faces'
| 'no_face_detected'
| 'poor_lighting'
| 'motion_blur'
| 'occluded';
type EnrollmentFlag =
| 'duplicate_face_in_org'
| 'duplicate_face_cross_org'
| 'duplicate_voice'
| 'low_quality_enrollment'
| 'watchlist_match';Authentication Response
interface AuthenticationResponse {
success: boolean;
data: {
sessionId: string;
decision: 'authenticated' | 'denied' | 'challenge_required' | 'manual_review';
confidenceBand: 'high' | 'medium' | 'low' | 'no_match';
scores: {
faceMatch: number; // 0-100
voiceMatch: number | null; // 0-100 or null if not used
liveness: number; // 0-100
deepfakeScore: number; // 0-100 (100 = definitely real)
combined: number; // 0-100 weighted score
};
flags: AuthenticationFlag[];
challenges?: LivenessChallenge[]; // If challenge_required
employee?: {
employeeId: string;
metadata?: Record<string, string>;
lastAuthenticatedAt?: string;
};
authenticatedAt: string;
processingTimeMs: number;
};
error?: {
code: AuthenticationErrorCode;
message: string;
};
}
type AuthenticationFlag =
| 'liveness_failed'
| 'deepfake_suspected'
| 'face_mismatch'
| 'voice_mismatch'
| 'watchlist_hit'
| 'velocity_anomaly'
| 'device_anomaly'
| 'location_anomaly'
| 'impossible_travel';Error Codes
Enrollment Error Codes
| Code | Description |
|---|---|
| ENROLLMENT_ALREADY_EXISTS | Employee already has an active enrollment |
| QUALITY_TOO_LOW | Captured images don't meet quality threshold |
| DUPLICATE_FACE_DETECTED | Face matches an existing enrollment |
| ENROLLMENT_QUOTA_EXCEEDED | Organization has reached enrollment limit |
| INSUFFICIENT_SAMPLES | Not enough quality samples collected |
Authentication Error Codes
| Code | Description |
|---|---|
| EMPLOYEE_NOT_ENROLLED | No enrollment found for this employee |
| ENROLLMENT_SUSPENDED | Employee enrollment is temporarily suspended |
| LIVENESS_FAILED | Liveness detection did not pass |
| DEEPFAKE_DETECTED | Potential deepfake or spoofing attempt |
| ACCOUNT_LOCKED | Too many failed attempts, account locked |
| RATE_LIMITED | Too many requests, slow down |
| CAPTURE_QUALITY_TOO_LOW | Poor image quality, retry with better conditions |
Browser Compatibility
| Browser | Face Capture | Voice Capture | Notes |
|---|---|---|---|
| Chrome 80+ | ✓ Full Support | ✓ Full Support | Recommended |
| Firefox 75+ | ✓ Full Support | ✓ Full Support | — |
| Safari 14+ | ✓ Full Support | ✓ Full Support | Requires HTTPS |
| Edge 80+ | ✓ Full Support | ✓ Full Support | Chromium-based |
Bundle size: ~45KB gzipped (within 50KB target). Requires HTTPS for camera/microphone access.
Handling Permissions
The SDK automatically handles camera and microphone permission requests. You can check permission status beforehand:
// Check permissions before starting
const permissions = await owl.checkPermissions();
if (!permissions.camera) {
// Show guidance to enable camera
showCameraPermissionGuide();
}
if (options.requireVoice && !permissions.microphone) {
// Show guidance to enable microphone
showMicrophonePermissionGuide();
}
// Permissions object
interface PermissionStatus {
camera: 'granted' | 'denied' | 'prompt';
microphone: 'granted' | 'denied' | 'prompt';
}Never expose your API secret key in client-side code. All enrollment and authentication requests should be initiated from your backend, which then provides session tokens to the frontend SDK.