diff --git a/src/Identity/IdentityServer/ClientProviders/SecretsManagerApiKeyProvider.cs b/src/Identity/IdentityServer/ClientProviders/SecretsManagerApiKeyProvider.cs index 045b1a1c09..dec5f8dc64 100644 --- a/src/Identity/IdentityServer/ClientProviders/SecretsManagerApiKeyProvider.cs +++ b/src/Identity/IdentityServer/ClientProviders/SecretsManagerApiKeyProvider.cs @@ -9,6 +9,8 @@ namespace Bit.Identity.IdentityServer.ClientProviders; internal class SecretsManagerApiKeyProvider : IClientProvider { + public const string ApiKeyPrefix = "apikey"; + private readonly IApiKeyRepository _apiKeyRepository; private readonly IOrganizationRepository _organizationRepository; diff --git a/src/Identity/IdentityServer/DynamicClientStore.cs b/src/Identity/IdentityServer/DynamicClientStore.cs index 00e265f015..d7e589a093 100644 --- a/src/Identity/IdentityServer/DynamicClientStore.cs +++ b/src/Identity/IdentityServer/DynamicClientStore.cs @@ -1,5 +1,6 @@ #nullable enable +using Bit.Identity.IdentityServer.ClientProviders; using Duende.IdentityServer.Models; using Duende.IdentityServer.Stores; @@ -18,7 +19,7 @@ internal class DynamicClientStore : IClientStore public DynamicClientStore( IServiceProvider serviceProvider, - [FromKeyedServices("sm-apikey")] IClientProvider apiKeyClientProvider, + [FromKeyedServices(SecretsManagerApiKeyProvider.ApiKeyPrefix)] IClientProvider apiKeyClientProvider, StaticClientStore staticClientStore ) { @@ -46,8 +47,6 @@ internal class DynamicClientStore : IClientStore // Increment past the period var identifierName = clientIdSpan[..firstPeriod++]; - // TODO: Validate some rules about the identifierName? - var identifier = clientIdSpan[firstPeriod..]; // The identifier is required to be non-empty @@ -56,6 +55,7 @@ internal class DynamicClientStore : IClientStore return Task.FromResult(null); } + // Once identifierName is proven valid, materialize the string var clientBuilder = _serviceProvider.GetKeyedService(identifierName.ToString()); if (clientBuilder == null) diff --git a/src/Identity/IdentityServer/ServiceCollectionExtensions.cs b/src/Identity/IdentityServer/ServiceCollectionExtensions.cs index fc97fb8e45..2402ebb7f9 100644 --- a/src/Identity/IdentityServer/ServiceCollectionExtensions.cs +++ b/src/Identity/IdentityServer/ServiceCollectionExtensions.cs @@ -4,15 +4,23 @@ namespace Microsoft.Extensions.DependencyInjection; public static class ServiceCollectionExtensions { + /// + /// Registers a custom for the given identifier to be called when a client id with + /// the identifier is attempting authentication. + /// + /// Your custom implementation of . + /// The service collection to add services to. + /// + /// The identifier to be used to invoke your client provider if a client_id is prefixed with your identifier + /// then your implementation will be invoked with the data after the seperating .. + /// + /// The for additional chaining. public static IServiceCollection AddClientProvider(this IServiceCollection services, string identifier) where T : class, IClientProvider { ArgumentNullException.ThrowIfNull(services); ArgumentException.ThrowIfNullOrWhiteSpace(identifier); - // TODO: Track name so that if they register the same one twice it's an error? - - // TODO: We could allow customization of service lifetime services.AddKeyedTransient(identifier); return services; diff --git a/src/Identity/Utilities/ServiceCollectionExtensions.cs b/src/Identity/Utilities/ServiceCollectionExtensions.cs index 51b658f4c3..34ad68c676 100644 --- a/src/Identity/Utilities/ServiceCollectionExtensions.cs +++ b/src/Identity/Utilities/ServiceCollectionExtensions.cs @@ -78,7 +78,7 @@ public static class ServiceCollectionExtensions services.AddClientProvider("user"); services.AddClientProvider("organization"); - services.AddClientProvider("sm-apikey"); + services.AddClientProvider(SecretsManagerApiKeyProvider.ApiKeyPrefix); if (CoreHelpers.SettingHasValue(globalSettings.IdentityServer.CosmosConnectionString)) {