Skip to content

Mobile App

The IDToken mobile app is the user’s authenticator and credential wallet. Built with Flutter for iOS and Android, it serves three roles:

RoleDescription
Credential storeHolds the IDToken VDS (QR image + decoded payload including photo)
OTP verifierDisplays the server-generated OTP for visual comparison with the browser
Cryptographic proverSigns authentication approvals with a device-bound ECDSA P-256 private key
WelcomeScan QR(Enroll)Verify Face(Liveness)My IDToken(Home)Auth Request(OTP screen)IDToken Card(View/Share)Approve(face verif)Decline
  1. User taps “Enroll my IDToken”
  2. Camera opens — scan the IDToken QR code
  3. App parses and verifies the VDS locally (ECDSA signature check, expiry check)
  4. id3 Face SDK performs liveness detection (passive + active anti-spoofing) and 1:1 match against the VDS face template
  5. App generates an ECDSA P-256 key pair in the device’s secure element (iOS Secure Enclave / Android Keystore StrongBox)
  6. App calls POST /enroll with the VDS data, public key, device ID, and FCM token
  7. IDToken stored locally in encrypted storage — the user sees the “Home” screen
  1. FCM data push received (OTP is never shown as a system notification — only data messages)
  2. App opens the consent screen showing:
    • Service name and logo
    • Requested scopes with toggleable switches
    • “This service will NOT receive” list (updates dynamically)
    • OTP for visual comparison
    • Countdown timer
  3. User compares OTP, toggles scopes, taps Approve & Share
  4. id3 Face SDK verifies the user (liveness + 1:1 match against VDS face template)
  5. App constructs the signed message: sessionId|otp|timestamp|grantedScopes
  6. ECDSA signature computed in the secure element
  7. App calls POST /auth/verify with the signature and granted scopes
  8. “Approved” checkmark shown — return to Home

The ECDSA P-256 key pair is hardware-bound and non-exportable:

PlatformSecure ElementKey Properties
iOSSecure EnclaveKeys are generated and used entirely within the enclave; never leave the hardware
AndroidAndroid Keystore (StrongBox if available)Hardware-backed; signing operations happen inside the TEE/SE

The public key is exported (PEM format) and sent to the auth server during enrollment. The private key is only used for signing — the app requests a signature from the secure element, passing the message to be signed.

ScenarioBehavior
OTP expires before approval”Session expired” screen; user re-initiates on browser
Phone lostPresent physical document, re-enroll (old tokenId revoked)
Face no longer matchesRe-enroll with document (new VDS with updated photo)
App deletedRe-install, re-enroll (new keypair generated)
Multiple devicesEach device has its own keypair; same tokenId can have multiple enrollments
No network during signingOffline signing works; POST /verify retried on reconnect

The IDToken credential is stored in platform-specific encrypted storage (iOS Keychain / Android EncryptedSharedPreferences). The stored data includes:

FieldDescription
tokenIdUnique VDS identifier
givenName, familyNameName from the credential
dateOfBirth, nationalityIdentity attributes
expiresAtCredential expiry date
photoBase64Portrait photo (WEBP)
faceTemplateBase64Biometric face template for 1:1 matching
qrImageBase64Original QR code image
enrolledAtEnrollment timestamp

The credential is never uploaded to any server after enrollment — the server only stores the public key and tokenId.