Class PasswordChangeHandler

java.lang.Object
org.codelibs.fess.api.v2.handlers.PasswordChangeHandler

public class PasswordChangeHandler extends Object
Handles POST /api/v2/auth/password.

Changes the current user's password. The handler requires an active session (401 auth_required otherwise) and the caller's current_password — when blank the response is 400 invalid_request, when wrong the response is 401 auth_required. The new password is validated against the system's password policy (SystemHelper#validatePassword), and the actual store is delegated to UserService.changePassword(java.lang.String, java.lang.String). Confirm-password mismatch and a blank new password both yield 400 invalid_request.

Request body shape:


 { "current_password": "...", "new_password": "...", "confirm_password": "..." }
 

All three fields are required. The current_password check follows the same TypicalLoginAssist.findLoginUser(org.lastaflute.web.login.credential.LoginCredential) pattern used by ProfileAction.changePassword.

C-3: although the caller is already authenticated, a stolen-session attacker could otherwise brute-force current_password unbounded. The handler therefore consults the LoginRateLimiter per-user bucket (same configuration as /api/v2/auth/login): a LoginRateLimiter.peek(org.codelibs.fess.api.v2.handlers.LoginRateLimiter.Scope, java.lang.String, int, int) gates entry, an LoginRateLimiter.allow(org.codelibs.fess.api.v2.handlers.LoginRateLimiter.Scope, java.lang.String, int, int) consumes a slot on wrong-password, and LoginRateLimiter.clear(org.codelibs.fess.api.v2.handlers.LoginRateLimiter.Scope, java.lang.String) resets the bucket on success — mirroring LoginHandler. When the user bucket is exhausted, the handler returns 429 rate_limited with a Retry-After header.

M-3 session contract: After a successful password change the current HTTP session is invalidated (HttpSession.invalidate()) so any session token that was exfiltrated before the change cannot be reused. The response includes re_login_required: true so the SPA can redirect to the login page. Note that csrf_token is NOT returned in the success response because the session that held the old token has already been destroyed; the SPA must obtain a fresh token after re-authenticating. Invalidating other concurrent sessions for the same user is a follow-up item (requires a Fess-wide session registry, not available in this release).

MJ-30 i18n contract: error.message values in this handler are developer-facing English strings. Clients MUST use error.code (the V2ErrorCode token) for user-facing i18n. Handlers also emit a stable error.details.reason token (and min_length for errors.password_length) so clients can localize the specific failure.

  • Constructor Summary

    Constructors
    Constructor
    Description
    Default constructor used by the DI container.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    handle(jakarta.servlet.http.HttpServletRequest req, jakarta.servlet.http.HttpServletResponse res)
    Processes one POST /api/v2/auth/password request.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • PasswordChangeHandler

      public PasswordChangeHandler()
      Default constructor used by the DI container. The handler resolves the shared LoginRateLimiter lazily so DI bootstrap order is not constrained. The handler holds no per-request state and is safe to share across concurrent requests.
  • Method Details

    • handle

      public void handle(jakarta.servlet.http.HttpServletRequest req, jakarta.servlet.http.HttpServletResponse res) throws IOException
      Processes one POST /api/v2/auth/password request.

      Requires an authenticated session, then re-verifies the supplied current_password via TypicalLoginAssist.findLoginUser(org.lastaflute.web.login.credential.LoginCredential) before updating the stored hash. On success the current HTTP session is invalidated (M-3) and the response includes re_login_required: true. Because the session is destroyed the response does not carry a rotated CSRF token; the SPA must obtain a fresh token after re-authenticating.

      Parameters:
      req - the incoming HTTP request
      res - the HTTP response to write to
      Throws:
      IOException - if writing the envelope or reading the body fails