Bytid liveness for Flutter
Bytid was called UVerify (and, briefly, ByteID). Package names are unchanged, and
UVerifyandByteIDstill work as aliases ofBytid.
Bytid's face check (liveness), and verification links, inside your Flutter app.
The check runs on Bytid's hosted page, the same one your customers get in a browser, so every anti-spoofing layer (depth, colour flash, random prompts) applies, and improvements reach your app without an app update.
flutter pub add uverify_liveness
iOS 14.3+ (camera inside web views), Android 7+.
Setup
iOS: ios/Runner/Info.plist
<key>NSCameraUsageDescription</key>
<string>We use the camera to confirm it's really you.</string>
and in ios/Podfile, turn on the camera permission for permission_handler:
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'PERMISSION_CAMERA=1']
end
end
end
Android: android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
Using address links? Also add NSLocationWhenInUseUsageDescription to Info.plist and <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> to the manifest. If the link asks for a proof of address, the customer photographs it: add NSPhotoLibraryUsageDescription (iOS) for the gallery; image_picker handles the rest.
Use
Your server creates the session with a Bytid server SDK and returns its url. Never put your API key in the app.
import 'package:uverify_liveness/uverify_liveness.dart';
final result = await UVerifyLiveness.start(context, url: session.url);
switch (result) {
case LivenessResult(:final sessionId, :final status):
// status: passed, failed or expired. Send sessionId to your server for the face match.
break;
case UVerifyCancelled(:final reason):
// closed, back or camera_denied
break;
default:
break;
}
Then, on your server, run the face match with that session:
await bytid.identity.bvnFaceMatch({ id_number, first_name, last_name, liveness_session_id: sessionId });
The result in the app is only a hint to move on; trust what your server gets from the API.
To place the check in your own screen instead of a full-screen route, use the widget:
UVerifyLivenessView(url: session.url, onResult: (result) { /* ... */ })
Verification links
The same view opens a verification link (link.url from kyc.createLink); the result is a KycResult with id, status and outcome.
Address links
It also opens an address link (link.url from address.createLink), where the customer shares their phone's location at home. The view asks for location instead of the camera, and the result is an AddressResult with id, status and result (verified, partial or failed). Read the distance and details on your server with address.getLink(id). A refused location comes back as UVerifyCancelled('location_denied').
Options
url |
The session or link url from your server |
redirectUrl |
The redirect_url you created it with, if any; reaching it also finishes (RedirectResult with its query params) |
allowedHosts |
Extra hosts allowed in the view (Bytid's are always allowed; everything else is blocked) |
title |
UVerifyLiveness.start only: the app bar title |
API reference: https://www.bytid.com/docs. MIT licence.
Libraries
- uverify_liveness
- Bytid (formerly UVerify) face check (liveness) and verification links inside a Flutter app.