Device Documentation
This documentation explains the features and usage of Device Module: Located at src/modules/device
Overview
Devices represent physical or virtual clients that users log in from. Each device is uniquely identified by a fingerprint and can be owned by multiple users. User-device relationships are managed through the DeviceOwnership model.
When a device ownership is removed, all active sessions linked to that device-user pair are immediately invalidated — across both Redis and the database — forcing logout on the affected client.
This is a critical security mechanism. It allows users (and admins) to forcibly terminate all sessions on a specific device-user pair.
Related Documents
- Authentication Documentation - For understanding session management and JWT
- Authorization Documentation - For policy-based access control on device endpoints
- Notification Documentation - For push notification token management tied to devices
Table of Contents
- Overview
- Related Documents
- Device Model
- Device-Session Relationship
- What Happens When a Device is Removed
- Endpoints
- Policy Control
Device Model
A Device represents a physical or virtual client. It is identified by a globally unique fingerprint that can be owned by multiple users.
Fields:
fingerprint— Globally unique identifier for the device. This value should be generated on the frontend and sent with every login/refresh request. The recommended library is FingerprintJS (or its open-source variant@fingerprintjs/fingerprintjs)name— Human-readable device name (optional, e.g."iPhone 15","Chrome on Windows")platform— Platform of the device. SeeEnumDevicePlatformbelownotificationToken— FCM/APNs push token (optional, used for push notifications). Globally unique per device. Populated viaPOST /user/device/refreshnotificationProvider— Derived automatically fromplatform. SeeEnumDeviceNotificationProviderbelow
Enums
EnumDevicePlatform
| Value | Description |
|---|---|
ios | Apple iOS device |
android | Android device |
web | Web browser |
EnumDeviceNotificationProvider
Automatically derived from platform when a notificationToken is present. Not set for web platform.
| Value | Platform | Description |
|---|---|---|
fcm | android | Firebase Cloud Messaging |
apns | ios | Apple Push Notification Service |
DeviceOwnership Model
The DeviceOwnership model represents the relationship between a User and a Device. It tracks:
- Which device a user owns
- Device revocation status and history
- Session count for that device-user pair
Device-Session Relationship
Each Session record has a required deviceOwnershipId field pointing to a DeviceOwnership. One device-user pair can have only one active session at a time.
User
└── DeviceOwnership (N per user, one per owned device)
├── Device (shared across multiple users via other ownerships)
└── Session[] (max 1 active per device-user pair)
Device
└── DeviceOwnership[] (can be owned by multiple users)
└── Session[] (per ownership)When listing devices, the API shows only the devices owned by the user, with session information for their specific ownership.
What Happens When a Device Ownership is Removed
Removing a device ownership (device per user) triggers a transaction that:
- Updates the
DeviceOwnershiprecord — marks as revoked (isRevoked: true,revokedAt: now,revokedById: userId), updatesupdatedBy. The ownership record is retained for audit trail. - Updates the
Devicerecord — clears thenotificationTokenandnotificationProviderfor this specific ownership (push token is invalidated), updatesupdatedBy. - Revokes the active session for that device-user pair in the database (
isRevoked: true,revokedAt: now) - Deletes the session key from Redis — causing immediate 401 on any subsequent request using those tokens
- Creates an activity log entry with action
userRemoveDeviceoradminDeviceRemove
Endpoints
Shared (User Self-Service)
| Method | Path | Description |
|---|---|---|
GET | /user/device/list | List own devices (cursor-based) with active session count for current session |
POST | /user/device/refresh | Update device info (name, push token, platform) |
DELETE | /user/device/remove/:deviceId | Remove own device — revokes all its sessions immediately |
Admin
| Method | Path | Description |
|---|---|---|
GET | /user/:userId/device/list | List a user’s devices (offset-based) |
DELETE | /user/:userId/device/remove/:deviceId | Remove a user’s device — revokes all its sessions immediately |
Policy Control
Device endpoints are protected using EnumPolicySubject.device. Admin endpoints require both user (read) and device (read/delete) abilities:
// Admin list devices
@PolicyAbilityProtected(
{ subject: EnumPolicySubject.user, action: [EnumPolicyAction.read] },
{ subject: EnumPolicySubject.device, action: [EnumPolicyAction.read] }
)
// Admin remove device
@PolicyAbilityProtected(
{ subject: EnumPolicySubject.user, action: [EnumPolicyAction.read] },
{ subject: EnumPolicySubject.device, action: [EnumPolicyAction.delete] }
)Shared (user self-service) endpoints only require @UserProtected() and @AuthJwtAccessProtected() — no policy subject check since users can only manage their own devices.