configuration PK: id 10 required 1 unique

Description

Stores device-level biometric enrollment references for users who have registered Face ID or fingerprint authentication after completing their first BankID or Vipps login. Credential material never leaves the device secure enclave; only a reference identifier is stored.

14
Attributes
4
Indexes
9
Validation Rules
7
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Immutable primary key, generated server-side on enrollment.
PKrequiredunique
user_id uuid Foreign key referencing the users table. Links the credential to the owning user account.
required
device_id string Stable platform device identifier (iOS identifierForVendor / Android ID). Used to differentiate enrollments across multiple devices owned by the same user.
required
credential_type enum The biometric modality used for this credential enrollment.
required
platform enum The mobile OS platform on which this credential is enrolled.
required
credential_reference string Opaque reference token returned by the device secure enclave / Keystore after successful biometric enrollment. Never contains raw biometric data. Used by the app to retrieve the stored Supabase session token via Flutter Secure Storage.
required
device_name string Human-readable device name (e.g., 'iPhone 15 Pro') sourced from the OS at enrollment time. Displayed to the user in credential management UIs.
-
is_active boolean Whether this credential is currently valid and usable for authentication. Set to false on logout, password change, or explicit revocation rather than hard deleting the row.
required
enrolled_at datetime Timestamp (UTC) when the biometric credential was first registered after a successful BankID or Vipps authentication session.
required
last_used_at datetime Timestamp (UTC) of the most recent successful biometric authentication using this credential. Updated on each successful challenge. Null if the credential was enrolled but never yet used for login.
-
revoked_at datetime Timestamp (UTC) when the credential was explicitly deactivated. Null for active credentials.
-
revocation_reason enum Machine-readable reason for revocation, useful for auditing and support diagnosis.
-
created_at datetime Row creation timestamp, set by Supabase default.
required
updated_at datetime Row last-update timestamp, maintained by a Supabase trigger.
required

Database Indexes

idx_biometric_credentials_user_id
btree

Columns: user_id

idx_biometric_credentials_user_device
btree unique

Columns: user_id, device_id

idx_biometric_credentials_user_active
btree

Columns: user_id, is_active

idx_biometric_credentials_last_used_at
btree

Columns: last_used_at

Validation Rules

device_id_non_empty error

Validation failed

credential_reference_non_empty error

Validation failed

enrolled_at_not_future error

Validation failed

last_used_not_before_enrolled error

Validation failed

valid_credential_type_enum error

Validation failed

valid_platform_enum error

Validation failed

user_id_exists error

Validation failed

device_name_length error

Validation failed

revocation_reason_required_when_inactive error

Validation failed

Business Rules

require_prior_national_id_auth
on_create

A biometric credential may only be created after the user has completed a successful BankID or Vipps authentication in the current session. Enrollment is blocked for users who have only authenticated via email/password.

Enforced by: Biometric Auth Service
one_credential_per_device_per_user
on_create

Each (user_id, device_id) pair must be unique. If a credential already exists for this device, the existing record must be revoked and replaced rather than creating a duplicate row.

Enforced by: Biometric Auth Service
max_enrolled_devices_per_user
on_create

A single user may have at most 5 active biometric credentials across different devices. Enrolling on a sixth device requires the user to explicitly revoke an existing credential first.

Enforced by: Biometric Auth Service
no_raw_biometric_data_stored
on_create

The credential_reference field must contain only the opaque reference token from the device secure enclave / Android Keystore. Raw biometric templates, hashes, or any biometric-derived material must never be stored in this table or transmitted off-device.

revoke_on_password_change
on_update

When the user changes their password or re-authenticates via BankID/Vipps with a new session, all active biometric credentials for that user must be set is_active = false with revocation_reason = 'password_changed' or 'bankid_reauth_required'.

Enforced by: Biometric Auth Service
revoke_on_logout
on_delete

On explicit logout, all active credentials for the user on the current device must be deactivated (is_active = false, revocation_reason = 'user_logout'). Full account logout revokes all device credentials.

update_last_used_on_auth
on_update

Every successful biometric authentication must update last_used_at to the current UTC timestamp on the corresponding credential row.

Enforced by: Biometric Auth Service
rls_user_scope
always

Supabase Row Level Security must restrict reads and writes to the row's own user_id matching auth.uid(). No user may read, modify, or enumerate another user's biometric credential records.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage

Entity Relationships

users
incoming one_to_many

A user may have biometric credentials enrolled on multiple devices

optional cascade delete