jcoffey-dev is traveling from Thursday 1 October through Sunday 4 October. Issues and pull requests are welcome, and will get an answer after that. Thanks for your patience.
Contract C-23. JMAP, /api, /auth/introspect, /auth/userinfo and authenticated /auth/register refuse Authorization: Basic before checking the password, with a Bearer-only 401. A wrong password gets the same answer as the right one. CalDAV/CardDAV keep Basic.
Why: a copy of a front end hosted elsewhere could collect a password and replay it as Basic from its own server. CORS (C-14) and client registration (C-5) don't cover that path.
Bootstrap and recovery mode accept Basic everywhere (like C-16).
INBUXA_HTTP_BASIC_AUTH=all restores it everywhere; dav is the default; any other value logs a warning.
Test builds (test_mode) accept Basic everywhere, since the integration suites sign in with passwords; legacy_protocols.py sets the variable.
Merge order: land ihasmail-inbuxa fix/confirm-password-without-basic and deploy it first. Until then, the webmail's app-password creation checks the password over Basic and would fail.
Tested: unit tests for the paths; tests/e2e/http_basic_auth.py against the debug build, 26/26: refusals and challenges, DAV unaffected, both front ends' sign-in path, token on JMAP/API, the operator switch, recovery mode, and an unregistered redirect refused. cargo check -p tests --tests clean; fork notice/name/privacy checks clean. Not run: the full integration suites, and legacy_protocols.py with the new variable.
Contract C-23. JMAP, `/api`, `/auth/introspect`, `/auth/userinfo` and authenticated `/auth/register` refuse `Authorization: Basic` before checking the password, with a Bearer-only 401. A wrong password gets the same answer as the right one. CalDAV/CardDAV keep Basic.
**Why:** a copy of a front end hosted elsewhere could collect a password and replay it as Basic from its own server. CORS (C-14) and client registration (C-5) don't cover that path.
- Bootstrap and recovery mode accept Basic everywhere (like C-16).
- `INBUXA_HTTP_BASIC_AUTH=all` restores it everywhere; `dav` is the default; any other value logs a warning.
- Test builds (`test_mode`) accept Basic everywhere, since the integration suites sign in with passwords; `legacy_protocols.py` sets the variable.
**Merge order:** land ihasmail-inbuxa `fix/confirm-password-without-basic` and deploy it first. Until then, the webmail's app-password creation checks the password over Basic and would fail.
**Tested:** unit tests for the paths; `tests/e2e/http_basic_auth.py` against the debug build, 26/26: refusals and challenges, DAV unaffected, both front ends' sign-in path, token on JMAP/API, the operator switch, recovery mode, and an unregistered redirect refused. `cargo check -p tests --tests` clean; fork notice/name/privacy checks clean. Not run: the full integration suites, and `legacy_protocols.py` with the new variable.
Anyone could host a copy of a front end on a server of their own,
collect a person's password there, and replay it as HTTP Basic against
JMAP or the API. Cross-origin rules don't stop that, since a server
isn't a browser, and neither does client registration, since Basic
never goes through OAuth (contract C-23).
JMAP (session, API, upload, download, event source, WebSocket), /api,
/auth/introspect, /auth/userinfo and authenticated /auth/register now
refuse an Authorization: Basic header before looking at the password,
with a 401 whose only challenge is Bearer. A wrong password gets the
same answer as the right one. CalDAV and CardDAV keep Basic, and their
401s still offer it. The sign-in page's /api/auth takes the password in
its body and is unaffected, as is the token endpoint's client
authentication.
Bootstrap and recovery mode accept Basic everywhere, as they keep
permissive CORS. INBUXA_HTTP_BASIC_AUTH=all puts it back everywhere;
dav is the default, and any other value logs a warning and keeps it.
Test builds accept Basic everywhere, since the integration suites sign
in with passwords, and legacy_protocols.py sets the variable.
Tested: unit tests for the paths, and tests/e2e/http_basic_auth.py
against the debug build, 26 checks, including both front ends' sign-in
path and a refused unregistered redirect.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Contract C-23. JMAP,
/api,/auth/introspect,/auth/userinfoand authenticated/auth/registerrefuseAuthorization: Basicbefore checking the password, with a Bearer-only 401. A wrong password gets the same answer as the right one. CalDAV/CardDAV keep Basic.Why: a copy of a front end hosted elsewhere could collect a password and replay it as Basic from its own server. CORS (C-14) and client registration (C-5) don't cover that path.
INBUXA_HTTP_BASIC_AUTH=allrestores it everywhere;davis the default; any other value logs a warning.test_mode) accept Basic everywhere, since the integration suites sign in with passwords;legacy_protocols.pysets the variable.Merge order: land ihasmail-inbuxa
fix/confirm-password-without-basicand deploy it first. Until then, the webmail's app-password creation checks the password over Basic and would fail.Tested: unit tests for the paths;
tests/e2e/http_basic_auth.pyagainst the debug build, 26/26: refusals and challenges, DAV unaffected, both front ends' sign-in path, token on JMAP/API, the operator switch, recovery mode, and an unregistered redirect refused.cargo check -p tests --testsclean; fork notice/name/privacy checks clean. Not run: the full integration suites, andlegacy_protocols.pywith the new variable.a742d0cd87tofaf3d1e056