CommonKeyVaultServices 1.0.1

dotnet add package CommonKeyVaultServices --version 1.0.1
                    
NuGet\Install-Package CommonKeyVaultServices -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CommonKeyVaultServices" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CommonKeyVaultServices" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="CommonKeyVaultServices" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CommonKeyVaultServices --version 1.0.1
                    
#r "nuget: CommonKeyVaultServices, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CommonKeyVaultServices@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CommonKeyVaultServices&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=CommonKeyVaultServices&version=1.0.1
                    
Install as a Cake Tool

CommonKeyVaultServices

A reusable .NET 10 library for integrating Azure Key Vault into applications and shared libraries with minimal setup.

The package provides Azure Key Vault credential creation, SecretClient registration, secret reading, and optional SQL Server Always Encrypted Azure Key Vault provider registration.

It supports both direct application usage and scenarios where multiple libraries inside the same application require independent Key Vault registrations.

Features

  • Azure Key Vault integration
  • SecretClient registration through dependency injection
  • IKeyVaultSecretReader abstraction for reading secrets
  • Support for DefaultAzureCredential
  • Support for ClientSecretCredential
  • Support for system-assigned and user-assigned Managed Identity
  • SQL Server Always Encrypted Azure Key Vault provider registration
  • Strongly typed KeyVaultOptions
  • Explicit caller-supplied configuration
  • Support for arbitrary configuration property names
  • Keyed dependency injection for multiple independent Key Vault registrations
  • Backward-compatible configuration-section registration
  • Compatible with ASP.NET Core, Azure Functions, Console Applications, and Class Libraries
  • .NET 10 support

Installation

Install the package from NuGet:

dotnet add package CommonKeyVaultServices

To install a specific version:

dotnet add package CommonKeyVaultServices --version 1.0.1

Basic Usage

The recommended approach is to explicitly provide the Key Vault settings from the consuming application.

builder.Services.AddSharedKeyVaultServices(options =>
{
    options.VaultName = builder.Configuration["MyVaultName"];
    options.CredentialMode = "ClientSecret";
    options.TenantId = builder.Configuration["MyTenant"];
    options.ClientId = builder.Configuration["MyClient"];
    options.ClientSecret = builder.Configuration["MyClientSecret"];
});

The configuration property names are controlled entirely by the consuming application.

For example, the consuming application could instead use:

builder.Services.AddSharedKeyVaultServices(options =>
{
    options.VaultName = builder.Configuration["ABC"];
    options.TenantId = builder.Configuration["TenantForMyApplication"];
    options.ClientId = builder.Configuration["AzureApplicationId"];
    options.ClientSecret = builder.Configuration["AzureApplicationSecret"];
    options.CredentialMode = "ClientSecret";
});

CommonKeyVaultServices does not require those configuration properties to use specific names when the explicit Action<KeyVaultOptions> registration is used.

The consuming application is responsible for retrieving the values from its configuration and supplying them to KeyVaultOptions.

Reading Secrets

Inject IKeyVaultSecretReader into the consuming service:

public class MyService
{
    private readonly IKeyVaultSecretReader _secretReader;

    public MyService(IKeyVaultSecretReader secretReader)
    {
        _secretReader = secretReader;
    }

    public async Task<string?> GetSecretAsync()
    {
        return await _secretReader.GetSecretAsync("MySecret");
    }
}

Multiple Key Vault Registrations

An application may require more than one independent Key Vault configuration.

For example:

  • the final application may use its own Key Vault;
  • a shared library such as DoCommon may internally use another Key Vault;
  • both may exist in the same dependency injection container.

CommonKeyVaultServices supports this through keyed dependency injection.

Application Key Vault

The application's primary Key Vault can use the normal registration:

builder.Services.AddSharedKeyVaultServices(options =>
{
    options.VaultName = builder.Configuration["ApplicationVault"];
    options.CredentialMode = "ClientSecret";
    options.TenantId = builder.Configuration["ApplicationTenant"];
    options.ClientId = builder.Configuration["ApplicationClient"];
    options.ClientSecret = builder.Configuration["ApplicationSecret"];
});

This registers the normal unkeyed:

TokenCredential
SecretClient
IKeyVaultSecretReader

Shared Library Key Vault

A shared library can register a separate Key Vault using a service key:

services.AddSharedKeyVaultServices("DoCommonKeyVault", options =>
{
    options.VaultName = suppliedOptions.VaultName;
    options.CredentialMode = suppliedOptions.CredentialMode;
    options.TenantId = suppliedOptions.TenantId;
    options.ClientId = suppliedOptions.ClientId;
    options.ClientSecret = suppliedOptions.ClientSecret;
    options.ManagedIdentityClientId = suppliedOptions.ManagedIdentityClientId;
    options.RegisterSqlColumnEncryptionProvider =
        suppliedOptions.RegisterSqlColumnEncryptionProvider;
});

This keeps the shared library's:

TokenCredential
SecretClient
IKeyVaultSecretReader

separate from the application's own Key Vault services.

Using a Keyed Secret Reader

When a keyed Key Vault registration is used, resolve the corresponding keyed service.

For example:

public class MyInternalService
{
    private readonly IKeyVaultSecretReader _secretReader;

    public MyInternalService(
        [FromKeyedServices("DoCommonKeyVault")]
        IKeyVaultSecretReader secretReader)
    {
        _secretReader = secretReader;
    }
}

The application's normal unkeyed IKeyVaultSecretReader remains independent from the keyed reader.

Configuration Sources

CommonKeyVaultServices does not dictate where configuration values must come from.

The final consuming application can obtain the values from:

  • local.settings.json
  • appsettings.json
  • environment variables
  • Azure App Settings
  • another configuration provider
  • programmatically supplied values

For example, an Azure Functions local.settings.json file could contain:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",

    "MY_APP_VAULT": "application-key-vault",
    "MY_APP_TENANT": "<tenant-id>",
    "MY_APP_CLIENT": "<client-id>",
    "MY_APP_SECRET": "<client-secret>",

    "DOCOMMON_VAULT": "docommon-key-vault",
    "DOCOMMON_TENANT": "<tenant-id>",
    "DOCOMMON_CLIENT": "<client-id>",
    "DOCOMMON_SECRET": "<client-secret>"
  }
}

The final application then decides how those values are mapped into the appropriate library options.

Configuration Section Registration

For applications that prefer the conventional configuration structure, the following overload remains available:

builder.Services.AddSharedKeyVaultServices(
    builder.Configuration,
    "KeyVault");

For example:

{
  "KeyVault": {
    "VaultName": "my-key-vault",
    "CredentialMode": "ClientSecret",
    "TenantId": "<tenant-id>",
    "ClientId": "<client-id>",
    "ClientSecret": "<client-secret>",
    "Required": true,
    "RegisterSqlColumnEncryptionProvider": true
  }
}

The explicit Action<KeyVaultOptions> approach is recommended when the consuming application requires custom configuration property names.

KeyVaultOptions

The available options are:

public sealed class KeyVaultOptions
{
    public string? VaultName { get; set; }
    public string? VaultUri { get; set; }
    public string? VaultSecret { get; set; }

    public bool Required { get; set; } = true;

    public string CredentialMode { get; set; } = "Default";

    public string? TenantId { get; set; }
    public string? ClientId { get; set; }
    public string? ClientSecret { get; set; }

    public string? ManagedIdentityClientId { get; set; }

    public bool RegisterSqlColumnEncryptionProvider { get; set; } = true;
}

Either VaultName or VaultUri must be supplied when Required is true.

When VaultName is supplied, the library constructs the Key Vault URI as:

https://{VaultName}.vault.azure.net/

Supported Credential Modes

Default

Uses DefaultAzureCredential.

options.CredentialMode = "Default";

If ManagedIdentityClientId is also supplied, it is passed to DefaultAzureCredential for user-assigned Managed Identity selection.

ClientSecret

Uses ClientSecretCredential.

options.CredentialMode = "ClientSecret";
options.TenantId = configuration["Tenant"];
options.ClientId = configuration["Client"];
options.ClientSecret = configuration["Secret"];

TenantId, ClientId, and ClientSecret are required when using this mode.

ManagedIdentity

Uses ManagedIdentityCredential.

options.CredentialMode = "ManagedIdentity";

For a user-assigned Managed Identity:

options.CredentialMode = "ManagedIdentity";
options.ManagedIdentityClientId =
    configuration["ManagedIdentityClientId"];

If ManagedIdentityClientId is not supplied, the default Managed Identity is used.

SQL Server Always Encrypted

CommonKeyVaultServices can register the Azure Key Vault provider required by SQL Server Always Encrypted.

Enable it through:

options.RegisterSqlColumnEncryptionProvider = true;

This option defaults to true.

The provider registration is performed internally by CommonKeyVaultServices when AddSharedKeyVaultServices(...) is called.

A separate InitializeSharedKeyVault(...) call is not required for new implementations.

The SQL Azure Key Vault provider registration is protected against repeated registration within the process.

Important

SQL Server's Azure Key Vault column-encryption provider registration is process-wide rather than a normal keyed dependency injection service.

Therefore, if multiple Key Vault registrations exist in the same application, the credential used to register the SQL Always Encrypted provider must have access to the Azure Key Vault keys required by the application's Always Encrypted databases.

Startup Secret

For scenarios where a secret must be retrieved directly during startup, GetStartupSecretAsync remains available.

Example:

var secret = await KeyVaultStartupExtensions.GetStartupSecretAsync(options =>
{
    options.VaultName = configuration["MyVault"];
    options.VaultSecret = "MyStartupSecret";
    options.CredentialMode = "ClientSecret";
    options.TenantId = configuration["MyTenant"];
    options.ClientId = configuration["MyClient"];
    options.ClientSecret = configuration["MySecret"];
});

This is intended for startup-time secret retrieval. Normal application services should use dependency injection and IKeyVaultSecretReader.

Backward Compatibility

InitializeSharedKeyVault(...) remains available for backward compatibility.

New implementations should use:

services.AddSharedKeyVaultServices(options =>
{
    // Key Vault configuration
});

or, when an independent named registration is required:

services.AddSharedKeyVaultServices(
    "MyKeyVault",
    options =>
    {
        // Key Vault configuration
    });

SQL Always Encrypted initialization is now handled as part of AddSharedKeyVaultServices(...).

Shared Library Scenario

A shared library should not read configuration files directly or assume configuration property names.

Instead, its consuming application should supply the required values to the shared library.

For example:

builder.Services.AddMySharedLibrary(options =>
{
    options.KeyVault.VaultName =
        builder.Configuration["WHATEVER_VAULT_PROPERTY"];

    options.KeyVault.TenantId =
        builder.Configuration["WHATEVER_TENANT_PROPERTY"];

    options.KeyVault.ClientId =
        builder.Configuration["WHATEVER_CLIENT_PROPERTY"];

    options.KeyVault.ClientSecret =
        builder.Configuration["WHATEVER_SECRET_PROPERTY"];
});

The shared library can then internally register its own Key Vault:

services.AddSharedKeyVaultServices(
    "MySharedLibraryKeyVault",
    options =>
    {
        options.VaultName = suppliedKeyVaultOptions.VaultName;
        options.VaultUri = suppliedKeyVaultOptions.VaultUri;
        options.CredentialMode = suppliedKeyVaultOptions.CredentialMode;
        options.TenantId = suppliedKeyVaultOptions.TenantId;
        options.ClientId = suppliedKeyVaultOptions.ClientId;
        options.ClientSecret = suppliedKeyVaultOptions.ClientSecret;
        options.ManagedIdentityClientId =
            suppliedKeyVaultOptions.ManagedIdentityClientId;
        options.RegisterSqlColumnEncryptionProvider =
            suppliedKeyVaultOptions.RegisterSqlColumnEncryptionProvider;
    });

This keeps configuration ownership with the final application while allowing the shared library to completely own its internal Key Vault registration.

Requirements

  • .NET 10 or later
  • Azure Key Vault
  • Appropriate Azure permissions for the selected credential type
  • Appropriate Key Vault key permissions when SQL Server Always Encrypted is enabled

Security

This package does not contain or store:

  • credentials
  • client secrets
  • connection strings
  • tenant IDs
  • Key Vault names
  • Key Vault URIs
  • application-specific configuration values

All values must be supplied by the consuming application or library.

Secrets and credentials should not be committed to source control.

For production environments, Managed Identity or another appropriate Azure identity mechanism should be preferred where applicable.

Versioning

This project follows Semantic Versioning.

1.0.1

  • Added support for keyed Key Vault service registrations.
  • Allows independent application and shared-library Key Vault registrations in the same dependency injection container.
  • Consolidated SQL Always Encrypted provider registration into AddSharedKeyVaultServices.
  • Preserved InitializeSharedKeyVault for backward compatibility.
  • Improved configuration binding so missing boolean settings preserve KeyVaultOptions defaults.
  • Preserved support for caller-defined configuration property names through Action<KeyVaultOptions>.

Versioning policy:

  • Patch: bug fixes and compatible corrections (1.0.x)
  • Minor: backward-compatible features (1.x.0)
  • Major: breaking changes (x.0.0)

License

MIT License

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 104 8/10/2026
1.0.0 123 5/29/2026