Closed Bug 2060544 Opened 2 months ago Closed 1 month ago

LibreWolf OAuth browser flow fails (for mailnews.oauth.useExternalBrowser=true): initiates and closes socket before sending actual request to redirect target. Also fails for Firefox with network.lna.allow_top_level_navigation=false

Categories

(Thunderbird :: Account Manager, defect, P2)

Thunderbird 153
defect
Points:
3

Tracking

(Not tracked)

RESOLVED FIXED
156 Branch

People

(Reporter: blacknaughtyreptile, Assigned: jtracey)

References

(Blocks 2 open bugs)

Details

Attachments

(2 files)

Attached file oauth-cap-redacted.txt —

User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:153.0) Gecko/20100101 Firefox/153.0

Steps to reproduce:

Thunderbird 153.0 (Arch Linux, distro package). Default system browser:
LibreWolf 153 (Firefox-based). Fresh Thunderbird profile.

  1. Add a Gmail account (OAuth2, default mailnews.oauth.useExternalBrowser=true).
  2. Browser opens Google consent page; complete login and click Allow.
  3. Google redirects to http://localhost:<port>/?state=...&code=...

Actual results:

Browser shows "Unable to connect" for http://localhost:<port>; Thunderbird
simultaneously reports "Authentication failure while connecting to server
imap.gmail.com". Account cannot be added. Reproduces 100% of attempts.

DIAGNOSIS (tcpdump -i lo on the listener port, capture attached, tokens
redacted): at redirect time the browser opens TWO connections back-to-back:

  1. An empty one: TCP handshake, then immediate FIN, zero payload bytes
    (browser-side speculative/spare connection).
  2. ~130 microseconds later, the real one: plain-HTTP GET /?state=...&code=...
    (correct per RFC 8252).

Thunderbird's listener processes the empty connection first, apparently
treats EOF-without-request as flow failure, and closes the listen socket:
the kernel ACKs the GET on connection 2, then Thunderbird FINs connection 1
and RSTs connection 2 without ever sending an HTTP response. The auth code
is never read. A subsequent browser retry connection is refused.

Verified NOT the cause:

  • Listener binds fine (127.0.0.1, verified via ss) and stays alive for
    minutes if the browser is left idle — no premature timeout.
  • network.http.speculative-parallel-limit=0 in the browser does not
    prevent the empty connection.
  • The GET is plain HTTP even with the browser's HTTPS-Only local-upgrade
    enabled — no TLS involvement.

WORKAROUND: mailnews.oauth.useExternalBrowser=false — embedded flow works
immediately.

Expected results:

The loopback listener receives the auth code and the account is added.

The listener should tolerate connections that close without sending a
request (browser preconnects/spare connections are common), continuing to
listen until a valid request arrives or a real timeout expires. As shipped,
any browser that opens a spare connection at redirect time kills the flow
deterministically.

Thanks for the detailed bug report; this is likely the same bug as bug 2055308 but my diagnosis for that was wrong. The fact LibreWolf is creating this extra TCP connection at all seems like a browser bug to me, since there is no speculative connection requested and they claim to disable them entirely in their features page. Nonetheless, it is probably a good idea to be more flexible in our handling of connections, and hold off on closing the socket until we get an explicit success or failure (or a generous timeout, but that's a separate issue).

Points: --- → 3
Priority: -- → P2
See Also: → 2055308
Summary: OAuth browser flow fails: loopback listener shuts down on empty preconnect connection, auth code redirect gets connection refused → LibreWolf OAuth browser flow fails: initiates and closes socket before sending actual request to redirect target

(In reply to Justin Tracey [:jtracey] from comment #1)

Thanks for the detailed bug report; this is likely the same bug as bug 2055308 but my diagnosis for that was wrong. The fact LibreWolf is creating this extra TCP connection at all seems like a browser bug to me, since there is no speculative connection requested and they claim to disable them entirely in their features page. Nonetheless, it is probably a good idea to be more flexible in our handling of connections, and hold off on closing the socket until we get an explicit success or failure (or a generous timeout, but that's a separate issue).

This is due to us setting network.lna.allow_top_level_navigation to false by default, which would also produce the same problems on Firefox. Setting it to true fixes this issue.

Blocks: tb153found
Summary: LibreWolf OAuth browser flow fails: initiates and closes socket before sending actual request to redirect target → LibreWolf OAuth browser flow fails (for mailnews.oauth.useExternalBrowser=true): initiates and closes socket before sending actual request to redirect target. Also fails for Firefox with network.lna.allow_top_level_navigation=false
Assignee: nobody → jtracey
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true

This allows multiple connections to establish to the listener for the external
browser flow, without failing (or succeeding) until one of them sends \r\n.

Target Milestone: --- → 156 Branch

Pushed by toby@thunderbird.net:
https://hg.mozilla.org/comm-central/rev/d3c239304637
Separate stream from socket in OAuth listener. r=mkmelin

Status: ASSIGNED → RESOLVED
Closed: 1 month ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: