Is it possible to authenticate to a remote Git repository using the default windows credentials non interactively?

Viewed 1464

My remote Git repository is hosted by the on premises TFS server. There are two ways to access its content:

To use the Restful API one can use the powershell Invoke-RestMethod command with the -UseDefaultCredentials and it works fine, no questions asked.

With git clone, however, I have no idea how to use the default credentials. The manager credential helper does not use them. When used for the first time it asks for the credentials.

So, the options I see are:

  • There an alternative git client, maybe with a limited functionality, but good enough to run clone that can use the default windows credentials.
  • There is a credential helper for windows that can use the default windows credentials.
  • There is an askpass implementation for windows that can use the default windows credentials.

The problem is that I could not find anything on the web that implements any of these options.

Edit 1

The approach suggested in https://github.com/git-for-windows/git/wiki/FAQ#how-do-i-access-a-repository-hosted-on-a-microsoft-team-foundation-server-inside-a-windows-domain does not seem to work. Please, observe:

C:\xyz\DevOps> $GitApiUrl
http://tfsserver:8080/tfs/DefaultCollection/code/_apis/git/repositories/MyConfigData
C:\xyz\DevOps> $ProjectName
dev_smoketest56oc
C:\xyz\DevOps> Test-Path .\params.json
False
C:\xyz\DevOps> Invoke-RestMethod -Uri "$GitApiUrl/items?path=$ProjectName.json&api-version=4.1" -UseDefaultCredentials -OutFile params.json
C:\xyz\DevOps> Test-Path .\params.json
True

As you can see the Restful API works without asking for credentials. Now let us try git clone:

C:\xyz\DevOps> $env:GIT_TRACE=1
C:\xyz\DevOps> git clone http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp a
09:13:21.405748 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/bin
09:13:21.406249 git.c:415               trace: built-in: git clone http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp a
Cloning into 'a'...
09:13:21.430369 run-command.c:637       trace: run_command: git remote-http origin http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp
09:13:21.459149 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
09:13:21.460654 git.c:654               trace: exec: git-remote-http origin http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp
09:13:21.460654 run-command.c:637       trace: run_command: git-remote-http origin http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp
09:13:21.481711 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
09:13:21.539575 run-command.c:637       trace: run_command: 'git credential-manager erase'
09:13:21.642660 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
09:13:21.644162 git.c:654               trace: exec: git-credential-manager erase
09:13:21.644162 run-command.c:637       trace: run_command: git-credential-manager erase
fatal: Authentication failed for 'http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp/'
C:\xyz\DevOps> $env:GIT_TRACE=0
C:\xyz\DevOps>

Authentication failed.

Edit 2

On the bash console:

$ GIT_CURL_VERBOSE=1

$ curl -v --ntlm -u : http://tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp -o 1.html 2> out.txt

$ curl -v --ntlm -u : http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp -o 2.html 2> out2.txt

The files 1.html and 2.html seem to represent the web page of the repository as in the browser, so both curl commands are successful.

The output files out.txt and out2.txt are very similar, the differences are in timestamps, guids and crypto strings. So, here is out.txt (I took the liberty to remove empty lines and scrub a few strings):

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 192.168.17.155...* TCP_NODELAY set* Connected to tfsserver (192.168.17.155) port 8080 (#0)* Server auth using NTLM with user ''> GET /tfs/DefaultCollection/code/_git/MyApp HTTP/1.1
> Host: tfsserver:8080
> Authorization: NTLM ***SCRUBBED***
> User-Agent: curl/7.60.0
> Accept: */*
> 
< HTTP/1.1 401 Unauthorized
< Content-Type: text/html; charset=us-ascii
< Server: Microsoft-HTTPAPI/2.0
< WWW-Authenticate: NTLM ***SCRUBBED***
< Date: Thu, 15 Nov 2018 23:07:58 GMT
< Content-Length: 341
< 
* Ignoring the response-body{ [341 bytes data]
100   341  100   341    0     0    642      0 --:--:-- --:--:-- --:--:--   642* Connection #0 to host tfsserver left intact* Issue another request to this URL: 'http://tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp'* Found bundle for host tfsserver: 0x4116f20 [can pipeline]* Re-using existing connection! (#0) with host tfsserver* Connected to tfsserver (192.168.17.155) port 8080 (#0)* Server auth using NTLM with user ''> GET /tfs/DefaultCollection/code/_git/MyApp HTTP/1.1
> Host: tfsserver:8080
> Authorization: NTLM ***SCRUBBED***
> User-Agent: curl/7.60.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Cache-Control: no-cache, no-store, must-revalidate
< Pragma: no-cache
< Content-Type: text/html; charset=utf-8
< Expires: -1
< Server: Microsoft-IIS/8.5
< X-TFS-ProcessId: e5b67424-832f-468b-8787-c7c05aef5396
< ActivityId: 50f62941-8163-4ee9-9c2b-81359ca72838
< X-TFS-Session: 50f62941-8163-4ee9-9c2b-81359ca72838
< X-VSS-E2EID: 50f62941-8163-4ee9-9c2b-81359ca72838
< X-FRAME-OPTIONS: SAMEORIGIN
< X-VSS-UserData: 34be4ed8-c4fd-4e9f-bdae-d1843df36b0f:mkharitonov
< X-AspNetMvc-Version: 4.0
< X-AspNet-Version: 4.0.30319
< Set-Cookie: __RequestVerificationToken_L3Rmcw2=***SCRUBBED***; path=/; HttpOnly
< Set-Cookie: __RequestVerificationToken27563503a-8c73-4ee0-8930-e1f466b255f5=***SCRUBBED***; path=/; HttpOnly
< Persistent-Auth: true
< X-Powered-By: ASP.NET
< P3P: CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR LOC CNT"
< Lfs-Authenticate: NTLM
< X-Content-Type-Options: nosniff
< Date: Thu, 15 Nov 2018 23:07:58 GMT
< Content-Length: 120608
< 
{ [183 bytes data]
100  117k  100  117k    0     0   167k      0 --:--:-- --:--:-- --:--:--  167k* Connection #0 to host tfsserver left intact
1 Answers

I cannot verify it to the end, but probably you should set http.emptyAuth to true in config (command git config --global http.emptyAuth true). At least after setting it my git 2.19.1.windows.1 has sent a Authorization: Negotiate ... header to a server which advertises this protocol.

Bottom line:

git config --global http.emptyAuth true

Does it if LFS is not in the picture. If LFS is involved, then prepend the host name with :@, e.g.

http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp
Related