Skip to content

Login/security refinements#6

Merged
SiteRelEnby merged 5 commits intomainfrom
auth-ux
Apr 26, 2026
Merged

Login/security refinements#6
SiteRelEnby merged 5 commits intomainfrom
auth-ux

Conversation

@SiteRelEnby
Copy link
Copy Markdown
Contributor

@SiteRelEnby SiteRelEnby commented Apr 25, 2026

Summary

Smaller changes to login flow and security model

Changes

  • Increase 2FA recovery code entropy to 64 bits,
  • Email/Password change endpoints
  • "Remember this device" 2FA bypass option, invalidated on password change, session revocation, and 2FA config change
  • Harden JWTs

Testing

  • ruff check sheaf/ passes
  • cd web && npm run lint && npx tsc --noEmit passes
  • Existing tests pass
  • New tests added (if applicable)
  • Tested manually

Security / privacy impact

  • Increased recovery code entropy for bruteforce resistance even against low-and-slow efforts.
  • Ability to change email+password generally considered a good thing
  • Remember this device is well-understood as a choice, and revoked on any change with account security implications.

Previously 32 bits (token_hex(4)) — feasible to brute-force offline
given enough compute. Each code is now 16 hex chars formatted as
XXXXXXXX-XXXXXXXX for readability when users transcribe them from
paper backups.
iss is sheaf_base_url when configured (tying tokens to the origin that
issued them) or the string "sheaf" otherwise. aud is "sheaf-api".
decode_token now enforces both plus exp / iat / sub via pyjwt's
require option, so an access token minted for a different deployment
or with a missing standard claim fails to validate.

Tokens issued before this change lack the new claims and will fail
decode, forcing one re-login.
Gated on the current password and, when TOTP is enabled, a fresh code
or recovery code. On success the calling session stays alive but every
other session for the user is revoked, so a stolen cookie elsewhere
can't survive the change. Refresh tokens bound to revoked sessions
fail at /refresh's session-existence check.
Same auth gate as change-password — current password plus TOTP if
enabled. The new address has email_verified flipped back to false and
a verification mail goes out; pre-apply verification doesn't actually
defend against session compromise (the attacker controls the
destination inbox), so the password+TOTP gate is the real protection
and the re-verify is a typo safety net. Other sessions revoked too.
Optional 30-day cookie that skips TOTP on a trusted browser. Cookie is
HMAC-hashed in the DB and bound to user_id so it can't be replayed
against another account. Auto-revoked on password change and TOTP
disable; manual revoke per-device or all-at-once from settings.
@SiteRelEnby SiteRelEnby marked this pull request as ready for review April 26, 2026 21:28
@SiteRelEnby SiteRelEnby merged commit c0096f9 into main Apr 26, 2026
3 checks passed
@SiteRelEnby SiteRelEnby deleted the auth-ux branch April 27, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant