Confirm a typed password without replaying it over JMAP #30

Merged
jcoffey-dev merged 1 commits from fix/confirm-password-without-basic into main 2026-09-29 17:03:54 +00:00
Owner

Creating an app password on a token session checked the typed password by sending it as Basic to /jmap/session. inbuxa-server now refuses Basic outside DAV (server contract C-23), so it would always fail.

It now asks the server's sign-in endpoint (/api/auth) as this client, to its registered redirect URI, with a PKCE challenge whose verifier is discarded, so the code can't be exchanged. mfaRequired counts as confirmed because the server only returns it after the password matched, so accounts with two-factor sign-in now pass too.

The mock answers /api/auth and can refuse Basic on JMAP; the app-password test turns that on and fails on the old check.

Tested: server tests 271/271; typecheck and server build clean. The server-side call itself is covered by inbuxa-server's tests/e2e/http_basic_auth.py, which makes the same request as ihasmail-inbuxa (authenticated / failure / foreign redirect refused). No user-visible strings added.

Merge before inbuxa-server feature/http-basic-dav-only, and deploy before rolling that server release out.

Creating an app password on a token session checked the typed password by sending it as Basic to `/jmap/session`. inbuxa-server now refuses Basic outside DAV (server contract C-23), so it would always fail. It now asks the server's sign-in endpoint (`/api/auth`) as this client, to its registered redirect URI, with a PKCE challenge whose verifier is discarded, so the code can't be exchanged. `mfaRequired` counts as confirmed because the server only returns it after the password matched, so accounts with two-factor sign-in now pass too. The mock answers `/api/auth` and can refuse Basic on JMAP; the app-password test turns that on and fails on the old check. **Tested:** server tests 271/271; typecheck and server build clean. The server-side call itself is covered by inbuxa-server's `tests/e2e/http_basic_auth.py`, which makes the same request as `ihasmail-inbuxa` (authenticated / failure / foreign redirect refused). No user-visible strings added. **Merge before** inbuxa-server `feature/http-basic-dav-only`, and deploy before rolling that server release out.
jcoffey-dev added 1 commit 2026-09-29 13:50:56 +00:00
Confirm a typed password without replaying it over JMAP
ci / version (pull_request) Skipped
ci / node (pull_request) Successful in 1m5s
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
ci / docker-build (pull_request) Successful in 35s
1acf2f29e7
Creating an app password asks for the account password. A session
holding a token has no password to compare with, so it sent the typed
one to the mail server as HTTP Basic on the JMAP session. INBUXA's
server now takes no password outside DAV (contract C-23), so that check
would always fail.

It now asks the server's sign-in endpoint, the one its own sign-in page
posts to, as this client, to its registered redirect URI, with a PKCE
challenge whose verifier is thrown away so the code can never be
exchanged. "Two-factor code needed" counts as confirmed: the server
says so only after the password matched, so accounts with two-factor
sign-in now pass where the Basic check failed them.

The mock answers /api/auth like the server and can refuse Basic on
JMAP; the app-password test turns that on, and fails on the old check.
jcoffey-dev merged commit 829e46beae into main 2026-09-29 17:03:54 +00:00
jcoffey-dev deleted branch fix/confirm-password-without-basic 2026-09-29 17:03:54 +00:00
Sign in to join this conversation.