/* * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) * See https://github.com/openiddict/openiddict-core for more information concerning * the license and the contributors participating to this project. */ using System; using System.ComponentModel; using System.Reflection; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection.Extensions; using OpenIddict.Abstractions; using OpenIddict.Core; using OpenIddict.Extensions; namespace Microsoft.Extensions.DependencyInjection { /// /// Exposes the necessary methods required to configure the OpenIddict core services. /// public class OpenIddictCoreBuilder { /// /// Initializes a new instance of . /// /// The services collection. public OpenIddictCoreBuilder([NotNull] IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } Services = services; } /// /// Gets the services collection. /// [EditorBrowsable(EditorBrowsableState.Never)] public IServiceCollection Services { get; } /// /// Amends the default OpenIddict core configuration. /// /// The delegate used to configure the OpenIddict options. /// This extension can be safely called multiple times. /// The . public OpenIddictCoreBuilder Configure([NotNull] Action configuration) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } Services.Configure(configuration); return this; } /// /// Adds a custom application store by a custom implementation derived /// from . /// Note: when using this overload, the application store /// must be either a non-generic or closed generic service. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder AddApplicationStore(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TStore : class => AddApplicationStore(typeof(TStore), lifetime); /// /// Adds a custom application store by a custom implementation derived /// from . /// Note: when using this overload, the application store can be /// either a non-generic, a closed or an open generic service. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder AddApplicationStore( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictApplicationStore<>)); if (root == null) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictApplicationStore<>) // or closed generics (e.g OpenIddictApplicationStore). if (type.GetTypeInfo().IsGenericTypeDefinition) { if (type.GetGenericArguments().Length != 1) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictApplicationStore<>), type, lifetime)); } else { Services.Replace(new ServiceDescriptor(typeof(IOpenIddictApplicationStore<>) .MakeGenericType(root.GenericTypeArguments[0]), type, lifetime)); } return this; } /// /// Adds a custom authorization store by a custom implementation derived /// from . /// Note: when using this overload, the authorization store /// must be either a non-generic or closed generic service. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder AddAuthorizationStore(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TStore : class => AddAuthorizationStore(typeof(TStore), lifetime); /// /// Adds a custom authorization store by a custom implementation derived /// from . /// Note: when using this overload, the authorization store can be /// either a non-generic, a closed or an open generic service. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder AddAuthorizationStore( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictAuthorizationStore<>)); if (root == null) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictAuthorizationStore<>) // or closed generics (e.g OpenIddictAuthorizationStore). if (type.GetTypeInfo().IsGenericTypeDefinition) { if (type.GetGenericArguments().Length != 1) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictAuthorizationStore<>), type, lifetime)); } else { Services.Replace(new ServiceDescriptor(typeof(IOpenIddictAuthorizationStore<>) .MakeGenericType(root.GenericTypeArguments[0]), type, lifetime)); } return this; } /// /// Adds a custom scope store by a custom implementation derived /// from . /// Note: when using this overload, the scope store /// must be either a non-generic or closed generic service. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder AddScopeStore(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TStore : class => AddScopeStore(typeof(TStore), lifetime); /// /// Adds a custom scope store by a custom implementation derived /// from . /// Note: when using this overload, the scope store can be /// either a non-generic, a closed or an open generic service. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder AddScopeStore( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictScopeStore<>)); if (root == null) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictScopeStore<>) // or closed generics (e.g OpenIddictScopeStore). if (type.GetTypeInfo().IsGenericTypeDefinition) { if (type.GetGenericArguments().Length != 1) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictScopeStore<>), type, lifetime)); } else { Services.Replace(new ServiceDescriptor(typeof(IOpenIddictScopeStore<>) .MakeGenericType(root.GenericTypeArguments[0]), type, lifetime)); } return this; } /// /// Adds a custom token store by a custom implementation derived /// from . /// Note: when using this overload, the token store /// must be either a non-generic or closed generic service. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder AddTokenStore(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TStore : class => AddTokenStore(typeof(TStore), lifetime); /// /// Adds a custom token store by a custom implementation derived /// from . /// Note: when using this overload, the token store can be /// either a non-generic, a closed or an open generic service. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder AddTokenStore( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(IOpenIddictTokenStore<>)); if (root == null) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictTokenStore<>) // or closed generics (e.g OpenIddictTokenStore). if (type.GetTypeInfo().IsGenericTypeDefinition) { if (type.GetGenericArguments().Length != 1) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictTokenStore<>), type, lifetime)); } else { Services.Replace(new ServiceDescriptor(typeof(IOpenIddictTokenStore<>) .MakeGenericType(root.GenericTypeArguments[0]), type, lifetime)); } return this; } /// /// Replace the default application manager by a custom manager derived /// from . /// Note: when using this overload, the application manager /// must be either a non-generic or closed generic service. /// /// The type of the custom manager. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceApplicationManager(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TManager : class => ReplaceApplicationManager(typeof(TManager), lifetime); /// /// Replace the default application manager by a custom manager derived /// from . /// Note: when using this overload, the application manager can be /// either a non-generic, a closed or an open generic service. /// /// The type of the custom manager. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceApplicationManager( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictApplicationManager<>)); if (root == null) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictApplicationManager<>) // or closed generics (e.g OpenIddictApplicationManager). if (type.GetTypeInfo().IsGenericTypeDefinition) { if (type.GetGenericArguments().Length != 1) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(type, type, lifetime)); Services.Replace(new ServiceDescriptor(typeof(OpenIddictApplicationManager<>), type, lifetime)); } else { object ResolveManager(IServiceProvider provider) => provider.GetRequiredService(typeof(OpenIddictApplicationManager<>) .MakeGenericType(root.GenericTypeArguments[0])); Services.Replace(new ServiceDescriptor(type, ResolveManager, lifetime)); Services.Replace(new ServiceDescriptor(typeof(OpenIddictApplicationManager<>) .MakeGenericType(root.GenericTypeArguments[0]), type, lifetime)); } return this; } /// /// Replaces the default application store resolver by a custom implementation. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceApplicationStoreResolver(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TResolver : IOpenIddictApplicationStoreResolver => ReplaceApplicationStoreResolver(typeof(TResolver), lifetime); /// /// Replaces the default application store resolver by a custom implementation. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceApplicationStoreResolver( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (!typeof(IOpenIddictApplicationStoreResolver).IsAssignableFrom(type)) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictApplicationStoreResolver), type, lifetime)); return this; } /// /// Replace the default authorization manager by a custom manager derived /// from . /// Note: when using this overload, the authorization manager /// must be either a non-generic or closed generic service. /// /// The type of the custom manager. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceAuthorizationManager(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TManager : class => ReplaceAuthorizationManager(typeof(TManager), lifetime); /// /// Replace the default authorization manager by a custom manager derived /// from . /// Note: when using this overload, the authorization manager can be /// either a non-generic, a closed or an open generic service. /// /// The type of the custom manager. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceAuthorizationManager( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictAuthorizationManager<>)); if (root == null) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictAuthorizationManager<>) // or closed generics (e.g OpenIddictAuthorizationManager). if (type.GetTypeInfo().IsGenericTypeDefinition) { if (type.GetGenericArguments().Length != 1) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(type, type, lifetime)); Services.Replace(new ServiceDescriptor(typeof(OpenIddictAuthorizationManager<>), type, lifetime)); } else { object ResolveManager(IServiceProvider provider) => provider.GetRequiredService(typeof(OpenIddictAuthorizationManager<>) .MakeGenericType(root.GenericTypeArguments[0])); Services.Replace(new ServiceDescriptor(type, ResolveManager, lifetime)); Services.Replace(new ServiceDescriptor(typeof(OpenIddictAuthorizationManager<>) .MakeGenericType(root.GenericTypeArguments[0]), type, lifetime)); } return this; } /// /// Replaces the default authorization store resolver by a custom implementation. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceAuthorizationStoreResolver(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TResolver : IOpenIddictAuthorizationStoreResolver => ReplaceAuthorizationStoreResolver(typeof(TResolver), lifetime); /// /// Replaces the default authorization store resolver by a custom implementation. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceAuthorizationStoreResolver( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (!typeof(IOpenIddictAuthorizationStoreResolver).IsAssignableFrom(type)) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictAuthorizationStoreResolver), type, lifetime)); return this; } /// /// Replace the default scope manager by a custom manager /// derived from . /// Note: when using this overload, the scope manager /// must be either a non-generic or closed generic service. /// /// The type of the custom manager. /// The . public OpenIddictCoreBuilder ReplaceScopeManager(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TManager : class => ReplaceScopeManager(typeof(TManager), lifetime); /// /// Replace the default scope manager by a custom manager /// derived from . /// Note: when using this overload, the scope manager can be /// either a non-generic, a closed or an open generic service. /// /// The type of the custom manager. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceScopeManager( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictScopeManager<>)); if (root == null) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictScopeManager<>) // or closed generics (e.g OpenIddictScopeManager). if (type.GetTypeInfo().IsGenericTypeDefinition) { if (type.GetGenericArguments().Length != 1) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(type, type, lifetime)); Services.Replace(new ServiceDescriptor(typeof(OpenIddictScopeManager<>), type, lifetime)); } else { object ResolveManager(IServiceProvider provider) => provider.GetRequiredService(typeof(OpenIddictScopeManager<>) .MakeGenericType(root.GenericTypeArguments[0])); Services.Replace(new ServiceDescriptor(type, ResolveManager, lifetime)); Services.Replace(new ServiceDescriptor(typeof(OpenIddictScopeManager<>) .MakeGenericType(root.GenericTypeArguments[0]), type, lifetime)); } return this; } /// /// Replaces the default scope store resolver by a custom implementation. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceScopeStoreResolver(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TResolver : IOpenIddictScopeStoreResolver => ReplaceScopeStoreResolver(typeof(TResolver), lifetime); /// /// Replaces the default scope store resolver by a custom implementation. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceScopeStoreResolver( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (!typeof(IOpenIddictScopeStoreResolver).IsAssignableFrom(type)) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictScopeStoreResolver), type, lifetime)); return this; } /// /// Replace the default token manager by a custom manager /// derived from . /// Note: when using this overload, the token manager /// must be either a non-generic or closed generic service. /// /// The type of the custom manager. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceTokenManager(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TManager : class => ReplaceTokenManager(typeof(TManager), lifetime); /// /// Replace the default token manager by a custom manager /// derived from . /// Note: when using this overload, the token manager can be /// either a non-generic, a closed or an open generic service. /// /// The type of the custom manager. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceTokenManager( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } var root = OpenIddictHelpers.FindGenericBaseType(type, typeof(OpenIddictTokenManager<>)); if (root == null) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } // Note: managers can be either open generics (e.g OpenIddictTokenManager<>) // or closed generics (e.g OpenIddictTokenManager). if (type.GetTypeInfo().IsGenericTypeDefinition) { if (type.GetGenericArguments().Length != 1) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(type, type, lifetime)); Services.Replace(new ServiceDescriptor(typeof(OpenIddictTokenManager<>), type, lifetime)); } else { object ResolveManager(IServiceProvider provider) => provider.GetRequiredService(typeof(OpenIddictTokenManager<>) .MakeGenericType(root.GenericTypeArguments[0])); Services.Replace(new ServiceDescriptor(type, ResolveManager, lifetime)); Services.Replace(new ServiceDescriptor(typeof(OpenIddictTokenManager<>) .MakeGenericType(root.GenericTypeArguments[0]), type, lifetime)); } return this; } /// /// Replaces the default token store resolver by a custom implementation. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceTokenStoreResolver(ServiceLifetime lifetime = ServiceLifetime.Scoped) where TResolver : IOpenIddictTokenStoreResolver => ReplaceTokenStoreResolver(typeof(TResolver), lifetime); /// /// Replaces the default token store resolver by a custom implementation. /// /// The type of the custom store. /// The lifetime of the registered service. /// The . public OpenIddictCoreBuilder ReplaceTokenStoreResolver( [NotNull] Type type, ServiceLifetime lifetime = ServiceLifetime.Scoped) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (!typeof(IOpenIddictTokenStoreResolver).IsAssignableFrom(type)) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } Services.Replace(new ServiceDescriptor(typeof(IOpenIddictTokenStoreResolver), type, lifetime)); return this; } /// /// Configures OpenIddict to use the specified entity as the default application entity. /// /// The . public OpenIddictCoreBuilder SetDefaultApplicationEntity() where TApplication : class => SetDefaultApplicationEntity(typeof(TApplication)); /// /// Configures OpenIddict to use the specified entity as the default application entity. /// /// The application entity type. /// The . public OpenIddictCoreBuilder SetDefaultApplicationEntity([NotNull] Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (type.GetTypeInfo().IsValueType) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } return Configure(options => options.DefaultApplicationType = type); } /// /// Configures OpenIddict to use the specified entity as the default authorization entity. /// /// The . public OpenIddictCoreBuilder SetDefaultAuthorizationEntity() where TAuthorization : class => SetDefaultAuthorizationEntity(typeof(TAuthorization)); /// /// Configures OpenIddict to use the specified entity as the default authorization entity. /// /// The authorization entity type. /// The . public OpenIddictCoreBuilder SetDefaultAuthorizationEntity([NotNull] Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (type.GetTypeInfo().IsValueType) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } return Configure(options => options.DefaultAuthorizationType = type); } /// /// Configures OpenIddict to use the specified entity as the default scope entity. /// /// The . public OpenIddictCoreBuilder SetDefaultScopeEntity() where TScope : class => SetDefaultScopeEntity(typeof(TScope)); /// /// Configures OpenIddict to use the specified entity as the default scope entity. /// /// The scope entity type. /// The . public OpenIddictCoreBuilder SetDefaultScopeEntity([NotNull] Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (type.GetTypeInfo().IsValueType) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } return Configure(options => options.DefaultScopeType = type); } /// /// Configures OpenIddict to use the specified entity as the default token entity. /// /// The . public OpenIddictCoreBuilder SetDefaultTokenEntity() where TToken : class => SetDefaultTokenEntity(typeof(TToken)); /// /// Configures OpenIddict to use the specified entity as the default token entity. /// /// The token entity type. /// The . public OpenIddictCoreBuilder SetDefaultTokenEntity([NotNull] Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (type.GetTypeInfo().IsValueType) { throw new ArgumentException("The specified type is invalid.", nameof(type)); } return Configure(options => options.DefaultTokenType = type); } } }