Files
EonaCat.SecureToken/EonaCat.SecureToken/Extensions/ServiceCollectionExtensions.cs
T
2026-06-20 06:27:57 +02:00

70 lines
3.0 KiB
C#

using Microsoft.Extensions.DependencyInjection;
using EonaCat.SecureToken.Cryptography;
using EonaCat.SecureToken.Validation;
using System;
namespace EonaCat.SecureToken.Extensions
{
// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
/// <summary>
/// Extension methods for registering SecureToken services with the DI container.
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds SecureToken services using a randomly generated ephemeral key.
/// Use <see cref="AddSecureTokens(IServiceCollection, SigningKeyStore)"/> in production
/// to supply a persistent, managed key store.
/// </summary>
public static IServiceCollection AddSecureTokens(this IServiceCollection services)
{
var keyStore = SigningKeyStore.CreateNew();
return services.AddSecureTokens(keyStore);
}
/// <summary>
/// Adds SecureToken services with a supplied key store.
/// </summary>
public static IServiceCollection AddSecureTokens(this IServiceCollection services, SigningKeyStore keyStore)
{
services.AddSingleton(keyStore);
services.AddSingleton<ITokenService, TokenService>();
return services;
}
/// <summary>
/// Adds SecureToken services with a factory function to configure the key store.
/// Useful when loading keys from environment variables or a secret manager.
/// </summary>
public static IServiceCollection AddSecureTokens(this IServiceCollection services, Func<IServiceProvider, SigningKeyStore> keyStoreFactory)
{
if (keyStoreFactory is null)
{
throw new ArgumentNullException(nameof(keyStoreFactory));
}
// Register SigningKeyStore as the singleton, invoking the factory exactly once
// on first resolution. Registering the Func<> itself (the original behavior)
// left nothing in the container that satisfies TokenService's SigningKeyStore
// dependency, so resolution of ITokenService would fail at runtime.
services.AddSingleton(sp => keyStoreFactory(sp));
services.AddSingleton<ITokenService, TokenService>();
return services;
}
/// <summary>
/// Registers a process-local <see cref="IReplayCache"/> (backed by
/// <see cref="InMemoryReplayCache"/>) for detecting replayed one-time-use
/// tokens. For multi-instance deployments, register your own <see cref="IReplayCache"/>
/// implementation backed by a shared store instead of calling this method.
/// </summary>
public static IServiceCollection AddSecureTokenReplayProtection(this IServiceCollection services)
{
services.AddSingleton<IReplayCache, InMemoryReplayCache>();
return services;
}
}
}