Fix/issue 82 oauth callback flow - #351
Open
Adeyemiadigun wants to merge 2 commits into
Open
Adeyemiadigun wants to merge 2 commits into
Adeyemiadigun wants to merge 2 commits into
Conversation
A token endpoint that answers with a non-dict body (`null` or a list, e.g. from a gateway) raised AttributeError and returned a 500. Normalize it so a malformed body degrades to the friendly failure path. Also stop flashing the raw upstream body: only GitHub's own error and error_description are surfaced to the user, while the raw body is truncated and logged server-side.
Drive GET /github/callback end to end with the token exchange and the /user verification mocked at the requests layer. Success asserts the authorization code is exchanged with the app credentials and that the stored access token is ciphertext which round-trips through decrypt_secret, with the plaintext never reaching the browser. Failure paths (state mismatch, missing code, GitHub error responses, a rejected user lookup) each assert a friendly redirect back to the dashboard, a readable flash, and that no client secret, access token, or raw upstream error body leaks into the page.
|
@Adeyemiadigun Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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.
Summary
Adds integration coverage for the full
/github/callbackOAuth flow with thetoken exchange and/userverification mocked at therequestslayer, andhardens the callback's token-error path so a malformed upstream response can no
longer 500 or echo a raw body back to the user.
Linked issue
Closes #82
Changes
tests/test_github_routes.py— newTestOAuthCallbackFlowclass (8 tests)covering success, state mismatch, missing code, and GitHub error responses
(
?error=, a 4xx token body, a non-JSON body, a non-dict body, and a rejecteduser lookup). Added shared doubles/helpers:
FakeHTMLResponse,_flashes,_forbid_token_exchange,_token_exchange,_assert_no_error_leakage, and asessions=hook on_make_fake_sessionso tests can assert the
Authorizationheader used for/user.app/github/routes.py— normalize a non-dict token body (null/list froma gateway) to
{}so it degrades to the friendly redirect instead of raisingAttributeErrorand returning a 500; and stop flashing the raw upstream body. Only GitHub's ownerror/error_descriptionare surfaced now — theraw body is truncated to 200 chars and logged server-side.
Validation
pytestpasses — partially. The8 new tests pass andtests/test_github_routes.pyis 41/41green. The full suite is 1865 passed / 37 failed, but all 37 failures are in
tests/test_migrations.pyand reproduce identically on a cleanmainworktree, so they are pre-existing and unrelated (see Notes).
ruff check .passesblack --check .passesNotes for reviewers
app/github/routes.pychange is a behavior fix, not a test. It is splitinto its own commit (
6d82c21) so it can be reviewed or split into a separatePR. It is required for the "no error leakage" criterion to actually hold:
with only the tests applied, 2 of the 8 fail — the raw gateway HTML was rendered
to the user, and the
nullbody 500'd. The other 6 are regression guards overbehavior that already worked.
GitHub's own
error_description(e.g. "The code passed is incorrect orexpired.") since that is a user-facing OAuth string. The tests assert the
machine-readable code is not shown and that no client secret, access token, or
internal marker (
Traceback,GitHubError,RequestException) reaches the page.statestill passes thecheck, because
routes.py:109comparesNone != None. A callback carrying acodewith nostateparam and no session state will exchange and persist aconnection. The guard only rejects a mismatched state, not a missing one, so
the CSRF protection the parameter exists for is weaker than intended. Worth its
own issue.
tests/test_migrations.pyfails 37/37 with
Multiple head revisions are present. Cause is threemigrations sharing
down_revision = 'd8e9f0a1b2c3'—91a2b3c4d5e6(
add_secure_conversation_share_links),91a2b3c4d5e7(add_team_prompt_scope),and
91a2b3c4d5e8(add_file_analysis_history) — which forks the graph intothree heads. Unrelated to this change; needs a merge migration.
.venvwas empty/broken, so it wasrebuilt with Python 3.12 (matching the project's
target-version = "py312") andrequirements-dev.txt..venv/is gitignored, so it is not part of the diff.