Skip to content

Conversation

@marekharanczyk
Copy link
Contributor

@marekharanczyk marekharanczyk commented May 20, 2021

Description of Change

If connecting via proxy, preflight request can receive 407 header response from proxy. This does not mean request was finished even though it received headers (from proxy, not the destination server), so prevent "completing" and most importantly deleting it, which causes request to be canceled in network layer. Just continue to monitor it and await proper response from server. Also add circuit breaker to cancel request if proxy auth failed 3 times (for example user keeps cancelling auth). This behavior happens only when app registered WebRequest api listeners.

Fixes #25184
Fixes #25758

Checklist

Release Notes

Notes: Fixed CORS preflight request always being cancelled when connecting via proxy requiring authentication for apps that had registered WebRequest listeners.

@electron-cation electron-cation bot added the new-pr 🌱 PR opened recently label May 20, 2021
@marekharanczyk
Copy link
Contributor Author

This PR fixes the problem described in #29265

If connecting via proxy, preflight request can receive 407
header response from proxy. This does not mean request
was finished even though it received headers (from proxy,
not the destination server), so prevent "completing"
and most importantly deleting it, which causes request
to be canceled in network layer. Just continue to monitor it
and await proper response from server. Also add circut breaker
to cancel request if proxy auth failed 3 times (for example
user keeps cancelling auth). This behavior happens only
when app registered WebRequest api listeners.
@marekharanczyk
Copy link
Contributor Author

Marked issue is a duplicate of #25758.

Copy link
Contributor

@nornagon nornagon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marekharanczyk
Copy link
Contributor Author

I've already reported https://chromium-review.googlesource.com/c/chromium/src/+/2910336 to chromium, which is similar change in their code.
This change is necessary because electron always sets "extraHeader" mode for WebRequests api. When connection is established through proxy requiring auth, 407 response is received from proxy to force client to authenticate itself with proxy. Extension/electron code assumed that any response that is received for CORS preflight (HTTP OPTIONS) completes the requests, but for proxy auth case, request is not yet finished, so it should be kept alive to allow network service to start authentication process. Deleting preflight request immediately after receiving 407 caused it to be cancelled, causing original request to be cancelled as well, making CORS unusable and breaking pages by rpeventing resource loads.
The only difference between CL and this PR is to provide failsafe and abort the request after 3 auth attempts to prevent unintentional infinite auth request loop. Authentication hooks in electron are different from chromium auth code and UI.

Copy link
Contributor

@zcbenz zcbenz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm good with this change, but we should wait for how Chromium reviewers say before merging.

@zcbenz zcbenz added semver/patch backwards-compatible bug fixes target/12-x-y labels May 25, 2021
@electron-cation electron-cation bot removed the new-pr 🌱 PR opened recently label May 25, 2021
@lukeapage
Copy link
Contributor

Amazing this is being fixed now. I’ve received the issue intermittently in chrome too where by I have to reset my settings and it goes away - I can only guess something in my setup pushes chrome into this extra header mode.

@miniak
Copy link
Contributor

miniak commented Jun 11, 2021

@miniak
Copy link
Contributor

miniak commented Jun 11, 2021

@marekharanczyk looks like we should also include https://chromium-review.googlesource.com/c/chromium/src/+/2011781
I hit the DCHECK when testing the fix with our repro

@marekharanczyk
Copy link
Contributor Author

@miniak The retry check is because electron does not have same handling of auth that chromium has, just a safety measure to prevent infinite loop. I can remove it if it bothers you. Regarding second chromium fix you pointed: I will move it as well.

Move relevant parts of chromium WebRequestProxyingURLLoaderFactory from
https://chromium-review.googlesource.com/c/chromium/src/+/2011781
into electron ProxyingURLLoaderFactory.
@miniak
Copy link
Contributor

miniak commented Jun 11, 2021

@marekharanczyk I was mostly just wondering why the fix is different between Chromium and Electron. If you believe the retry limit makes sense we can keep it.

@marekharanczyk
Copy link
Contributor Author

Updated code to final version that just got merged upstream and removed fail safe.

@jkleinsc jkleinsc requested a review from nornagon June 14, 2021 13:42
// CorsURLLoader::FollowRedirect. In such a case the old network::URLLoader
// is going to be detached fairly soon, so we don't need to take care of it.
// We need this explicit reset to avoid a DCHECK failure in mojo::Receiver.
header_client_receiver_.reset();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this .reset() needed given we immediately .Bind() on the next line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a cherry-pick of https://chromium-review.googlesource.com/c/chromium/src/+/2011781. Reason for reset is stated above in comment by original author, it is here to prevent DCHECK in mojo receiver.

@nornagon
Copy link
Contributor

11.x is security fixes only now.

@nornagon nornagon removed the semver/patch backwards-compatible bug fixes label Jun 17, 2021
@VerteDinde VerteDinde added semver/none semver/patch backwards-compatible bug fixes and removed semver/none labels Jun 17, 2021
@zcbenz zcbenz merged commit 507cbdc into electron:main Jun 21, 2021
@release-clerk
Copy link

release-clerk bot commented Jun 21, 2021

Release Notes Persisted

Fixed CORS preflight request always being cancelled when connecting via proxy requiring authentication for apps that had registered WebRequest listeners.

trop bot pushed a commit that referenced this pull request Jun 21, 2021
* fix: do not cancel CORS preflight request on proxy auth.

If connecting via proxy, preflight request can receive 407
header response from proxy. This does not mean request
was finished even though it received headers (from proxy,
not the destination server), so prevent "completing"
and most importantly deleting it, which causes request
to be canceled in network layer. Just continue to monitor it
and await proper response from server. Also add circut breaker
to cancel request if proxy auth failed 3 times (for example
user keeps cancelling auth). This behavior happens only
when app registered WebRequest api listeners.

* Port chromium webrequest changes to electron code.

Move relevant parts of chromium WebRequestProxyingURLLoaderFactory from
https://chromium-review.googlesource.com/c/chromium/src/+/2011781
into electron ProxyingURLLoaderFactory.

* Update code to upstreamed version and remove retyr count failsafe.

Co-authored-by: Milan Burda <milan.burda@gmail.com>
trop bot pushed a commit that referenced this pull request Jun 21, 2021
* fix: do not cancel CORS preflight request on proxy auth.

If connecting via proxy, preflight request can receive 407
header response from proxy. This does not mean request
was finished even though it received headers (from proxy,
not the destination server), so prevent "completing"
and most importantly deleting it, which causes request
to be canceled in network layer. Just continue to monitor it
and await proper response from server. Also add circut breaker
to cancel request if proxy auth failed 3 times (for example
user keeps cancelling auth). This behavior happens only
when app registered WebRequest api listeners.

* Port chromium webrequest changes to electron code.

Move relevant parts of chromium WebRequestProxyingURLLoaderFactory from
https://chromium-review.googlesource.com/c/chromium/src/+/2011781
into electron ProxyingURLLoaderFactory.

* Update code to upstreamed version and remove retyr count failsafe.

Co-authored-by: Milan Burda <milan.burda@gmail.com>
trop bot pushed a commit that referenced this pull request Jun 21, 2021
* fix: do not cancel CORS preflight request on proxy auth.

If connecting via proxy, preflight request can receive 407
header response from proxy. This does not mean request
was finished even though it received headers (from proxy,
not the destination server), so prevent "completing"
and most importantly deleting it, which causes request
to be canceled in network layer. Just continue to monitor it
and await proper response from server. Also add circut breaker
to cancel request if proxy auth failed 3 times (for example
user keeps cancelling auth). This behavior happens only
when app registered WebRequest api listeners.

* Port chromium webrequest changes to electron code.

Move relevant parts of chromium WebRequestProxyingURLLoaderFactory from
https://chromium-review.googlesource.com/c/chromium/src/+/2011781
into electron ProxyingURLLoaderFactory.

* Update code to upstreamed version and remove retyr count failsafe.

Co-authored-by: Milan Burda <milan.burda@gmail.com>
@trop
Copy link
Contributor

trop bot commented Jun 21, 2021

I have automatically backported this PR to "12-x-y", please check out #29810

@trop
Copy link
Contributor

trop bot commented Jun 21, 2021

I have automatically backported this PR to "13-x-y", please check out #29811

@trop
Copy link
Contributor

trop bot commented Jun 21, 2021

I have automatically backported this PR to "14-x-y", please check out #29812

zcbenz added a commit that referenced this pull request Jun 21, 2021
* fix: do not cancel CORS preflight request on proxy auth. (#29266)

* fix: do not cancel CORS preflight request on proxy auth.

If connecting via proxy, preflight request can receive 407
header response from proxy. This does not mean request
was finished even though it received headers (from proxy,
not the destination server), so prevent "completing"
and most importantly deleting it, which causes request
to be canceled in network layer. Just continue to monitor it
and await proper response from server. Also add circut breaker
to cancel request if proxy auth failed 3 times (for example
user keeps cancelling auth). This behavior happens only
when app registered WebRequest api listeners.

* Port chromium webrequest changes to electron code.

Move relevant parts of chromium WebRequestProxyingURLLoaderFactory from
https://chromium-review.googlesource.com/c/chromium/src/+/2011781
into electron ProxyingURLLoaderFactory.

* Update code to upstreamed version and remove retyr count failsafe.

Co-authored-by: Milan Burda <milan.burda@gmail.com>

* chore: add required header

Co-authored-by: marekharanczyk <48673767+marekharanczyk@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
zcbenz added a commit that referenced this pull request Jun 21, 2021
* fix: do not cancel CORS preflight request on proxy auth. (#29266)

* fix: do not cancel CORS preflight request on proxy auth.

If connecting via proxy, preflight request can receive 407
header response from proxy. This does not mean request
was finished even though it received headers (from proxy,
not the destination server), so prevent "completing"
and most importantly deleting it, which causes request
to be canceled in network layer. Just continue to monitor it
and await proper response from server. Also add circut breaker
to cancel request if proxy auth failed 3 times (for example
user keeps cancelling auth). This behavior happens only
when app registered WebRequest api listeners.

* Port chromium webrequest changes to electron code.

Move relevant parts of chromium WebRequestProxyingURLLoaderFactory from
https://chromium-review.googlesource.com/c/chromium/src/+/2011781
into electron ProxyingURLLoaderFactory.

* Update code to upstreamed version and remove retyr count failsafe.

Co-authored-by: Milan Burda <milan.burda@gmail.com>

* chore: add required header

Co-authored-by: marekharanczyk <48673767+marekharanczyk@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
@trop trop bot added the merged/12-x-y label Jun 21, 2021
zcbenz added a commit that referenced this pull request Jun 21, 2021
* fix: do not cancel CORS preflight request on proxy auth. (#29266)

* fix: do not cancel CORS preflight request on proxy auth.

If connecting via proxy, preflight request can receive 407
header response from proxy. This does not mean request
was finished even though it received headers (from proxy,
not the destination server), so prevent "completing"
and most importantly deleting it, which causes request
to be canceled in network layer. Just continue to monitor it
and await proper response from server. Also add circut breaker
to cancel request if proxy auth failed 3 times (for example
user keeps cancelling auth). This behavior happens only
when app registered WebRequest api listeners.

* Port chromium webrequest changes to electron code.

Move relevant parts of chromium WebRequestProxyingURLLoaderFactory from
https://chromium-review.googlesource.com/c/chromium/src/+/2011781
into electron ProxyingURLLoaderFactory.

* Update code to upstreamed version and remove retyr count failsafe.

Co-authored-by: Milan Burda <milan.burda@gmail.com>

* chore: add required header

Co-authored-by: marekharanczyk <48673767+marekharanczyk@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
@trop trop bot removed the in-flight/12-x-y label Jun 21, 2021
BlackHole1 pushed a commit to BlackHole1/electron that referenced this pull request Aug 30, 2021
)

* fix: do not cancel CORS preflight request on proxy auth.

If connecting via proxy, preflight request can receive 407
header response from proxy. This does not mean request
was finished even though it received headers (from proxy,
not the destination server), so prevent "completing"
and most importantly deleting it, which causes request
to be canceled in network layer. Just continue to monitor it
and await proper response from server. Also add circut breaker
to cancel request if proxy auth failed 3 times (for example
user keeps cancelling auth). This behavior happens only
when app registered WebRequest api listeners.

* Port chromium webrequest changes to electron code.

Move relevant parts of chromium WebRequestProxyingURLLoaderFactory from
https://chromium-review.googlesource.com/c/chromium/src/+/2011781
into electron ProxyingURLLoaderFactory.

* Update code to upstreamed version and remove retyr count failsafe.

Co-authored-by: Milan Burda <milan.burda@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver/patch backwards-compatible bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Every CORS (preflight) request fails when behind a proxy and listener attached Second socket on a session does not send Proxy-Authenticate for ntlm

6 participants