Seamlessly integrate 1Password secrets into your .NET applications during development.
If you love 1Password (and who doesn't?) and want to bring that same level of security and convenience to your .NET development workflow, this library is for you.
The Problem: Managing secrets during development is painful. You don't want to commit API keys, connection strings, or passwords to source control, but you also don't want to juggle multiple files, environment variables, or complicated secret management systems just to run your app locally.
The Solution: This library bridges the gap between 1Password and your .NET application's configuration system. Just reference your 1Password secrets using the op:// URI scheme in your existing configuration files, and let the library handle the rest. No changes to your existing configuration infrastructure required!
- π― Zero Configuration Changes Required - Works seamlessly with your existing
IConfigurationsetup - π Universal Compatibility - Supports
appsettings.json, environment variables, or any configuration source - β‘ Async-First Design - Built for modern .NET with full async/await support
- π§ͺ Fully Testable - Comes with a mockable interface for unit testing
- π Multi-Account Support - Specify which 1Password account to use
- π¨ Developer-Friendly - Simple API with just one method call to set up
- π¦ Lightweight - Built on .NET Standard 2.1 for broad compatibility
- π³ Aspire Integration - First-class support for .NET Aspire distributed applications
- π Parameter Resources - Add individual 1Password secrets as Aspire parameter resources
Install via NuGet Package Manager:
dotnet add package Arkanis.Hosting.Extensions.1PasswordOr via Package Manager Console:
Install-Package Arkanis.Hosting.Extensions.1PasswordFor use with .NET Aspire projects:
dotnet add package Arkanis.Aspire.Hosting.Extensions.1PasswordOr via Package Manager Console:
Install-Package Arkanis.Aspire.Hosting.Extensions.1PasswordCreate a secret in 1Password (e.g., an API key in the "Private" vault under "MyApp/ApiKey").
Add a reference to your secret in appsettings.json using the op:// URI scheme:
{
"ApiKey": "op://Private/MyApp/ApiKey",
"Database": {
"ConnectionString": "op://Private/MyApp/database-connection"
}
}Add one line to your application startup:
using Hosting.Extensions._1Password;
var builder = Host.CreateApplicationBuilder(args);
// That's it! π
await builder.Use1PasswordAsync("my.1password.com");
// or builder.Use1Password("my.1password.com");
var host = builder.Build();
await host.RunAsync();Your secrets are now available through the standard IConfiguration interface.
They are only resolved in-memory at runtime, so your configuration files remain clean.
var apiKey = builder.Configuration["ApiKey"];
var connectionString = builder.Configuration["Database:ConnectionString"];
// Use them as you normally would!var builder = Host.CreateApplicationBuilder(args);
// Resolve secrets from your default 1Password account
await builder.Use1PasswordAsync();
var host = builder.Build();
await host.RunAsync();var builder = Host.CreateApplicationBuilder(args);
// Use a specific 1Password account or sign-in address
await builder.Use1PasswordAsync("my.1password.com");
var host = builder.Build();
await host.RunAsync();If you prefer synchronous code:
var builder = Host.CreateApplicationBuilder(args);
// Synchronous version (blocks until secrets are resolved)
builder.Use1Password("my.1password.com");
var host = builder.Build();
host.Run();Works perfectly with ASP.NET Core applications:
var builder = WebApplication.CreateBuilder(args);
// Inject 1Password secrets before registering services
await builder.Use1PasswordAsync("my.1password.com");
builder.Services.AddControllers();
// ... register other services
var app = builder.Build();
app.Run();Only use 1Password in development:
var builder = Host.CreateApplicationBuilder(args);
if (builder.Environment.IsDevelopment())
{
await builder.Use1PasswordAsync("my.1password.com");
}
var host = builder.Build();
await host.RunAsync();Use 1Password with .NET Aspire for distributed application configuration:
using Aspire.Hosting;
using Arkanis.Aspire.Hosting.Extensions._1Password;
var builder = DistributedApplication.CreateBuilder(args);
// Inject secrets into the AppHost configuration
await builder.Use1PasswordAsync("my.1password.com");
// or
await builder.Use1PasswordAsync(options =>
{
options.Account = "my.1password.com";
// Additional options can be configured here
});
// ...
builder.Build().Run();Add individual 1Password parameters as Aspire resources:
using Aspire.Hosting;
using Arkanis.Aspire.Hosting.Extensions._1Password;
var builder = DistributedApplication.CreateBuilder(args);
// Add a specific 1Password secret as a parameter resource
builder.Add1PasswordParameter(
key: "ApiKey",
onePasswordKey: "op://Private/MyApp/ApiKey",
account: "my.1password.com"
);
// ...
builder.Build().Run();The library automatically traverses nested configuration:
{
"Authentication": {
"Google": {
"ClientId": "op://Private/OAuth/Google/client-id",
"ClientSecret": "op://Private/OAuth/Google/client-secret"
},
"GitHub": {
"ClientId": "op://Private/OAuth/GitHub/client-id",
"ClientSecret": "op://Private/OAuth/GitHub/client-secret"
}
},
"Database": {
"Primary": "op://Private/Database/primary-connection",
"Readonly": "op://Private/Database/readonly-connection"
}
}All op:// references are automatically detected and resolved, no matter how deeply nested!
The library is designed with testability in mind. Use the IOpCliInvoker interface to mock 1Password CLI calls in your tests:
using NSubstitute;
// Create a mock invoker
var mockInvoker = Substitute.For<IOpCliInvoker>();
mockInvoker.InvokeAsync(Arg.Any<string?>(), Arg.Any<string>())
.Returns(new BufferedCommandResult(
exitCode: 0,
standardOutput: "ApiKey=\"test-api-key-123\"",
standardError: ""
));
// Use it in your tests
var builder = Host.CreateApplicationBuilder(args);
await builder.Use1PasswordAsync(
account: "my.1password.com",
opCliInvoker: mockInvoker
);
// Verify the configuration was populated
Assert.Equal("test-api-key-123", builder.Configuration["ApiKey"]);- .NET Runtime: .NET Standard 2.1 or higher (supports .NET Core 3.0+, .NET 5+, .NET 6+, etc.)
- 1Password CLI: The
opCLI must be installed and available in your PATH - Authentication: You must be signed in to 1Password (the CLI will use your existing session)
- .NET Runtime: .NET 8.0, 9.0, or 10.0
- 1Password CLI: The
opCLI must be installed and available in your PATH - Authentication: You must be signed in to 1Password (the CLI will use your existing session)
To install the 1Password CLI:
# macOS (via Homebrew)
brew install 1password-cli
# Windows (via WinGet)
winget install 1password-cli
# Or download from: https://developer.1password.com/docs/cli/get-started/- Detection: The library scans your
IConfigurationfor any values starting withop:// - Templating: It builds a template with all detected secret references
- Resolution: It invokes the 1Password CLI (
op inject) to resolve all secrets in one call - Injection: The resolved values are written back into your configuration in-memory
All of this happens transparently during application startup, before your services are registered or initialized.
The Aspire package extends the core library with features tailored for distributed applications:
- AppHost Integration: Resolve 1Password secrets in your
AppHostproject configuration - Parameter Resources: Add individual 1Password secrets as Aspire parameter resources that can be referenced by services
- Dual APIs: Both async (
Use1PasswordAsync) and sync (Use1Password) methods for compatibility withIHostApplicationBuilder
This library is perfect for:
- β Local development - Keep secrets secure while developing locally
- β Team collaboration - Share secret references (not secrets themselves) in source control
- β Rapid prototyping - Get started quickly without complex secret management
- β Multi-environment setups - Different secrets per environment, same configuration structure
Not recommended for:
- β Production deployments - Use your platform's native secret management (Azure Key Vault, AWS Secrets Manager, etc.)
Contributions are welcome! Please feel free to submit a Pull Request.
# Clone the repository
git clone https://github.com/ArkanisCorporation/Hosting.Extensions.1Password.git
cd Hosting.Extensions.1Password
# Restore dependencies
dotnet restore
# Build the solution
dotnet build
# Run tests
dotnet testThis project is licensed under the MIT License - see the LICENSE.md file for details.
- Built with β€οΈ for the .NET and 1Password communities
- Powered by CliWrap for reliable CLI invocation
- Inspired by the amazing developer experience that 1Password provides
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with π by developers who love 1Password