Skip to main content

Overview

NuGetGallery.Services is the central business-logic assembly for the NuGet Gallery. It sits between the web layer and the data layer, providing well-defined service interfaces and their concrete implementations for every major feature area: authentication (passwords, API keys, OAuth, federated/OIDC credentials), package lifecycle, user and account management, security policy enforcement, feature flags, telemetry, and cloud storage abstraction. The project multi-targets net472 (full .NET Framework, used by the ASP.NET MVC gallery host) and netstandard2.1 (used by background worker processes). The netstandard2.1 target deliberately excludes the most UI-coupled directories (Authentication, Mail, Configuration, etc.) via <Compile Remove> directives, exposing only the subset needed by workers.
The netstandard2.1 compile exclusions are intentional — many classes in this library depend on System.Web, OWIN middleware, and ASP.NET MVC types that are not available outside of the full .NET Framework host. Check the .csproj <Compile Remove> blocks before referencing a type from a non-net472 context.

Role in the System

Gallery Frontend

NuGetGallery (the MVC web app) consumes every service interface defined here — from IAuthenticationService to IPackageService — via constructor-injected dependencies.

Backend Workers

Background job projects reference the netstandard2.1 slice for shared entities, telemetry helpers, and infrastructure utilities without pulling in the web-specific stack.

NuGetGallery.Core

This library sits directly above NuGetGallery.Core, which owns EF entity models, repository abstractions, and low-level package-file operations.

NuGet.Services.*

Depends on NuGet.Services.Configuration, NuGet.Services.Logging, and NuGet.Services.FeatureFlags for cross-cutting infrastructure.

Key Files and Classes


Dependencies

NuGet Package References

Internal Project References


Notable Patterns and Implementation Details

Dual-target architecture — The .csproj uses <Compile Remove> to strip the entire Authentication, Configuration, Mail, Permissions, Security, Storage, and Telemetry folders from the netstandard2.1 build. This is the primary mechanism for keeping background workers free of ASP.NET dependencies.
API key versioning (V3 → V5) — Three key formats coexist. V3 uses PBKDF2-hashed GUIDs. V4 adds scope-aware prefixes. V5 uses the HISv2 standard (84 base62 characters) with embedded metadata (user ID, allocation time, environment code, expiry) and a Marvin32 checksum for fast pre-DB validation. All formats are still validated to support existing long-lived keys.
LegacyHasher (Authentication/LegacyHasher.cs) implements the old MD5/SHA1-based credential hashing that predates V3Hasher. It is retained solely to validate credentials created before the PBKDF2 migration and automatically upgrades them on successful login. New credentials must never use this hasher.
Federated credential / trusted publishingFederatedCredentialService issues short-lived API keys (≤ 15 minutes, encoded in the V5 key body) after validating an OIDC bearer token from GitHub Actions or an Entra ID service principal against policies stored per-user in the database. The short lifetime is enforced both in the V5 key metadata and by the database expiry field.
ContentObjectService caches JSON blobs from Azure Blob Storage with a 5-minute refresh interval (RefreshInterval = TimeSpan.FromMinutes(5)). Feature-gated configuration objects (typosquatting lists, login discontinuation rules, cert allowlists) are all loaded this way, allowing live updates without redeployment.
SecurityPolicyService handlers are registered as static Lazy<IEnumerable<...>> singletons. Adding a new policy handler requires updating both CreateUserHandlers() and CreatePackageHandlers() factory methods inside SecurityPolicyService.cs, otherwise the new handler will never be evaluated.