Skip to main content

Biometric Verification

What it is​

Face-matching and liveness-detection for identity verification — the mechanism behind the KYC_COMPLETE flag referenced in the User guide. Built on AWS Rekognition for the computer-vision work (face comparison, liveness, face detection) plus IdentityPass for the BVN-linked flow — not Vertex AI, despite Vertex AI being the platform's primary AI provider for other features (content generation).

Core concepts​

  • Liveness ≠ face match — these are two different checks composed together. Liveness proves the person is a real live human in front of the camera right now (not a photo of a photo); face match proves that live person is who they claim to be (matches a reference image, e.g. an ID photo). A full verification typically needs both.
  • Two liveness modes: a two-image challenge/response (checkLiveness, checkLivenessTwoImages — initial image + a challenge image, e.g. after a prompted action) and a video-based flow (verify-video, extract-video-frames — frames are pulled from an uploaded video via VideoFrameExtractor and checked individually).
  • checkLivenessWithBvn ties biometric proof to the BVN verification flow covered in the User guide — this is where KYC_COMPLETE actually gets satisfied, distinct from the simpler OTP-only BVN_VERIFIED/NIN_VERIFIED flags.

How it works​

  1. POST /biometric/detect-face — confirm an image actually contains a usable face before running anything more expensive on it.
  2. POST /biometric/check-liveness (or .../verify-video + .../extract-video-frames for the video variant) — prove the submission is a live person.
  3. POST /biometric/compare-faces / .../verify-user-face — match the live capture against a reference image.
  4. POST /biometric/check-liveness-with-bvn — the combined flow that, on success, is what actually completes KYC_COMPLETE for the user.

Key business rules & edge cases​

  • Because verification composes multiple independent AWS Rekognition calls (detect → liveness → compare), a partial failure partway through should be surfaced distinctly from "verification failed" — e.g. "no face detected" needs different user-facing guidance than "face didn't match."
  • Video-based liveness runs frame extraction then per-frame detection (detectFaceFromBuffer in a loop) — this is more expensive than the two-image flow; don't default to it for cases where the simpler two-image challenge is sufficient.
  • This module's provider choice (AWS Rekognition + IdentityPass) is a real discrepancy from the platform's usual AI-provider story (Vertex AI/OpenAI elsewhere) — don't assume Vertex AI patterns/quotas/config apply here.

POST /v1/biometric/detect-face, POST /v1/biometric/check-liveness, POST /v1/biometric/compare-faces, POST /v1/biometric/verify-user-face, POST /v1/biometric/check-liveness-with-bvn. Not yet in the generated OpenAPI spec.

  • src/modules/biometric-verification/biometric-verification.route.ts, .controller.ts, .service.ts
  • src/shared/services/aws-rekognition.service.ts
  • src/shared/implementations/identityPass/identityPass.provider.service.ts
  • src/shared/utils/video-frame-extractor.ts
  • Cross-reference: src/shared/enum/kyc.enum.ts — KycStatusFlags.KYC_COMPLETE