olorunda / laravel-rekognition-face
Biometric face comparison and real human face verification using Amazon Rekognition for Laravel and PHP
Package info
github.com/olorunda/laravel-rekognition-face
pkg:composer/olorunda/laravel-rekognition-face
Requires
- php: >=8.1
- aws/aws-sdk-php: ^3.280
- illuminate/console: ^9.0|^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0|^10.0|^11.0
- phpunit/phpunit: ^10.0|^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Production-ready Laravel & standalone PHP package to compare two human face images for biometric identity matching and verify whether an image contains a genuine, high-quality, real human face using Amazon Rekognition.
๐ Key Features
-
Biometric Face Comparison (
CompareFaces):- Compares two faces and computes biometric similarity percentage (0% to 100%).
- Configurable similarity threshold (e.g. 80% default).
- Returns bounding boxes, confidence scores, matched landmarks, and unmatched faces in target photo.
-
Real Human Face & Quality Verification (
DetectFaces):- Human Face Detection Confidence: Verifies Rekognition detects a human face with high confidence (e.g. โฅ 95%).
- Single Face Enforcement: Ensures exactly one human face is present (flags multi-face or crowded photos for KYC / ID verification).
- Image Sharpness & Blur Filter: Rejects motion-blurred, out-of-focus, or low-resolution spoof images.
- Brightness & Exposure Validation: Ensures balanced lighting (rejects pitch black or washed-out photocopies).
- 3D Head Pose Orientation: Checks Yaw (turning), Pitch (tilting up/down), and Roll (sideways tilt) to enforce frontal portrait alignment.
- Open Eyes & Liveness Heuristics: Detects closed eyes (flags sleeping/passive photo spoofing).
- Occlusion & Mask Detection: Rejects sunglasses and facial coverings that conceal biometric landmarks.
- Composite Quality Score: Generates a normalized score (0โ100) and actionable diagnostic checklist.
-
Combined Verification Pipeline (
verifyAndCompare):- Verifies that both images are real human faces first.
- Compares the two faces and checks similarity.
- Returns a comprehensive audit trail with pass/fail status and specific violation reasons.
-
AWS Rekognition Face Liveness Session:
- Helpers to generate AWS Face Liveness sessions (
createLivenessSession) and fetch results (getLivenessResults) for frontend camera SDKs (Amplify FaceLivenessDetector).
- Helpers to generate AWS Face Liveness sessions (
-
Universal Image Input Support:
- Local file paths (
/path/to/selfie.jpg) - Raw binary bytes (
file_get_contents(...)) - Base64 strings & Data URIs (
data:image/jpeg;base64,...) - Remote HTTP / HTTPS URLs (auto-downloaded securely)
- Amazon S3 objects (
['bucket' => '...', 'key' => '...']) - Laravel
Illuminate\Http\UploadedFileinstances ($request->file('avatar'))
- Local file paths (
-
Artisan CLI Tools:
php artisan face:compare {source} {target}php artisan face:verify {image}
-
Framework Flexibility:
- Fully integrated with Laravel (Service Provider, Facade, Config publishing, Artisan CLI).
- Can also be instantiated directly in standalone PHP without Laravel.
๐ฆ Installation
Install via Composer:
composer require olorunda/laravel-rekognition-face
In Laravel, the Service Provider and RekognitionFace Facade are registered automatically.
Publish the configuration file:
php artisan vendor:publish --tag="rekognition-face-config"
โ๏ธ Configuration & Environment
Add your AWS credentials to your .env file:
AWS_ACCESS_KEY_ID=your-aws-access-key-id AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key AWS_DEFAULT_REGION=us-east-1 # Optional overrides: REKOGNITION_SIMILARITY_THRESHOLD=80.0 REKOGNITION_MIN_FACE_CONFIDENCE=95.0 REKOGNITION_STRICT_SINGLE_FACE=true REKOGNITION_MIN_SHARPNESS=20.0 REKOGNITION_MIN_BRIGHTNESS=15.0 REKOGNITION_MAX_BRIGHTNESS=95.0 REKOGNITION_REQUIRE_EYES_OPEN=true REKOGNITION_DISALLOW_SUNGLASSES=true REKOGNITION_DISALLOW_OCCLUSION=true # Test & Simulation Mode (Run without real AWS keys!): REKOGNITION_TEST_MODE=false REKOGNITION_SIMULATE_SCENARIO=match # match, no_match, blurry, closed_eyes, multiple_faces, occluded, not_human REKOGNITION_SIMULATE_SIMILARITY=96.5 REKOGNITION_SIMULATE_CONFIDENCE=99.8
๐ Usage
1. Compare Two Faces (Biometric Matching)
Compare an ID card photo and a selfie to see if they belong to the same person:
use Olorunda\RekognitionFace\Facades\RekognitionFace; // Compare local files, URLs, base64 strings, or UploadedFiles $result = RekognitionFace::compare( sourceImage: '/storage/id_card.jpg', targetImage: '/storage/selfie.jpg', similarityThreshold: 85.0 // Optional override ); if ($result->isMatch()) { echo "Faces match! Similarity: {$result->getSimilarity()}%\n"; echo "Detection confidence: {$result->getConfidence()}%\n"; } else { echo "Not a match. Similarity was {$result->getSimilarity()}%\n"; } // Inspect details $matchedFace = $result->getMatchedFace(); echo "Face pitch: {$matchedFace->pitch}ยฐ, yaw: {$matchedFace->yaw}ยฐ\n"; echo "Unmatched faces in target image: {$result->getUnmatchedCount()}\n";
2. Verify If An Image Is A Real Human Face
Inspect an image for authenticity, quality, pose, and absence of spoofs or occlusions:
use Olorunda\RekognitionFace\Facades\RekognitionFace; $realness = RekognitionFace::verifyRealHumanFace('/storage/selfie.jpg'); if ($realness->isRealHumanFace()) { echo "Genuine human face verified!\n"; echo "Quality Score: {$realness->getQualityScore()} / 100\n"; echo "Detection Confidence: {$realness->getConfidence()}%\n"; } else { echo "Verification failed! Issues:\n"; foreach ($realness->getViolations() as $violation) { echo " - {$violation}\n"; } } // Checklist breakdown $checks = $realness->getChecks(); /* [ 'human_detected' => true, // Rekognition detected human face >= 95% 'single_face' => true, // Exactly 1 face found in image 'sharpness_ok' => true, // Not blurry (sharpness >= 20) 'brightness_ok' => true, // Balanced exposure 'pose_frontal' => true, // Facing camera (yaw/pitch/roll within bounds) 'eyes_open' => true, // Open eyes detected 'no_occlusion' => true, // No sunglasses or masks 'min_face_size_ok' => true, // Face is prominent in the frame ] */
Customizing checks on the fly:
$realness = RekognitionFace::verifyRealHumanFace($image, [ 'strict_single_face' => false, // Allow photos with multiple people 'min_sharpness' => 40.0, // Require higher sharpness 'require_eyes_open' => false, // Permit closed eyes ]);
3. Complete End-to-End Pipeline (verifyAndCompare)
Runs both real face checks on the source and target images before comparing them:
use Olorunda\RekognitionFace\Facades\RekognitionFace; $verification = RekognitionFace::verifyAndCompare( sourceImage: $request->file('id_card'), targetImage: $request->file('selfie'), options: ['threshold' => 80.0] ); if ($verification->passed()) { echo "Verification SUCCESS!\n"; echo "Similarity: {$verification->getSimilarity()}%\n"; } else { echo "Verification FAILED!\n"; foreach ($verification->getFailureReasons() as $reason) { echo " - {$reason}\n"; } }
4. AWS Rekognition Face Liveness Session
For active 3D liveness detection using AWS Amplify web or mobile SDK:
use Olorunda\RekognitionFace\Facades\RekognitionFace; // 1. Create a session for the mobile/web frontend $sessionId = RekognitionFace::createLivenessSession(); // 2. Pass $sessionId to client app running AWS Amplify FaceLivenessDetector // 3. Retrieve results once client completes the test $results = RekognitionFace::getLivenessResults($sessionId); if ($results['Status'] === 'SUCCEEDED' && $results['Confidence'] >= 90.0) { echo "Liveness check passed with confidence {$results['Confidence']}%\n"; }
5. ๐งช Test & Simulation Mode (Run Without AWS Keys)
You can develop, test, and run biometric verification without supplying real AWS credentials. This is ideal for local development, CI/CD, staging, and demo environments.
A. Enable via .env:
REKOGNITION_TEST_MODE=true REKOGNITION_SIMULATE_SCENARIO=match # Options: match, no_match, blurry, closed_eyes, multiple_faces, occluded, not_human
B. Runtime Simulation (Mocking like Http::fake()):
use Olorunda\RekognitionFace\Facades\RekognitionFace; // Turn on test mode on the fly RekognitionFace::fake(); // Switch test scenarios: RekognitionFace::fakeScenario('match'); // Matches with high similarity (96.5%) RekognitionFace::fakeScenario('no_match'); // Valid faces, but different people (38.4% similarity) RekognitionFace::fakeScenario('blurry'); // Fails sharpness quality filter RekognitionFace::fakeScenario('closed_eyes'); // Fails eyes open liveness check RekognitionFace::fakeScenario('multiple_faces'); // Multiple people in image (fails strict single-face) RekognitionFace::fakeScenario('occluded'); // Face wearing sunglasses or mask RekognitionFace::fakeScenario('not_human'); // No human face found // Custom simulation parameters: RekognitionFace::fake([ 'similarity' => 92.0, 'is_match' => true, 'confidence' => 99.9, ]); // Check status or turn off: RekognitionFace::isTestMode(); // true RekognitionFace::enableTestMode(false);
C. Available Simulation Scenarios:
| Scenario | Real Face Result | Comparison Result | Typical Use Case |
|---|---|---|---|
match (default) |
Pass (Quality: ~94) | Match (Similarity: 96.5%) | Happy path testing |
no_match |
Pass | No Match (Similarity: 38.4%) | Testing rejection of non-matching IDs |
blurry |
Fail (Sharpness: 8.5 < 20) | Match | Testing low-quality camera uploads |
closed_eyes |
Fail (Eyes closed) | Match | Testing sleeping/photo liveness spoof |
multiple_faces |
Fail (2 faces found) | Match | Testing anti-crowd / multiple person photo |
occluded |
Fail (Sunglasses detected) | Match | Testing mask/sunglasses rejection |
not_human |
Fail (0 faces found) | Throws Exception | Testing object or pet photos |
6. Flexible Image Inputs
The package accepts any of the following formats interchangeably:
// Local file path RekognitionFace::compare('/path/to/photo.jpg', '/path/to/selfie.png'); // Laravel UploadedFile from form request RekognitionFace::compare($request->file('id_document'), $request->file('webcam_capture')); // Base64 Data URI from HTML5 webcam RekognitionFace::verifyRealHumanFace('data:image/jpeg;base64,/9j/4AAQSkZJRg...'); // Raw binary bytes RekognitionFace::compare($rawJpegBytes1, $rawJpegBytes2); // Remote HTTP / HTTPS URL RekognitionFace::compare('https://mycdn.com/id.jpg', 'https://mycdn.com/selfie.jpg'); // AWS S3 Object reference RekognitionFace::compare( ['bucket' => 'my-private-bucket', 'key' => 'users/123/passport.jpg'], ['bucket' => 'my-private-bucket', 'key' => 'users/123/live_capture.jpg'] );
7. Artisan CLI Commands
Compare Two Face Images
# Standard mode (with AWS keys): php artisan face:compare /path/to/id.jpg /path/to/selfie.jpg --threshold=85 # Test mode (without AWS keys): php artisan face:compare /path/to/id.jpg /path/to/selfie.jpg --simulate --scenario=match
Output:
Comparing faces using AWS Rekognition...
Source: /path/to/id.jpg
Target: /path/to/selfie.jpg
MATCH DETECTED!
+----------------------------+-----------+
| Metric | Value |
+----------------------------+-----------+
| Is Match | YES |
| Similarity Score | 96.5% |
| Required Threshold | 85% |
| Detection Confidence | 99.8% |
| Unmatched Faces in Target | 0 |
+----------------------------+-----------+
Verify a Real Human Face
# Standard mode: php artisan face:verify /path/to/selfie.jpg --strict # Test mode: php artisan face:verify /path/to/selfie.jpg --simulate --scenario=blurry
Output:
Analyzing image for real human face...
Image: /path/to/selfie.jpg
REAL HUMAN FACE VERIFIED
+-------------------------+-----------+
| Metric | Value |
+-------------------------+-----------+
| Is Real Human Face | YES |
| Detection Confidence | 99.9% |
| Composite Quality Score | 94.2 / 100|
| Faces Detected | 1 |
| Passed All Checks | YES |
+-------------------------+-----------+
Validation Checklist:
+-------------------+--------+
| Check | Status |
+-------------------+--------+
| Human Detected | PASS |
| Single Face | PASS |
| Sharpness Ok | PASS |
| Brightness Ok | PASS |
| Pose Frontal | PASS |
| Eyes Open | PASS |
| No Occlusion | PASS |
| Min Face Size Ok | PASS |
+-------------------+--------+
8. Standalone PHP Usage (Without Laravel)
require_once __DIR__ . '/vendor/autoload.php'; use Olorunda\RekognitionFace\Services\RekognitionFaceService; $service = new RekognitionFaceService([ 'region' => 'us-east-1', 'credentials' => [ 'key' => 'YOUR_AWS_KEY', 'secret' => 'YOUR_AWS_SECRET', ], 'comparison' => [ 'default_threshold' => 80.0, ], ]); $result = $service->compare('id.jpg', 'selfie.jpg'); if ($result->isMatch()) { echo "Matched! Similarity: " . $result->getSimilarity() . "%\n"; }
๐ Required AWS IAM Policy
Your AWS IAM user or role must have the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RekognitionFacePermissions",
"Effect": "Allow",
"Action": [
"rekognition:CompareFaces",
"rekognition:DetectFaces",
"rekognition:CreateFaceLivenessSession",
"rekognition:GetFaceLivenessSessionResults"
],
"Resource": "*"
}
]
}
(If using S3 object references directly, also ensure s3:GetObject permission on the target buckets).
๐งช Testing
Run PHPUnit tests:
composer test
All unit and feature tests use the AWS SDK MockHandler to run offline without hitting AWS or incurring costs.
๐ License
The MIT License (MIT). Please see LICENSE.md for more information.