microsoft / Git-Credential-Manager-for-Windows

Secure Git credential storage for Windows with support for Visual Studio Team Services, GitHub, and Bitbucket multi-factor authentication.
Other
2.87k stars 589 forks source link

Cannot read credentials for target URL with path #859

Open sbogdano-quest opened 5 years ago

sbogdano-quest commented 5 years ago

Steps to reproduce:

  1. Clone any repository (e.g. git clone https://github.com/SomeOrg/SomeRepository). During the process git.exe creates an entry in Credential Manager with name "git:https://github.com"
  2. Run this code: var creds = new SecretStore("git").ReadCredentials(new TargetUri("https://github.com/SomeOrg/SomeRepository")); if (creds == null) Console.WriteLine("Credentials not found");
  3. You'll get "Credentials not found".

If you use "https://github.com" in the code above then everything will work fine. The root cause is that Secret.UriToName method that is used by SecretStore.ReadCredentials by default does not truncate path part of URL. I think it should truncate by default to be consistent with git.exe which creates git:https://github.com entry for https://github.com/SomeOrg/SomeRepository URL.

sbogdano-quest commented 5 years ago

I think github label is not suitable for the issue, the issue is actual for the Bitbucket too.

jeschu1 commented 5 years ago

@sbogdano-quest, GCM will store the full path on a clone if useHttpPath is set. Please see documentation here

That flag will let you store per repository, rather than per host. If someone has that flag set, they should be using the full path in the lookup as well.

What is your scenario here?

sbogdano-quest commented 5 years ago

Seems Microsoft.Alm.Authentication.SecretStore also should have something like useHttpPath parameter.

I'm writing the code to enum branches of remote repository using Microsoft.Alm.Authentication and LibGit2Sharp:

void PrintBranches(string repositoryUrl = "https://git.mycompany.com/myproject/myrepository.git") { var targetUri = new TargetUri(new TargetUri(repositoryUrl).ToString(username: false, port: true, path: false)); var creds = new SecretStore("git").ReadCredentials(targetUri);`

foreach (var r in Repository.ListRemoteReferences(repositoryUrl, (url, usernameFromUrl, types) => new UsernamePasswordCredentials
    {
        Username = creds.Username,
        Password = creds.Password
    }))
    Console.WriteLine(r.CanonicalName);

}

This code uses credentials that are stored in Credential Manager by git.exe to access remote repository. And I have to truncate repositoryUrl to make this code working because SecretStore does not do this by default: var targetUri = new TargetUri(new TargetUri(repositoryUrl).ToString(username: false, port: true, path: false));

kzu commented 5 years ago

Agreed with this, just spent some time trying to get things to work until I found this. My workaround was to create a Uri from the string and just pick the right components: new TargetUri(uri.GetComponents(UriComponents.Scheme | UriComponents.Host, UriFormat.Unescaped)) before calling the API