Have you ever tried to connect to a Git repository that uses NTLM authentication? No? I’m not surprised, because none of the known Git providers required such credentials. But with the Team Foundation Server 2013 git source control this is necessary, at least for the on-premise installed one. If you have used LibGit2Sharp (http://www.nuget.org/packages/LibGit2Sharp/, https://github.com/libgit2/libgit2sharp/) in your application to connect to Git, you will need to realize that it does not support NTLM authentication unfortunately, so you (or your clients) cannot enjoy the benefits of Git with TFS 2013. If you try, you will get an exception, like “Request failed with status code: 401”.
We had the same situation with SpecLog, that is able to synchronize Gherkin files from Git repositories. But because of this limitation, it did not work with TFS 2013.
Microsoft folks have mentioned several times (e.g. Scott Hanselman or Edward Thomson) that Visual Studio uses libgit2 and libgit2sharp for connecting to Git repositories. And indeed, Visual Studio can connect to TFS 2013 Git! How can this be?
My suspicion was that they use a cooked version of these tools (located in
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer), but even with their version, I’ve got the 401.
By browsing the source code and comparing it with a decompiled one, I could not figure out what’s the difference. Finally, fiddler helped me out. I have captured the HTTP(s) traffic while cloning a repository with VS2013. I enabled the automatic breakpoint feature in fiddler and stopped the execution at the first request made towards the TFS server. While the request was blocked, I quickly attached to the Visual Studio process with another VS instance and paused the execution. Among the threads, I found the one that was performing the Git clone and the answer was there…
As you can see, libgit2sharp calls out to libgit2, but that calls back to a class called TfsSmartTransportStream! Wow! Smart!
Now what is strange that the entire infrastructure supporting this (SmartSubtransportStream and co.) is only in the VS version of the libgit2sharp library. (Update: There is a pending pull request to include it.) It needs a little bit of work to implement the necessary
SmartSubtransport class and the related classes, but not super complicated (see my solution that uses
HttpClient here). An easy alternative is to use the implementation used by VS. For instance you can create a class like this:
Note: As the
TfsSmartSubtransport implementation is bound to TFS and Visual Studio, don’t use this as a generic purpose NTLM connection. For real code, I recommend using the pure
With this session class, you just need to wrap your LibGit2Sharp commands, in order to enable the custom network handler that can perform NTLM authentication:
Happy gitting, now also on TFS!
(You can check the sample code related to this post on github: https://github.com/gasparnagy/Sample_NtlmGitTest/)