A note about Chrome and proxying requests to localhost
Weirdly specific, right?
I recently stumbled upon this scenario: I have a web app - Vue client, RoR backoffice + API - running on (sighs) Azure. We use Azure Easy Auth to authenticate our users, either with AAD (Azure Active Directory) or Google. My goal was testing the access given to users depending on whether they were accessing with one provider or the other, and other constraints around that.
Now, besides adding cookies and headers to your requests, Azure Easy Auth provides a few endpoints of their own. For example, if you access
/.auth/login/google, and assuming you have correctly set up Google oauth client ID/secret in your application, you’re redirected to a login page to choose your Google account. If you access
/.auth/me, and if you are logged in, you have access to some information like your current user ID, an ID token in the form of a JWT, and some other information (some of which may be configured on Azure).
The outcome of visiting
/.auth/me when authenticated. I don’t trust any single person reading this, so I blurred the tokens and cropped part of the image. Just in case.
For some of my tests, I wanted to see what would happen when the client is presented with different outputs by accessing the
/.auth/me endpoint. This endpoint is managed by Azure, so I thought it wouldn’t make sense to write a controller on my app and manipulate the output of that controller. I tried to find a way to proxy my requests like Azure does, and make sure requests to this endpoint wouldn’t even reach my server at all.
An over-simplified diagram of how the
/.auth endpoints work
We were already using a gem called Puffing Billy to simulate the responses from other (external) endpoints, so I tried using it. It’s quite easy to define stubs with this gem, so I thought for once I would be able to do something easily on my first try. As you may have guessed by now, this was not the case.
The requests were returning a
404 because the route was not defined in my server. I checked if I was setting the gem up correctly, I checked if the proxy was active before the test started, I checked a few hundred times if I had the right path in the stub, I tried proxying external URLs (successfully), I added debug logs and incantations, I even considered the sheer madness of skipping these tests for the time being.
Fast forward a few hours, a thousand test runs, a dozen punches on the wall and three coffees, and I stumbled upon this StackExchange thread, and consequently this thread on the Chromium bug tracker. If you don’t want to go through those links, the gist is:
“Since 2018, the chromium engine implicitly bypasses localhost when proxying requests”
To put it even more simply, “You want to proxy requests to localhost? Nope.” However, they obviously didn’t want to remove that option completely, so they also present the alternative that makes it work:
When using Chrome (or a chromium-based browser), to proxy requests to localhost, add the flag
--proxy-bypass-list=<-loopback> (or add
<-loopback> to an existing list of proxy bypasses) when starting the browser.
That’s it. My requests started working as expected, I spent way longer than if I had just written a controller and changed its response values for the tests, and I’m now writing a 3-volume essay on how to make it work consistently on both my computer and the CI server.
Is this a common issue? More importantly, is this a known solution? Let me know.