feat(auth): add owner-tier passkey-unbind remediation endpoint
Add DELETE /api/v1/users/{id}/passkeys (owner-only) to unbind every passkey a
target account holds — the authenticator remediation that stops a passkey planted
or retained via a transiently-hijacked session from surviving as a standing login
foothold. It wires the previously-uncalled DeleteAllPasskeyCredentialsForUser and
is deliberately not a lockout: the account re-enters via the email-OTP door
(players) or op-login's in-game approval (staff), then re-enrolls. Documented in
the OpenAPI, so the served/documented parity gate covers it.
Remove RevokeUserSessionsExcept: a change-password-era orphan with no callers
since the passwordless migration. Its keep-one ("log out my other devices")
semantics is inherently self-service, and no such slice is on the roadmap; the
admin remediation path already uses RevokeAllUserSessions.
This commit is contained in:
6 files changed
+103
-23
No files matched your search
@@ -836,18 +836,6 @@ func (p *PGRepo) RevokeSession(ctx context.Context, tokenHash string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// RevokeUserSessionsExcept revokes every live session of a user except keepTokenHash
|
||||
// — logs out an account's other devices while keeping the current one. Its original
|
||||
// caller (the change-password flow) was removed in the passwordless migration; it is
|
||||
// retained for the account-remediation path (P5, #78) and currently has no caller.
|
||||
func (p *PGRepo) RevokeUserSessionsExcept(ctx context.Context, userID, keepTokenHash string) error {
|
||||
_, err := p.db.ExecContext(ctx,
|
||||
`UPDATE sessions SET revoked_at = now()
|
||||
WHERE user_id = $1 AND token_hash <> $2 AND revoked_at IS NULL`,
|
||||
userID, keepTokenHash)
|
||||
return err
|
||||
}
|
||||
|
||||
// ---- runtime platform settings (spec §B platform_settings) ----
|
||||
|
||||
// GetSetting reads a setting's raw jsonb value as bytes, or ErrNotFound.
|
||||
|
||||
Reference in new issue
Block a user