// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.AspNetCore.Identity { /// /// Helper functions for configuring identity services. /// public class IdentityBuilder { /// /// Creates a new instance of . /// /// The to use for the users. /// The to use for the roles. /// The to attach to. public IdentityBuilder(Type user, Type role, IServiceCollection services) { UserType = user; RoleType = role; Services = services; } /// /// Gets the used for users. /// /// /// The used for users. /// public Type UserType { get; private set; } /// /// Gets the used for roles. /// /// /// The used for roles. /// public Type RoleType { get; private set; } /// /// Gets the services are attached to. /// /// /// The services are attached to. /// public IServiceCollection Services { get; private set; } private IdentityBuilder AddScoped(Type serviceType, Type concreteType) { Services.AddScoped(serviceType, concreteType); return this; } /// /// Adds an for the . /// /// The user validator type. /// The current instance. public virtual IdentityBuilder AddUserValidator() where T : class { return AddScoped(typeof(IUserValidator<>).MakeGenericType(UserType), typeof(T)); } /// /// Adds an for the . /// /// The role validator type. /// The current instance. public virtual IdentityBuilder AddRoleValidator() where T : class { return AddScoped(typeof(IRoleValidator<>).MakeGenericType(RoleType), typeof(T)); } /// /// Adds an for the . /// /// The type of the claims principal factory. /// The current instance. public virtual IdentityBuilder AddClaimsPrincipalFactory() where T : class { return AddScoped(typeof(IUserClaimsPrincipalFactory<>).MakeGenericType(UserType), typeof(T)); } /// /// Adds an . /// /// The type of the error describer. /// The current instance. public virtual IdentityBuilder AddErrorDescriber() where TDescriber : IdentityErrorDescriber { Services.AddScoped(); return this; } /// /// Adds an for the . /// /// The user type whose password will be validated. /// The current instance. public virtual IdentityBuilder AddPasswordValidator() where T : class { return AddScoped(typeof(IPasswordValidator<>).MakeGenericType(UserType), typeof(T)); } /// /// Adds an for the . /// /// The user type whose password will be validated. /// The current instance. public virtual IdentityBuilder AddUserStore() where T : class { return AddScoped(typeof(IUserStore<>).MakeGenericType(UserType), typeof(T)); } /// /// Adds a for the . /// /// The role type held in the store. /// The current instance. public virtual IdentityBuilder AddRoleStore() where T : class { return AddScoped(typeof(IRoleStore<>).MakeGenericType(RoleType), typeof(T)); } /// /// Adds a token provider. /// /// The type of the token provider to add. /// The name of the provider to add. /// The current instance. public virtual IdentityBuilder AddTokenProvider(string providerName) where TProvider : class { return AddTokenProvider(providerName, typeof(TProvider)); } /// /// Adds a token provider for the . /// /// The name of the provider to add. /// The type of the to add. /// The current instance. public virtual IdentityBuilder AddTokenProvider(string providerName, Type provider) { if (!typeof(IUserTwoFactorTokenProvider<>).MakeGenericType(UserType).GetTypeInfo().IsAssignableFrom(provider.GetTypeInfo())) { throw new InvalidOperationException(Resources.FormatInvalidManagerType(provider.Name, "IUserTokenProvider", UserType.Name)); } Services.Configure(options => { options.Tokens.ProviderMap[providerName] = new TokenProviderDescriptor(provider); }); Services.AddTransient(provider); return this; } /// /// Adds the default token providers used to generate tokens for reset passwords, change email /// and change telephone number operations, and for two factor authentication token generation. /// /// The current instance. public virtual IdentityBuilder AddDefaultTokenProviders() { var dataProtectionProviderType = typeof(DataProtectorTokenProvider<>).MakeGenericType(UserType); var phoneNumberProviderType = typeof(PhoneNumberTokenProvider<>).MakeGenericType(UserType); var emailTokenProviderType = typeof(EmailTokenProvider<>).MakeGenericType(UserType); return AddTokenProvider(TokenOptions.DefaultProvider, dataProtectionProviderType) .AddTokenProvider(TokenOptions.DefaultEmailProvider, emailTokenProviderType) .AddTokenProvider(TokenOptions.DefaultPhoneProvider, phoneNumberProviderType); } /// /// Adds a for the . /// /// The type of the user manager to add. /// The current instance. public virtual IdentityBuilder AddUserManager() where TUserManager : class { var userManagerType = typeof(UserManager<>).MakeGenericType(UserType); var customType = typeof(TUserManager); if (userManagerType == customType || !userManagerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo())) { throw new InvalidOperationException(Resources.FormatInvalidManagerType(customType.Name, "UserManager", UserType.Name)); } Services.AddScoped(customType, services => services.GetRequiredService(userManagerType)); return AddScoped(userManagerType, customType); } /// /// Adds a for the . /// /// The type of the role manager to add. /// The current instance. public virtual IdentityBuilder AddRoleManager() where TRoleManager : class { var managerType = typeof(RoleManager<>).MakeGenericType(RoleType); var customType = typeof(TRoleManager); if (managerType == customType || !managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo())) { throw new InvalidOperationException(Resources.FormatInvalidManagerType(customType.Name, "RoleManager", RoleType.Name)); } Services.AddScoped(typeof(TRoleManager), services => services.GetRequiredService(managerType)); return AddScoped(managerType, typeof(TRoleManager)); } /// /// Adds a for the . /// /// The type of the sign in manager to add. /// The current instance. public virtual IdentityBuilder AddSignInManager() where TSignInManager : class { var managerType = typeof(SignInManager<>).MakeGenericType(UserType); var customType = typeof(TSignInManager); if (managerType == customType || !managerType.GetTypeInfo().IsAssignableFrom(customType.GetTypeInfo())) { throw new InvalidOperationException(Resources.FormatInvalidManagerType(customType.Name, "SignInManager", UserType.Name)); } Services.AddScoped(typeof(TSignInManager), services => services.GetRequiredService(managerType)); return AddScoped(managerType, typeof(TSignInManager)); } } }