Overview
Device management tracks which browsers and devices have accessed your PassAgent vault. Each device is identified by a privacy-respecting fingerprint, assigned a trust level, and monitored for activity. When an unrecognized device signs in, PassAgent can trigger step-up authentication — requiring the user to re-verify their identity before accessing sensitive vault operations.Device fingerprinting
ThegenerateDeviceFingerprint() function in lib/device-fingerprint.ts produces a SHA-256 hash from a set of stable browser and OS signals. This fingerprint is deterministic for the same device/browser combination but varies across different setups.
Collected signals:
| Signal | Source | Example |
|---|---|---|
| Platform | navigator.platform | MacIntel |
| Language | navigator.language | en-US |
| CPU cores | navigator.hardwareConcurrency | 8 |
| Screen resolution | screen.width x screen.height | 2560x1440 |
| Color depth | screen.colorDepth | 24 |
| Timezone | Intl.DateTimeFormat().resolvedOptions().timeZone | America/New_York |
| Touch points | navigator.maxTouchPoints | 0 |
| GPU renderer | WebGL UNMASKED_RENDERER_WEBGL | ANGLE (Apple, ANGLE Metal..., ...) |
| separators and hashed with SHA-256 via crypto.subtle.digest(). The resulting hex string is the device fingerprint.
This is NOT a tracking fingerprint. PassAgent does not use canvas fingerprinting, audio fingerprinting, font enumeration, or any invasive tracking technique. The signals collected are limited to what is necessary for device identification and are never shared with third parties.
Device type detection
getDeviceType() classifies the device into three categories based on the user agent string:
| Type | Detection pattern |
|---|---|
tablet | /iPad|Android(?!.*Mobile)/i |
mobile | /Mobile|iPhone|iPod|Android|webOS|BlackBerry|IEMobile|Opera Mini/i |
desktop | Everything else |
Registration flow
Generate fingerprint
On login or vault unlock, the client calls
generateDeviceFingerprint() to produce the device hash. The client also collects deviceName (derived from the user agent), deviceType, os, and browser metadata.Register device
The client sends
POST /api/devices with the fingerprint and metadata. The server checks if a device with this fingerprint already exists for the user.Existing device: update activity
If the fingerprint matches an existing record, the server updates
last_active_at, sets is_current: true (and clears is_current from all other devices), and refreshes the OS/browser metadata.Trust levels
| Level | Description | Vault access |
|---|---|---|
trusted | Recognized device, explicitly approved | Full access |
recognized | Previously seen but not yet trusted | Requires step-up auth for sensitive operations |
unknown | Brand new device, never seen before | Requires full re-authentication |
Device record schema
Each trusted device record in thetrusted_devices table contains:
| Field | Type | Description |
|---|---|---|
id | UUID | Primary key |
user_id | string | Owner’s user ID |
device_fingerprint | string | SHA-256 hash of collected signals |
device_name | string | Human-readable name (e.g., “Chrome on macOS”) |
device_type | string | desktop, mobile, or tablet |
os | string | Operating system (e.g., “macOS 14.2”) |
browser | string | Browser name and version (e.g., “Chrome 120”) |
ip_address | string | Last known IP address |
trust_level | string | trusted, recognized, or unknown |
is_current | boolean | Whether this is the active device |
last_active_at | timestamp | Last activity time |
trusted_at | timestamp | When the device was first trusted |
Managing devices
Rename a device
PATCH /api/devices/{id} with { deviceName: "Work Laptop" } updates the display name. This is purely cosmetic and does not affect the fingerprint or trust level.
Change trust level
PATCH /api/devices/{id} with { trustLevel: "recognized" } downgrades a device. This is useful if you lent your laptop to someone and want to require step-up auth the next time it accesses your vault.
Revoke a device
DELETE /api/devices/{id} permanently removes the device from your trusted list. The next time that device accesses your vault, it will appear as a new, unknown device and trigger the new-device flow.
Step-up authentication
When a sensitive operation is attempted (password export, emergency access, session sharing), PassAgent checks the device’s trust level. If the device isrecognized or unknown, or if the last authentication was too long ago, the user is prompted to re-verify their identity with their master password or biometric.
Audit logging
All device management actions are recorded in the audit log:| Action | Trigger |
|---|---|
device.updated | Device renamed or trust level changed |
device.revoked | Device removed from trusted list |
Rate limiting
| Endpoint | Limit | Window |
|---|---|---|
POST /api/devices (register) | 30 requests | 60 seconds |
PATCH /api/devices/{id} (update) | 30 requests | 60 seconds |
DELETE /api/devices/{id} (revoke) | 30 requests | 60 seconds |
API endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/devices | List all trusted devices for the authenticated user |
POST | /api/devices | Register or re-register the current device |
PATCH | /api/devices/[id] | Update device name or trust level |
DELETE | /api/devices/[id] | Revoke a trusted device |
The
is_current flag is automatically managed by the server. Only one device per user can be marked as current at any time. This flag is used by the UI to highlight which device you are currently using.