Enrollment
Enrollment is the process of binding a VDS credential (digital identity derived from a passport) to a mobile app’s ECDSA key pair. This creates the trust anchor used for all subsequent authentications.
Overview
Section titled “Overview”During enrollment:
- The mobile app scans a passport (MRZ + NFC ICAO)
- The id3 Face SDK performs liveness detection and 1:1 face matching
- The BioSeal Issuance Service generates a VDS (Visible Digital Seal)
- The mobile app generates an ECDSA P-256 key pair
- The app sends the VDS data + public key to the auth server
- The server verifies the VDS and stores the binding
Enrollment Endpoint
Section titled “Enrollment Endpoint”Registers a mobile device with a VDS credential and ECDSA public key.
Rate limit: 5 requests per hour per IP.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
vdsData | string | Yes | VDS data (Base64, Base45, or hex encoded MessagePack) |
publicKeyPem | string | Yes | ECDSA P-256 public key in PEM format |
deviceId | string | Yes | Unique device identifier |
fcmToken | string | No | Firebase Cloud Messaging token for push notifications |
Example Request
Section titled “Example Request”{ "vdsData": "3q8DVkRT...", "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYH...\n-----END PUBLIC KEY-----", "deviceId": "device-uuid-12345", "fcmToken": "fcm:APA91b..."}Response (200 OK)
Section titled “Response (200 OK)”{ "enrolled": true, "tokenId": "vds-uuid-from-seal", "expiresAt": "2026-01-15T00:00:00Z"}Error Responses
Section titled “Error Responses”| Status | Reason |
|---|---|
400 | Invalid VDS data or public key format |
409 | Token ID already revoked |
429 | Rate limit exceeded |
VDS Verification During Enrollment
Section titled “VDS Verification During Enrollment”When the server receives VDS data, it performs these verification steps:
- Decode — Detect encoding (Base64, Base45, hex) and convert to binary
- Parse header — Extract marker (
0xDE), version, IAC, cert reference, manifest ID, timestamp - Validate timestamp — Must not be more than 5 minutes in the future
- Decode payload — MessagePack decode to extract identity fields
- Check expiration — VDS must not be expired
- Verify signature — ECDSA P-256 signature over
SHA256(header || SHA256(payload)) - Walk PKI chain — Resolve trust from VDSIC Governance List down to signing certificate
VDS Payload Fields
Section titled “VDS Payload Fields”| Field | Key | Description |
|---|---|---|
| Given name | gn | First name from passport |
| Family name | fn | Last name from passport |
| Date of birth | dob | ISO date format |
| Nationality | nat | 3-letter country code |
| Document number | doc | Passport/ID number |
| Token ID | tid | Unique VDS identifier (UUID) |
| Expiry | exp | Unix timestamp |
| Photo | photo | CBEFF biometric photo (JPEG, optional) |
Trust Levels
Section titled “Trust Levels”Each enrollment is assigned a trust level based on the VDS certificate chain:
| Level | Name | Meaning |
|---|---|---|
| 1 | Self | VDS issued by non-verified CA |
| 2 | Admin | VDS verified by an operator |
| 3 | eIDAS | Full PKI chain verified (VDSIC → CA) |
Trust levels determine which services the user can access. Relying parties can require a minimum trust level.
Idempotent Enrollment
Section titled “Idempotent Enrollment”Enrollment is idempotent — calling POST /enroll with the same tokenId updates the existing enrollment (new public key, device ID, FCM token) rather than creating a duplicate.
This allows:
- Device replacement — User gets a new phone, re-enrolls with the same VDS
- FCM token refresh — Update the push notification token without re-enrolling
Revocation
Section titled “Revocation”Enrollments can be revoked via POST /revoke:
{ "tokenId": "vds-uuid", "reason": "lost_device"}Revocation reasons:
lost_device— Mobile device lost or stolencompromised— Key compromise suspectedexpired_document— Underlying passport/ID expireduser_request— User-initiated revocation
Once revoked, the tokenId cannot be used for authentication. A new enrollment with the same VDS is possible (new key pair generated).
Database Schema
Section titled “Database Schema”The enrollment data is stored in the following structure:
| Column | Type | Description |
|---|---|---|
id | UUID | Primary key |
token_id | VARCHAR(64) | Unique VDS token identifier |
public_key_pem | TEXT | ECDSA P-256 public key (PEM) |
device_id | VARCHAR(255) | Unique device identifier |
fcm_token | TEXT | Push notification token (optional) |
trust_level | SMALLINT | Trust level (1, 2, or 3) |
is_revoked | BOOLEAN | Whether enrollment is revoked |
revoked_at | TIMESTAMPTZ | Revocation timestamp |
revoke_reason | TEXT | Reason for revocation |
created_at | TIMESTAMPTZ | Enrollment creation time |
updated_at | TIMESTAMPTZ | Last update time |