/*
* 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);
}
}
}