Skip to content

Add HTTP endpoint for end users to change their own password #351

@melvincarvalho

Description

@melvincarvalho

Summary

A logged-in user has no way to change their own password through the running JSS. The only password-management interface today is the jss passwd <user> CLI (#232), which requires shell access on the server. End users in a multi-user pod or anyone running JSS without local shell access (containers, managed hosts, etc.) is stuck.

Current state

  • CLI: jss passwd <user> — operator-only, shell required.
  • HTTP IDP:
    • POST /idp/credentials — login only (issues token).
    • No change-password / password-reset endpoint.
  • Account records carry passwordHash (bcrypt) so the data layer already supports a rotation, just no API.

Proposed shape

A single authenticated endpoint, owner-only (the caller's WebID must match the account's WebID), gated by re-supplying the current password as proof:

PUT /idp/credentials
Authorization: <existing session / DPoP>
Content-Type: application/json

{
  "currentPassword": "...",
  "newPassword": "..."
}
  • 200 + new bcrypt hash written, all other sessions invalidated, current session re-issued.
  • 401 if current password is wrong.
  • 401 if not authenticated.
  • 403 if the authenticated WebID doesn't match the target account.

(Path bikeshed: PUT /idp/credentials matches the existing POST /idp/credentials shape; alternatives are POST /idp/account/password or PATCH /idp/credentials. Not load-bearing — pick whatever lands cleanly with the existing IDP routes.)

Out of scope

  • Password recovery / forgot-password flow (no current password). That's a separate feature that needs an email channel + token store. File as a follow-up if/when there's a recovery story.
  • WebAuthn / passkey rotation (separate auth mechanism, tracked in feat: Add passkey (WebAuthn) authentication support #78).

Acceptance

  • New endpoint accepts a valid {currentPassword, newPassword} from the authenticated owner and rotates the hash.
  • Wrong currentPassword → 401, hash unchanged.
  • Cross-account write attempts (authenticated as A, targeting B's password) → 403.
  • Any other active sessions for the rotated account are invalidated (refresh tokens revoked, etc.).
  • Existing jss passwd <user> CLI continues to work unchanged.
  • Tests cover happy path + the three failure modes above + session-invalidation behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions