Skip to content

TIGER-242: credential provider owns password writes (change/forgot/admin reset) - #319

Merged
WebTigers merged 1 commit into
mainfrom
feat/tiger-242-credential-write-seam
Sep 26, 2026
Merged

WebTigers merged 1 commit into
mainfrom
feat/tiger-242-credential-write-seam

Conversation

@WebTigers

Copy link
Copy Markdown
Owner

TIGER-242 — the credential provider owns password writes

The Tiger_Auth_Credential seam (shipped 1.16.0) made the password verify pluggable: a registered provider — e.g. TigerServer's server adapter — authenticates an account owner's login against the OS/system credential, so there's one password. But the factor was verify-only: every password write (change, forgot-password reset, admin reset) still wrote the DB user_credential the provider has superseded. So an owner changing their password didn't touch the real (OS) password → login kept failing.

This makes the factor read and write, so a provider that owns a user's login also owns their password writes.

Changes

  • Tiger_Auth_Credential_Adapter_Abstract — adds canSetPassword($user) + setPassword($user, $newPassword). Both default false: a verify-only authority (an external IdP / AD) stays read-only, and the write flows report "managed elsewhere" instead of silently writing an ignored DB row. A write-capable adapter (the server adapter) overrides both.
  • Tiger_Service_Authentication::setPasswordFor($userId, $newPassword) — the single write seam. Resolves the same provider login()/unlock() consult; writes through it when it owns the user, else the default DB path (setPassword + recordSuccess). Fail-safe: unknown user / read-only provider / adapter throw → false.
  • All three write flows routed through it: Profile_Service_Security::changePassword (self-service), Authentication::resetPassword (forgot-password), Access_Service_User::save (admin reset).

Safety / back-compat

  • No provider configured → byte-for-byte the same DB behaviour as before (the ~all installs). The provider path is only taken when one is registered and appliesTo() the user.
  • Only the password factor moves; TOTP/2FA, lockout, audit, and session issuance are untouched.

Tests

  • CredentialTest extended: read-only default (verify-only adapter can't write), write-capable adapter owns the write and fails closed on an empty password. Unit suite green (7 tests).
  • Integration suites (AuthenticationTest, SecurityServiceTest, Access) run in CI against the test DB.

Added profile.security.password_change_failed in all seven locales. 1.16.1 → 1.17.0; CHANGELOG + FEATURES updated.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ

…min reset)

The pluggable password factor was verify-only: a registered provider (e.g.
TigerServer's system credential) authenticated login/unlock, but every
password WRITE still landed in the DB user_credential the provider has
superseded — so changing or resetting an account owner's password didn't
touch the real (OS) password.

Make the factor read AND write:

- Tiger_Auth_Credential_Adapter_Abstract gains canSetPassword($user) +
  setPassword($user, $newPassword) (both default false — a verify-only
  authority like an external IdP stays read-only and reports "managed
  elsewhere" rather than silently writing an ignored DB row).
- New write seam Tiger_Service_Authentication::setPasswordFor($userId,
  $newPassword): resolves the same provider login()/unlock() use; writes
  through it when it owns the user, else the default DB path (setPassword +
  recordSuccess). Fail-safe: unknown user / read-only provider / adapter
  throw -> false.
- Route all three password-write flows through it:
  Profile_Service_Security::changePassword (self-service),
  Authentication::resetPassword (forgot-password), and
  Access_Service_User::save (admin reset). No provider configured -> byte-for-
  byte the same DB behaviour as before.

profile.security.password_change_failed added in all seven locales.
Version 1.16.1 -> 1.17.0; CHANGELOG + FEATURES updated. Unit tests extended
(read-only default, write-capable adapter).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ
@WebTigers
WebTigers merged commit 7d8da0b into main Sep 26, 2026
14 checks passed
@WebTigers
WebTigers deleted the feat/tiger-242-credential-write-seam branch September 26, 2026 20:55
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