4 Commits

Author SHA1 Message Date
07196a4bcb fix: keep the device polling token off the QR code
golem15.user.device_auth.auth_url gains a {short_code} placeholder and
defaults to {frontend_url}/device/scan/{short_code}; POST
/devices/authorize accepts the short code in its token field, so a scan
page that posts what its URL carries keeps working. The status poll hands
the session token over only to a client with the User-Agent the device
initiated with; another client sees the session confirmed and takes
nothing.
2026-10-26 16:12:08 +01:00
557c03c595 fix: a password change or ban ends authorized device sessions
The device hand-over now refuses a session authorized before the user's
tokens_valid_after, and every AccessRevokedEvent revokes the user's
pending and confirmed device sessions inside the write's transaction
(classes.RevokeDeviceSessions).
2026-10-26 16:08:20 +01:00
cc3636cea9 fix: a device revoke cannot lose to a concurrent refresh
The revoke now reads the device's jti with UPDATE ... RETURNING under the
row lock, and the refresh's hand-over (classes.FollowDeviceJTI) reports a
session revoked meanwhile, so the refresh answers the blacklisted-token
401 without a token. A hand-over error fails the refresh closed instead
of leaving the session on a stale jti.
2026-10-26 16:00:43 +01:00
1f3266a417 test: device authorization flow and its migration
- TestDeviceCodes (classes, short): tokens, short-code alphabet and
  distribution, normalization
- TestDeviceAuthURL, TestDeviceDisplayName (short): auth_url template, TTL,
  PHP's user-agent order
- TestDeviceInitiate, TestDeviceStatus, TestDeviceAuthorize: PHP bodies for
  every state and refusal, bounded cleanup, short-code collision retry,
  concurrent authorizes binding one user
- TestDeviceHandOverConcurrent, TestDeviceListAndRevoke,
  TestDeviceRevokeAfterRefresh, TestDeviceTokensAtRest
- TestDeviceAuthSessionsMigration (updates): columns, constraints, indexes,
  cascade, rollback and re-up
2026-10-26 14:15:54 +01:00