[squeak-dev] Missing auth headers in WebClient request (was: Squot and Github)

Jakob Reschke forums.jakob at resfarm.de
Mon Jul 20 13:19:52 UTC 2020

The authParams variable of WebClient contains a Dictionary that holds
associations for #authMethod, #authRealm, #authResponse, #username,

flushAuthState only removes #authMethod, to the effect that on the
next HTTP 401/407 response the authentication methods are dispatched
again (which is good). If #authMethod remained, all the authentication
methods would assume that a previous method has already supplied
credentials. Since each new WebRequest is not supplied with the
Authorization headers proactively, each new request dispatches again
with an additional round of 401 (which is not optimal, but

#authResponse is removed for each new dispatch of the authentication
methods. If a method matches the challenge in the 401 response, the
method will put a new #authResponse. The basic authentication method
writes an #authResponse if it matches the challenge and finds
#username and #password in the dictionary.

#username and #password seem to never be removed in the code. You can
set them with WebClient>>username: and password:, or by handling the
WebAuthRequired exception. Yet sometimes they appear to be missing
because eventually/sometimes the WebClient does not put new
Authorization headers to repeat the request, and instead returns the
401 response.

Actually I don't see how in WebClient>>#authenticate:from: the code
"The other possibility is that the credentials are wrong. [...]" can
ever be reached if the WebClient is supplied with username: and
password: from outside before the request or after the first 401. Is
the comment wrong and should instead read "The other possibility is
that credentials were not supplied yet. [...]"? I assume that wrong
credentials should be handled by the code that uses the WebClient, in
response to a HTTP 401 response. Or is there a problem in the logic,
or how can this be reached with wrong credentials?

My Git push code does not handle WebAuthRequired, instead checks for
401 responses, then sets username: and password: on the WebClient,
then repeats the request (actually the WebClient creates a new
WebRequest). This is all done for the first URL accessed during a Git
push. For the second URL, the same WebClient is used (so it should
still have #username and #password) and further 401 responses are
simply wrapped in an exception and signalled without further retry
logic. Is this sound or do you have any remarks about this? It looks
like I could avoid the extra 401 round for the first URL by handling
WebAuthRequired instead of the 401 response. But not for the second
URL, where the failure sometimes occurs.

A different issue: #authRealm seems to be mostly ignored by the
WebClient (it is remembered in the dictionary, but not used
afterwards). That means that a single WebClient used to talk to
different realms of a site or to multiple sites would simply send/leak
the same credentials to all the sites, doesn't it?

Am Sa., 11. Juli 2020 um 15:32 Uhr schrieb Levente Uzonyi
<leves at caesar.elte.hu>:
> On Sat, 11 Jul 2020, Jakob Reschke wrote:
> > Hi all,
> >
> > Am Sa., 11. Juli 2020 um 13:53 Uhr schrieb Eric Gade <eric.gade at gmail.com>:
> >>
> >>> Could you please inspect whether the `response request` actually
> >>> contains authentication headers? I have seen in the past that
> >>> sometimes the WebClient does not send them when it should.
> >>
> >>
> >> It looks to me like the WebClient's response request (the original request sent I assume) headers *don't* have any Auth information: ` 'an OrderedCollection(''Content-Type''->''application/x-git-receive-pack-request'' ''Content-Length''->5343 ''User-Agent''->''git/2.0.5'' ''Host''->''github.com'')'`
> >>
> >
> > To me these missing auth headers look like a WebClient bug because the
> > GitSmartHTTPProtocol class (comes with the Git Browser) clearly
> > supplies the credentials to the client (see
> > discoverReferencesForService:, requestCredentials, applyCredentials)
> > and uses the same WebClient instance for the whole push operation,
> > which entails two requests (discover references is the first, invoke
> > receive pack is the second).
> >
> > If the misbehavior triggers, the second request is usually the one
> > that is missing the auth headers. I have already seen this
> > sporadically myself, but not lately. Repeating the request (by
> > restarting the method) usually resolves the problem.
> >
> > Does anyone have a hint? It is possible that I have wrong expectations
> > about the WebClient interface and how it remembers the credentials...
> Perhaps this part of WebClient >> #sendRequest:contentBlock: is
> responsible:
>         "Flush previous authState.
>         XXXX: Fixme. authState must be preserved for pre-authentication of requests."
>         self flushAuthState.
> #flushAuthState removes the passed credentials.
> Also, any kind of redirect will remove the credentials.
> Levente
> >
> > Kind regards,
> > Jakob

More information about the Squeak-dev mailing list