Skip to content

Commit eb66ceb

Browse files
committed
Update password change logic for OAuth accounts
1 parent 7dab2b2 commit eb66ceb

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

accounts/src/main/java/org/restheart/accounts/ChangePasswordService.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
* { "currentPassword": "...", "newPassword": "..." }
3636
* }</pre>
3737
*
38+
* <p>{@code currentPassword} is still required in the request body, but is only verified
39+
* against the stored hash when the account actually has one. Accounts with no password yet
40+
* (e.g. OAuth-only signups) can set their first password through this same endpoint without
41+
* a matching current one to confirm — see the {@code hasPassword} check in {@link #handle}.
42+
*
3843
* <p>Does not invalidate other active sessions/JWTs — out of scope for JWT-based
3944
* auth unless a token-versioning/blacklist mechanism is added separately.
4045
*/
@@ -108,7 +113,15 @@ public void handle(JsonRequest req, JsonResponse res) {
108113
var user = userOpt.get();
109114
var storedHash = user.containsKey("password") && user.get("password").isString()
110115
? user.getString("password").getValue() : null;
111-
if (storedHash == null || !TokenUtils.checkPassword(currentPassword, storedHash)) {
116+
117+
// Accounts that never had a password set (e.g. OAuth-only signups — restheart-accounts
118+
// stores an empty, not null, password field for those) have nothing to confirm here.
119+
// Skipping the check is safe: this endpoint is `secure = true` and always acts on the
120+
// authenticated principal's own document (`email` above comes from
121+
// account.getPrincipal().getName()), never an arbitrary user. Also avoids
122+
// TokenUtils.checkPassword() throwing on an empty/malformed BCrypt hash.
123+
var hasPassword = storedHash != null && !storedHash.isBlank();
124+
if (hasPassword && !TokenUtils.checkPassword(currentPassword, storedHash)) {
112125
Errors.error(res, HttpStatus.SC_UNAUTHORIZED, "Invalid current password");
113126
return;
114127
}

0 commit comments

Comments
 (0)