Search code examples
.netauthenticationgitlabnugetcicd

Getting 401 when trying to access NuGet sources


I have a local PC with Windows 11 on it. In my global Nuget.Config there are several Nuget sources. There is the default one on nuget.org, and some of my private ones on gitlab.com.

For the private ones, user credentials are provided. On Windows with encrypted (not cleartext) password.

When i run 'nuget' or 'dotnet nuget' commands, everything runs find on Windows.

But i also use CI/CD on gitlab.com. There is NO Nuget.Config file in my repo. Instead, i add all needed nuget sources via dotnet nuget add source... The private ones on gitlab.com with clear text password since it otherwise is not supported on linux. That all worked fine until some days ago. Now some nuget operations fail with 401.

$ dotnet nuget list source

Registered Sources:

  1. nuget.org [Enabled] https://api.nuget.org/v3/index.json
  2. gitlabgrp [Enabled] https://gitlab.com/api/v4/groups/xxx/-/packages/nuget/index.json
  3. gitlab-tools [Enabled] https://gitlab.com/api/v4/groups/yyy/-/packages/nuget/index.json
  4. gitlab-archive [Enabled] https://gitlab.com/api/v4/groups/zzz/-/packages/nuget/index.json
  5. dotnet8preview [Enabled] https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json

$ dotnet tool install -g dotnet-reportgenerator-globaltool --ignore-failed-sources

Unhandled exception: System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized). at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at NuGet.Protocol.HttpSource.<>c__DisplayClass15_01.<<GetAsync>b__0>d.MoveNext() --- End of stack trace from previous location --- at NuGet.Common.ConcurrencyUtilities.ExecuteWithFileLockedAsync[T](String filePath, Func2 action, CancellationToken token) at NuGet.Common.ConcurrencyUtilities.ExecuteWithFileLockedAsync[T](String filePath, Func2 action, CancellationToken token) at NuGet.Protocol.HttpSource.GetAsync[T](HttpSourceCachedRequest request, Func2 processAsync, ILogger log, CancellationToken token) at NuGet.Protocol.PackageMetadataResourceV3.LoadRegistrationIndexAsync(HttpSource httpSource, Uri registrationUri, String packageId, SourceCacheContext cacheContext, Func2 processAsync, ILogger log, CancellationToken token) at NuGet.Protocol.PackageMetadataResourceV3.GetMetadataAsync(String packageId, Boolean includePrerelease, Boolean includeUnlisted, VersionRange range, SourceCacheContext sourceCacheContext, ILogger log, CancellationToken token) at NuGet.Protocol.PackageMetadataResourceV3.GetMetadataAsync(String packageId, Boolean includePrerelease, Boolean includeUnlisted, SourceCacheContext sourceCacheContext, ILogger log, CancellationToken token) at Microsoft.DotNet.Cli.NuGetPackageDownloader.NuGetPackageDownloader.GetPackageMetadataAsync(PackageSource source, String packageIdentifier, Boolean includePrerelease, CancellationToken cancellationToken) at Microsoft.DotNet.Cli.NuGetPackageDownloader.NuGetPackageDownloader.GetMatchingVersionInternalAsync(String packageIdentifier, IEnumerable1 packageSources, VersionRange versionRange, CancellationToken cancellationToken) at Microsoft.DotNet.Cli.NuGetPackageDownloader.NuGetPackageDownloader.GetBestPackageVersionAsync(PackageId packageId, VersionRange versionRange, PackageSourceLocation packageSourceLocation) at Microsoft.DotNet.Cli.ToolPackage.ToolPackageDownloader.<>c__DisplayClass8_0.b__0() at Microsoft.DotNet.Cli.TransactionalAction.Run[T](Func`1 action, Action commit, Action rollback) at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.Execute() at System.CommandLine.Invocation.InvocationPipeline.Invoke(ParseResult parseResult) at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)

Is there any possibility to see WHY there is a 401? In the example above, i try to install dotnet global tool 'dotnet-report-generator-globaltool'. That used to work for at least a year. It comes from nuget.org. So no auth should be needed at all here. But i get a 401!

I tried adding --ignore-failed-sources. But with no success.

I'm using .NET 8 SDK here.


Solution

  • OK, i found that the password for one of my NuGet sources was expired.

    The 'dotnet restore' command did not tell which source threw the 401. The option --ignore-failed-sources did not help here. My CI job failed anyway. Got some hints with --verbosity detailed option.

    Since NuGet does not check the credentials on adding a source and even if it was OK at the time it was added but, like in my case, has expired sometime after, there is no possibility to check the stored credentials, i created a feature request for NuGet to add that possibility.

    See: NuGet GitHub issue