Conversation
GET /auth/verify used to mark the magic-link token used and sign in whoever fetched it. Mail scanners, click trackers and link previews fetch links automatically, so they were signed in and the real user saw "Link expired". - GET /auth/verify now only renders a confirmation page. Sign-in moves to POST /auth/verify. - The token is claimed with a conditional update, so a link cannot be redeemed twice, and the claim is released if the session cannot be created, so a failed sign-in no longer burns the link. - SessionMiddleware no longer overwrites a session cookie the route has already set. It re-set the cookie to the temporary session that signing in a returning user had just deleted, leaving them signed out. - The auth funnel counts only POSTs to /auth/verify as verifications, since opening a link is now a separate GET. Fixes GenAI-Security-Project#582 Fixes GenAI-Security-Project#583 Refs GenAI-Security-Project#541
Contributor
Author
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.
GET /auth/verify used to mark the magic-link token used and sign in whoever fetched it. Mail scanners, click trackers and link previews fetch links automatically, so they were signed in and the real user saw "Link expired".
Fixes #582
Fixes #583
Refs #541
Summary
Fixes two magic-link sign-in bugs:
GET /auth/verifymarked the token used and signed in whoever fetched it. Mail scanners, click trackers and link previews fetch links automatically, so on an account's first sign-in they were signed in, and the real user saw "Link expired"./portalsbut left signed out; the middleware overwrites their new session cookie with the temp session sign-in just deleted #583 — a returning user who opened the link in a different browser was redirected to/portalsbut left signed out, because the middleware overwrote the new session cookie with the temporary session that sign-in had just deleted.Changes
finbot/apps/finbot/auth.pyGET /auth/verifynow only renders a confirmation page. Sign-in moves toPOST /auth/verify. The token is claimed with a conditional update so a link can't be redeemed twice, and the claim is released if the session can't be created, so a failed sign-in no longer burns the link. The session-selection logic is unchanged.finbot/apps/finbot/templates/auth-confirm.htmlauth-error.html.finbot/core/auth/middleware.pyfinbot/core/analytics/queries.pyPOST /auth/verifyas verifications; opening a link is now a separate GET.tests/integration/auth/test_magic_link_verify.pyTesting
Automated —
tests/integration/auth/test_magic_link_verify.py, 12 tests:mainEvery test uses a freshly generated email address, and every retry uses a separate client. A same-client retry is short-circuited by
_is_authenticated, and reused addresses take the returning-user path, both of which hide these bugs.Full suite: 325 passed, 3 failed. The same 3 fail on
main(tests/unit/agents/test_specialized_agents.py).Manual, in two browsers against a local server:
curlfirst, then opened by the usercurlgets303and a session; user sees "Link expired"curlgets the confirmation page; user signs inSet-CookieheadersSet-Cookie(Max-Age=1209600)Notes for reviewers
/portalsbut left signed out; the middleware overwrites their new session cookie with the temp session sign-in just deleted #583 no longer triggers there on its own. The middleware change still matters when the submit arrives without a session — cookies cleared, or the session expired in between — which is whattest_returning_user_signs_in_when_the_submit_has_no_sessioncovers.