v0.1.7: fix browser login form (multipart vs urlencoded)#5
Merged
Conversation
…d urlencoded
The submit handler in web_auth._HTML_FORM was using:
const formData = new FormData(form);
fetch('/submit?...', { method: 'POST', body: formData });
When fetch sees a FormData body it sets Content-Type to
`multipart/form-data; boundary=...`. The server in _make_handler reads:
body = self.rfile.read(length).decode('utf-8')
form = parse_qs(body)
email = (form.get('email') or [''])[0].strip()
parse_qs only understands application/x-www-form-urlencoded — given a
multipart body it returns an empty dict, so email/password come back
empty and the handler returns 400 "Email and password are required".
This was broken in every release that shipped the browser login form
(0.1.2 through 0.1.6). Nobody hit it earlier because the demos used
the CLI terminal path, and the MCP login_browser tool was always
timed out in chat clients before the user could even click Submit.
Once v0.1.6 made login_browser non-blocking so users could actually
finish the flow, the bug surfaced immediately.
Fix: wrap FormData in URLSearchParams in the JS submit handler, so
fetch sends `application/x-www-form-urlencoded` — which is exactly what
parse_qs expects.
Verified end-to-end: server now parses the credentials and forwards
to the eModul API (returns 401 for fake credentials, which is the
correct downstream behavior).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
The submit handler in `web_auth._HTML_FORM` was sending `multipart/form-data` (default when fetch sees a FormData body), but the server in `_make_handler` parses with `parse_qs` which only understands `application/x-www-form-urlencoded`. Result: every form submission came in with empty email + password, and the server returned 400 "Email and password are required."
Broken in 0.1.2 through 0.1.6. Nobody hit it earlier because:
The fix
Wrap FormData in URLSearchParams in the JS submit handler. fetch then sends `application/x-www-form-urlencoded` — which is exactly what `parse_qs` expects:
```js
const params = new URLSearchParams(new FormData(form));
const resp = await fetch('/submit?state=' + ..., { method: 'POST', body: params });
```
Verified
End-to-end real-server test: simulate a JS form submit with urlencoded body, server now parses fields correctly and forwards to the eModul API (returns 401 for fake credentials, the expected downstream behavior).
Release
After merge: tag v0.1.7 → OIDC publish. Users on 0.1.6 must `pipx upgrade emodul` to use the browser login flow.