Search code examples
c#azure-devopsnugetnuget-packageazure-artifacts

NuGet Client SDK - Connecting to a private NuGet feed through code


I'm using a private NuGet feed through Azure DevOps.
To see information about a public NuGet package from code, one simply has to follow the documentation here. In particular:

ILogger logger = NullLogger.Instance;
CancellationToken cancellationToken = CancellationToken.None;

SourceCacheContext cache = new SourceCacheContext();
SourceRepository repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
PackageMetadataResource resource = await repository.GetResourceAsync<PackageMetadataResource>();

IEnumerable<IPackageSearchMetadata> packages = await resource.GetMetadataAsync(
    "Newtonsoft.Json",
    includePrerelease: true,
    includeUnlisted: false,
    cache,
    logger,

I'm trying to achieve the same result for my own private feed by adding my credentials to the process:

var logger = NullLogger.Instance;
var cancellationToken = CancellationToken.None;

var cache = new SourceCacheContext();    
var source = new PackageSource("*my feed*/nuget/v3/index.json");
source.Credentials = new PackageSourceCredential("*my feed*/nuget/v3/index.json", "*username*", "*password*", true, null);

var repository = Repository.Factory.GetCoreV2(source);
var resource = await repository.GetResourceAsync<PackageMetadataResource>();

IEnumerable<IPackageSearchMetadata> searchMetadata = await resource.GetMetadataAsync(
    "My.Package.Name",
    includePrerelease: true,
    includeUnlisted: false,
    cache,
    logger,
    cancellationToken);

Please note, that even though I call the Factory.GetCoreV2(), the inside of the method still calls V3 providers. It's simply the only constructor that takes a PackageSource as a parameter:

public static SourceRepository GetCoreV2(this Repository.RepositoryFactory factory, PackageSource source)
{
     return Repository.CreateSource(Repository.Provider.GetCoreV3(), source);
}

However, no matter what I do, I cannot get through step

var resource = await repository.GetResourceAsync<PackageMetadataResource>();

which keeps failing with a NuGet.Protocol.Core.Types.FatalProtocolException - 401 Unauthorised. I've verified the validity of my credentials and my feed endpoint, as well as my permissions within the feed (full access). I've also tried the initialisation process described here (plus the step with my credentials), yet the result is the same.

How am I expected to identify to an Azure DevOps feed from code, to be able to get the IPackageMetadata information?


Solution

  • Azure DevOps doesn't support username & password authentication through NuGet. If your account needs 2 factor authentication (2FA), there's no way for NuGet to prompt you for it. I don't know if they decided not to support it for all accounts, even ones that are not 2FA enabled, or if there are other reasons as well (I suspect it's not allowed for other security reasons).

    If you have Visual Studio installed, or have otherwise installed the Azure Artifacts NuGet credentials provider, maybe you could try not using any credentials in your code. I'm not sure how exactly nuget.exe, dotnet cli and msbuild discover the credentials provider, but maybe it works when using the sdk as well.

    Otherwise if you want to, or need to, use the credentials API, you need to generate a personal access token, and use that as the password.