Shuzheng
Shuzheng

Reputation: 13996

Why does HTTP Basic Auth works using `git -c http.extraHeader="Authorization: Basic <base64>"`, but not when putting credentials directly in the URL?

I've the following "dummy" credentials (username and PAT) for accessing a repository:

bd6164:o6g5xae5fmqeqdbjatdfjichdk55lweq4jxyt2jvwtjuzxdwwgxa

Now, according to MS documentation, I should supply these credentials to git using git -c http.extraHeader="Authorization: Basic <base64>" ..., which results in successful authentication.

However, if I supply these credentials to git directly in the URL:

https://bd6164:o6g5xae5fmqeqdbjatdfjichdk55lweq4jxyt2jvwtjuzxdwwgxa@azuredevops.example.net

then authentication fails.

Normally, when I use git, I can put my credentials directly in the URL for successful authentication, so why do I experience these inconsistencies? In general, aren't credentials in the URL converted to Base64 and sent in a "Authorization: Basic" HTTP header?

Here is the documentation from MS on how to use PAT with git:

https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page#use-a-pat

Works:

# git -c http.extraHeader="Authorization: Basic YmQ2MTY0Om82ZzV4YWU1Zm1xZXFkYmphdGRmamljaGRrNTVsd2VxNGp4eXQyanZ3dGp1enhkd3dneGE=" clone https://azuredevops.example.net/Main/MyProj/_git/MyRepo

Fails:

# git clone https://bd6164:o6g5xae5fmqeqdbjatdfjichdk55lweq4jxyt2jvwtjuzxdwwgxa@azuredevops.example.net/Main/MyProj/_git/MyRepo

Upvotes: 9

Views: 20278

Answers (2)

VonC
VonC

Reputation: 1326932

Before Git 2.34 (Q4 2021), sensitive data in the HTTP trace were supposed to be redacted, but we failed to do so in HTTP/2 requests.

See commit b66c77a (22 Sep 2021) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 58e2bc4, 03 Oct 2021)

http: match headers case-insensitively when redacting

Signed-off-by: Jeff King

When HTTP/2 is in use, we fail to correctly redact "Authorization" (and other) headers in our GIT_TRACE_CURL output.

We get the headers in our CURLOPT_DEBUGFUNCTION callback, curl_trace().
It passes them along to curl_dump_header(), which in turn checks redact_sensitive_header().
We see the headers as a text buffer like:

Host: ...
Authorization: Basic ...

After breaking it into lines, we match each header using skip_prefix().
This is case-sensitive, even though HTTP headers are case-insensitive.
This has worked reliably in the past because these headers are generated by curl itself, which is predictable in what it sends.

But when HTTP/2 is in use, instead we get a lower-case "authorization:" header, and we fail to match it.
The fix is simple: we should match with skip_iprefix().

There's one other way to demonstrate the issue (and how I actually found it originally).
Looking at GIT_TRACE_CURL output against github.com, you'll see the unredacted output, even if you didn't set http.version.
That's because setting it is only necessary for curl to send the extra headers in its HTTP/1.1 request that say "Hey, I speak HTTP/2; upgrade if you do, too".
But for a production site speaking https, the server advertises via ALPN, a TLS extension, that it supports HTTP/2, and the client can immediately start using it.

Upvotes: 5

LeGEC
LeGEC

Reputation: 51988

It looks like an issue with the interaction of git, git credential manager, and a server announcing it supports NTLM.

Found in this issue on github :

  • OP says he fixed the issue by manually setting login/password for the target domain in his credentials manager,
  • maintainer suggests to also try setting git config credential.authority basic in git config

Upvotes: 1

Related Questions