feat(auth): Active Devices — view/revoke mobile sessions
Adds the self-service device-session surface the mobile-SSO spec requires, on
top of the existing mobile_refresh_tokens store.
- Schema: device_name + last_used_at columns on mobile_refresh_tokens (nullable,
additive via the ALTER section; seeded to now on insert). With single-use
rotation each login/refresh inserts a fresh row, so the active row's timestamp
is the session's last activity, and the label is carried forward on refresh.
- Model: listActiveForUser (one row per live device, no token hash) +
revokeByIdForUser (ownership-scoped, idempotent).
- GET /auth/me/sessions + DELETE /auth/me/sessions/:id (role-agnostic, behind
requireAuth). Named distinctly from /auth/me/devices (push endpoints).
- device_name is an optional field on /auth/mobile/login and
/auth/mobile/sso/exchange so the app can label a device.
- Client: an "Active Devices" panel on the player account page (list + sign a
device out), plus the PlayerLogin change to honor the mobile SSO bridge's
{ redirect } deep link on a 2FA completion.
- Swagger DeviceSession schema + regenerated spec; 3 controller tests. Full
server suite green (274); client builds.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,8 @@ mobileRouter.post(
|
||||
body('password').isString().notEmpty(),
|
||||
// Optional TOTP code (single-request 2FA); only checked when the account has 2FA on.
|
||||
body('code').optional().isString().trim().isLength({ min: 6, max: 8 }),
|
||||
// Optional friendly device label for the Active Devices list.
|
||||
body('device_name').optional({ values: 'falsy' }).isString().trim().isLength({ max: 100 }),
|
||||
validate,
|
||||
login,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user