Use DataProtectionTokenProvider from DI

Fixes https://github.com/aspnet/Identity/issues/224
This commit is contained in:
Hao Kung 2014-10-27 12:51:45 -07:00
parent 78b66382f9
commit cb3948b86f
23 changed files with 167 additions and 313 deletions

View File

@ -8,5 +8,13 @@
"IdentityConnection": {
"Connectionstring": "Server=(localdb)\\v11.0;Database=IdentityMvc-8-12-14;Trusted_Connection=True;MultipleActiveResultSets=true"
}
},
"Identity": {
"Password": {
"RequireDigit" : "false",
"RequireLowercase" : "false",
"RequireUppercase" : "false",
"RequireNonLetterOrDigit" : "false"
}
}
}

View File

@ -36,12 +36,8 @@ namespace IdentitySamples
options.DefaultAdminPassword = Configuration.Get("DefaultAdminPassword");
});
services.AddDefaultIdentity<ApplicationDbContext, ApplicationUser, IdentityRole>(Configuration, options =>
services.AddDefaultIdentity<ApplicationDbContext, ApplicationUser, IdentityRole>(Configuration.GetSubKey("Identity"), options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequireNonLetterOrDigit = false;
options.SecurityStampValidationInterval = TimeSpan.FromMinutes(20);
});

View File

@ -1,4 +1,5 @@
using Microsoft.AspNet.Security.DataProtection;
using Microsoft.Framework.OptionsModel;
using System;
using System.IO;
using System.Text;
@ -11,7 +12,6 @@ namespace Microsoft.AspNet.Identity
{
public string Name { get; set; } = "DataProtection";
public TimeSpan TokenLifespan { get; set; } = TimeSpan.FromDays(1);
}
/// <summary>
@ -19,18 +19,19 @@ namespace Microsoft.AspNet.Identity
/// </summary>
public class DataProtectorTokenProvider<TUser> : IUserTokenProvider<TUser> where TUser : class
{
public DataProtectorTokenProvider(DataProtectionTokenProviderOptions options, IDataProtector protector)
public DataProtectorTokenProvider(IDataProtectionProvider dataProtectionProvider, IOptions<DataProtectionTokenProviderOptions> options)
{
if (options == null)
if (options == null || options.Options == null)
{
throw new ArgumentNullException(nameof(options));
}
if (protector == null)
if (dataProtectionProvider == null)
{
throw new ArgumentNullException(nameof(protector));
throw new ArgumentNullException(nameof(dataProtectionProvider));
}
Options = options;
Protector = protector;
Options = options.Options;
// Use the Name as the purpose which should usually be distinct from others
Protector = dataProtectionProvider.CreateProtector(Name ?? "DataProtectorTokenProvider");
}
public DataProtectionTokenProviderOptions Options { get; private set; }

View File

@ -2,6 +2,7 @@ using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity
{
@ -24,14 +25,15 @@ namespace Microsoft.AspNet.Identity
public class EmailTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser>
where TUser : class
{
public EmailTokenProvider(EmailTokenProviderOptions options)
public EmailTokenProvider(IOptions<EmailTokenProviderOptions> options, string name = "")
{
Options = options;
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
Options = options.GetNamedOptions(name);
}
public EmailTokenProvider() : this(new EmailTokenProviderOptions()) { }
public EmailTokenProviderOptions Options { get; private set; }
public override string Name { get { return Options.Name; } }

View File

@ -43,9 +43,10 @@ namespace Microsoft.AspNet.Identity
return AddInstance(validator);
}
public IdentityBuilder<TUser, TRole> AddTokenProvider(IUserTokenProvider<TUser> tokenProvider)
public IdentityBuilder<TUser, TRole> AddTokenProvider<TTokenProvider>() where TTokenProvider : class, IUserTokenProvider<TUser>
{
return AddInstance(tokenProvider);
Services.AddScoped<IUserTokenProvider<TUser>, TTokenProvider>();
return this;
}
public IdentityBuilder<TUser, TRole> ConfigureIdentity(Action<IdentityOptions> action, int order = 0)

View File

@ -96,16 +96,14 @@ namespace Microsoft.Framework.DependencyInjection
where TUser : class
where TRole : class
{
return services.AddIdentity<TUser, TRole>(config, configureOptions)
.AddTokenProvider(new DataProtectorTokenProvider<TUser>(
new DataProtectionTokenProviderOptions
{
Name = Resources.DefaultTokenProvider,
},
// TODO: This needs to get IDataProtectionProvider from the environment
new EphemeralDataProtectionProvider().CreateProtector("ASP.NET Identity")))
.AddTokenProvider(new PhoneNumberTokenProvider<TUser>())
.AddTokenProvider(new EmailTokenProvider<TUser>());
services.Configure<DataProtectionTokenProviderOptions>(options =>
{
options.Name = Resources.DefaultTokenProvider;
});
return services.AddIdentity<TUser, TRole>(config)
.AddTokenProvider<DataProtectorTokenProvider<TUser>>()
.AddTokenProvider<PhoneNumberTokenProvider<TUser>>()
.AddTokenProvider<EmailTokenProvider<TUser>>();
}
public static IdentityBuilder<TUser, IdentityRole> AddIdentity<TUser>(this IServiceCollection services)

View File

@ -2,6 +2,7 @@ using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity
{
@ -12,7 +13,7 @@ namespace Microsoft.AspNet.Identity
/// <summary>
/// Message contents which should contain a format string which the token will be the only argument
/// </summary>
public string MessageFormat { get; set; } = "Your security code is: {0}";
public string MessageFormat { get; set; } = Resources.DefaultPhoneNumberTokenProviderMessageFormat;
}
/// <summary>
@ -22,14 +23,15 @@ namespace Microsoft.AspNet.Identity
public class PhoneNumberTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser>
where TUser : class
{
public PhoneNumberTokenProvider(PhoneNumberTokenProviderOptions options)
public PhoneNumberTokenProvider(IOptions<PhoneNumberTokenProviderOptions> options)
{
Options = options;
if (options == null || options.Options == null)
{
throw new ArgumentNullException(nameof(options));
}
Options = options.Options;
}
public PhoneNumberTokenProvider() : this(new PhoneNumberTokenProviderOptions()) { }
public PhoneNumberTokenProviderOptions Options { get; private set; }
public override string Name { get { return Options.Name; } }

View File

@ -10,7 +10,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
using Microsoft.AspNet.Security.DataProtection;
namespace Microsoft.AspNet.Identity
{

View File

@ -20,14 +20,10 @@ namespace Microsoft.AspNet.Identity
where TRole : IdentityRole
where TDbContext : DbContext
{
var builder = services.AddIdentity<TUser, TRole>();
var builder = services.AddDefaultIdentity<TUser, TRole>();
services.AddInstance<IUserStore<TUser>>(new InMemoryUserStore<TUser, TDbContext>(context));
var store = new RoleStore<TRole, TDbContext>(context);
services.AddInstance<IRoleStore<TRole>>(store);
//services.AddInstance(context);
//services.AddScoped<TDbContext>();
//services.AddScoped<IUserStore<TUser>, InMemoryUserStore<TUser, TDbContext>>();
//services.AddScoped<IRoleStore<TRole>, RoleStore<TRole, TDbContext>>();
return builder;
}
}

View File

@ -3,8 +3,6 @@
using Microsoft.AspNet.Identity.Test;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
{
@ -15,38 +13,15 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
return new InMemoryContext();
}
protected override UserManager<IdentityUser> CreateManager(object context)
protected override void AddUserStore(IServiceCollection services, object context = null)
{
if (context == null)
{
context = CreateTestContext();
}
var services = new ServiceCollection();
services.Add(OptionsServices.GetDefaultServices());
services.AddEntityFramework().AddInMemoryStore();
services.AddIdentityInMemory((InMemoryContext)context);
services.ConfigureIdentity(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonLetterOrDigit = false;
options.Password.RequireUppercase = false;
options.User.UserNameValidationRegex = null;
});
return services.BuildServiceProvider().GetRequiredService<UserManager<IdentityUser>>();
services.AddInstance<IUserStore<IdentityUser>>(new InMemoryUserStore<IdentityUser, InMemoryContext>((InMemoryContext)context));
}
protected override RoleManager<IdentityRole> CreateRoleManager(object context)
protected override void AddRoleStore(IServiceCollection services, object context = null)
{
if (context == null)
{
context = CreateTestContext();
}
var services = new ServiceCollection();
services.Add(OptionsServices.GetDefaultServices());
services.AddEntityFramework().AddInMemoryStore();
services.AddIdentityInMemory((InMemoryContext)context);
return services.BuildServiceProvider().GetRequiredService<RoleManager<IdentityRole>>();
var store = new RoleStore<IdentityRole, InMemoryContext>((InMemoryContext)context);
services.AddInstance<IRoleStore<IdentityRole>>(store);
}
}
}

View File

@ -23,20 +23,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
return db;
}
public static UserManager<IdentityUser> CreateManager(InMemoryContext context)
{
return MockHelpers.CreateManager<IdentityUser>(new InMemoryUserStore<IdentityUser>(context));
}
public static UserManager<IdentityUser> CreateManager()
{
return CreateManager(CreateContext());
}
public static RoleManager<IdentityRole> CreateRoleManager(InMemoryContext context)
{
var services = new ServiceCollection();
services.AddIdentity().AddRoleStore(new RoleStore<IdentityRole>(context));
services.AddDefaultIdentity<IdentityUser, IdentityRole>().AddRoleStore(new RoleStore<IdentityRole>(context));
return services.BuildServiceProvider().GetRequiredService<RoleManager<IdentityRole>>();
}

View File

@ -1,5 +1,6 @@
{
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.Http": "1.0.0-*",
"Microsoft.AspNet.Identity": "3.0.0-*",
"Microsoft.AspNet.Identity.EntityFramework": "3.0.0-*",

View File

@ -7,13 +7,14 @@ using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Identity.Test;
using Microsoft.Data.Entity;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
using Xunit;
namespace Microsoft.AspNet.Identity.EntityFramework.Test
{
public abstract class SqlStoreTestBase<TUser, TRole, TKey> : UserManagerTestBase<TUser, TRole, TKey>
where TUser : IdentityUser<TKey>, new()
where TRole : IdentityRole<TKey>, new()
@ -59,24 +60,14 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
return CreateContext();
}
protected override UserManager<TUser> CreateManager(object context = null)
protected override void AddUserStore(IServiceCollection services, object context = null)
{
if (context == null)
{
context = CreateTestContext();
}
return MockHelpers.CreateManager(new UserStore<TUser, TRole, TestDbContext, TKey>((TestDbContext)context));
services.AddInstance<IUserStore<TUser>>(new UserStore<TUser, TRole, TestDbContext, TKey>((TestDbContext)context));
}
protected override RoleManager<TRole> CreateRoleManager(object context = null)
protected override void AddRoleStore(IServiceCollection services, object context = null)
{
var services = DbUtil.ConfigureDbServices<TestDbContext>(ConnectionString);
if (context == null)
{
context = CreateTestContext();
}
services.AddIdentity<TUser, TRole>().AddRoleStore(new RoleStore<TRole, TestDbContext, TKey>((TestDbContext)context));
return services.BuildServiceProvider().GetRequiredService<RoleManager<TRole>>();
services.AddInstance<IRoleStore<TRole>>(new RoleStore<TRole, TestDbContext, TKey>((TestDbContext)context));
}
public void EnsureDatabase()

View File

@ -4,7 +4,6 @@
using System;
using Microsoft.AspNet.Identity.Test;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Xunit;
namespace Microsoft.AspNet.Identity.EntityFramework.Test
@ -60,24 +59,14 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
}
}
protected override UserManager<GuidUser> CreateManager(object context)
protected override void AddUserStore(IServiceCollection services, object context = null)
{
if (context == null)
{
context = CreateTestContext();
}
return MockHelpers.CreateManager(new ApplicationUserStore((TestDbContext)context));
services.AddInstance<IUserStore<GuidUser>>(new ApplicationUserStore((TestDbContext)context));
}
protected override RoleManager<GuidRole> CreateRoleManager(object context)
protected override void AddRoleStore(IServiceCollection services, object context = null)
{
if (context == null)
{
context = CreateTestContext();
}
var services = DbUtil.ConfigureDbServices(ConnectionString);
services.AddIdentity<GuidUser, GuidRole>().AddRoleStore(new ApplicationRoleStore((TestDbContext)context));
return services.BuildServiceProvider().GetRequiredService<RoleManager<GuidRole>>();
services.AddInstance<IRoleStore<GuidRole>>(new ApplicationRoleStore((TestDbContext)context));
}
}
}

View File

@ -16,11 +16,11 @@ using Xunit;
namespace Microsoft.AspNet.Identity.EntityFramework.Test
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { }
[TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")]
public class UserStoreTest : UserManagerTestBase<IdentityUser, IdentityRole>
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { }
private readonly string ConnectionString = @"Server=(localdb)\v11.0;Database=SqlUserStoreTest" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ";Trusted_Connection=True;";
[TestPriority(-1000)]
@ -145,34 +145,14 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
return db;
}
public static UserManager<IdentityUser> CreateManager(DbContext context)
protected override void AddUserStore(IServiceCollection services, object context = null)
{
return MockHelpers.CreateManager(new UserStore<IdentityUser>(context));
services.AddInstance<IUserStore<IdentityUser>>(new UserStore<IdentityUser, IdentityRole, IdentityDbContext>((IdentityDbContext)context));
}
protected override UserManager<IdentityUser> CreateManager(object context = null)
protected override void AddRoleStore(IServiceCollection services, object context = null)
{
if (context == null)
{
context = CreateTestContext();
}
return CreateManager((DbContext)context);
}
public RoleManager<IdentityRole> CreateRoleManager(IdentityDbContext context)
{
var services = DbUtil.ConfigureDbServices(ConnectionString);
services.AddIdentity().AddRoleStore(new RoleStore<IdentityRole>(context));
return services.BuildServiceProvider().GetRequiredService<RoleManager<IdentityRole>>();
}
protected override RoleManager<IdentityRole> CreateRoleManager(object context)
{
if (context == null)
{
context = CreateTestContext();
}
return CreateRoleManager((IdentityDbContext)context);
services.AddInstance<IRoleStore<IdentityRole>>(new RoleStore<IdentityRole, IdentityDbContext>((IdentityDbContext)context));
}
[Fact]

View File

@ -36,7 +36,9 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
app.UseServices(services =>
{
services.AddInstance(contextAccessor.Object);
services.AddIdentity<ApplicationUser, IdentityRole>().AddInMemory();
services.AddIdentity<ApplicationUser, IdentityRole>();
services.AddSingleton<IUserStore<ApplicationUser>, InMemoryUserStore<ApplicationUser>>();
services.AddSingleton<IRoleStore<IdentityRole>, InMemoryRoleStore<IdentityRole>>();
});
// Act

View File

@ -1,22 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Identity.InMemory;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Identity
{
public static class IdentityBuilderExtensions
{
public static IdentityBuilder<TUser, TRole> AddInMemory<TUser, TRole>(this IdentityBuilder<TUser, TRole> builder)
where TUser : IdentityUser
where TRole : IdentityRole
{
builder.Services.AddSingleton<IUserStore<TUser>, InMemoryUserStore<TUser>>();
builder.Services.AddScoped<UserManager<TUser>, UserManager<TUser>>();
builder.Services.AddSingleton<IRoleStore<TRole>, InMemoryRoleStore<TRole>>();
builder.Services.AddScoped<RoleManager<TRole>, RoleManager<TRole>>();
return builder;
}
}
}

View File

@ -1,11 +1,8 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Identity.Test;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity.InMemory.Test
{
@ -16,27 +13,14 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
return null;
}
protected override UserManager<IdentityUser> CreateManager(object context)
protected override void AddUserStore(IServiceCollection services, object context = null)
{
var services = new ServiceCollection();
services.Add(OptionsServices.GetDefaultServices());
services.AddIdentity().AddInMemory();
services.ConfigureIdentity(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonLetterOrDigit = false;
options.Password.RequireUppercase = false;
options.User.UserNameValidationRegex = null;
});
return services.BuildServiceProvider().GetRequiredService<UserManager<IdentityUser>>();
services.AddSingleton<IUserStore<IdentityUser>, InMemoryUserStore<IdentityUser>>();
}
protected override RoleManager<IdentityRole> CreateRoleManager(object context)
protected override void AddRoleStore(IServiceCollection services, object context = null)
{
var services = new ServiceCollection();
services.AddIdentity().AddInMemory();
return services.BuildServiceProvider().GetRequiredService<RoleManager<IdentityRole>>();
services.AddSingleton<IRoleStore<IdentityRole>, InMemoryRoleStore<IdentityRole>>();
}
}
}

View File

@ -1,82 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Identity.Test;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
using System;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNet.Identity.InMemory.Test
{
public class StartupTest
{
public class ApplicationUser : IdentityUser { }
[Fact]
public async Task EnsureStartupUsageWorks()
{
var builder = new ApplicationBuilder(new ServiceCollection().BuildServiceProvider());
builder.UseServices(services => services.AddIdentity<ApplicationUser>().AddInMemory());
var userStore = builder.ApplicationServices.GetRequiredService<IUserStore<ApplicationUser>>();
var roleStore = builder.ApplicationServices.GetRequiredService<IRoleStore<IdentityRole>>();
var userManager = builder.ApplicationServices.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = builder.ApplicationServices.GetRequiredService<RoleManager<IdentityRole>>();
Assert.NotNull(userStore);
Assert.NotNull(userManager);
Assert.NotNull(roleStore);
Assert.NotNull(roleManager);
await CreateAdminUser(builder.ApplicationServices);
}
[Fact]
public void VerifyUseInMemoryLifetimes()
{
var builder = new ApplicationBuilder(new ServiceCollection().BuildServiceProvider());
builder.UseServices(services => services.AddIdentity<ApplicationUser>().AddInMemory());
var userStore = builder.ApplicationServices.GetRequiredService<IUserStore<ApplicationUser>>();
var roleStore = builder.ApplicationServices.GetRequiredService<IRoleStore<IdentityRole>>();
var userManager = builder.ApplicationServices.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = builder.ApplicationServices.GetRequiredService<RoleManager<IdentityRole>>();
Assert.NotNull(userStore);
Assert.NotNull(userManager);
Assert.NotNull(roleStore);
Assert.NotNull(roleManager);
var userStore2 = builder.ApplicationServices.GetRequiredService<IUserStore<ApplicationUser>>();
var roleStore2 = builder.ApplicationServices.GetRequiredService<IRoleStore<IdentityRole>>();
var userManager2 = builder.ApplicationServices.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager2 = builder.ApplicationServices.GetRequiredService<RoleManager<IdentityRole>>();
// Stores are singleton, managers are scoped
Assert.Equal(userStore, userStore2);
Assert.Equal(userManager, userManager2);
Assert.Equal(roleStore, roleStore2);
Assert.Equal(roleManager, roleManager2);
}
private static async Task CreateAdminUser(IServiceProvider serviceProvider)
{
const string userName = "admin";
const string roleName = "Admins";
const string password = "1qaz@WSX";
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var user = new ApplicationUser { UserName = userName };
IdentityResultAssert.IsSuccess(await userManager.CreateAsync(user, password));
IdentityResultAssert.IsSuccess(await roleManager.CreateAsync(new IdentityRole { Name = roleName }));
IdentityResultAssert.IsSuccess(await userManager.AddToRoleAsync(user, roleName));
}
}
}

View File

@ -1,5 +1,6 @@
{
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.Http" : "1.0.0-*",
"Microsoft.AspNet.Identity" : "3.0.0-*",
"Microsoft.AspNet.PipelineCore" : "1.0.0-*",

View File

@ -1,5 +1,6 @@
{
"dependencies": {
"Microsoft.AspNet.Hosting" : "1.0.0-*",
"Microsoft.AspNet.Http" : "1.0.0-*",
"Microsoft.AspNet.Identity" : "3.0.0-*",
"Microsoft.AspNet.PipelineCore" : "1.0.0-*",

View File

@ -1,34 +1,35 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Hosting;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
using Moq;
using System;
using System.Collections.Generic;
namespace Microsoft.AspNet.Identity.Test
{
public static class MockHelpers
{
public static UserManager<TUser> CreateManager<TUser>(IUserStore<TUser> store) where TUser : class
{
var services = new ServiceCollection();
services.Add(OptionsServices.GetDefaultServices());
services.AddIdentity<TUser>().AddUserStore(store);
services.ConfigureIdentity(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonLetterOrDigit = false;
options.Password.RequireUppercase = false;
options.User.UserNameValidationRegex = null;
});
return services.BuildServiceProvider().GetService<UserManager<TUser>>();
}
//public static UserManager<TUser> CreateManager<TUser>(IUserStore<TUser> store) where TUser : class
//{
// var services = new ServiceCollection();
// services.Add(OptionsServices.GetDefaultServices());
// services.Add(HostingServices.GetDefaultServices());
// services.AddDefaultIdentity<TUser, IdentityRole>().AddUserStore(store);
// services.ConfigureIdentity(options =>
// {
// options.Password.RequireDigit = false;
// options.Password.RequireLowercase = false;
// options.Password.RequireNonLetterOrDigit = false;
// options.Password.RequireUppercase = false;
// options.User.UserNameValidationRegex = null;
// });
// return services.BuildServiceProvider().GetService<UserManager<TUser>>();
//}
public static Mock<UserManager<TUser>> MockUserManager<TUser>() where TUser : class
{

View File

@ -10,10 +10,13 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Testing;
using Xunit;
using Microsoft.AspNet.Security.DataProtection;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Microsoft.AspNet.Hosting;
using Microsoft.Framework.DependencyInjection.Fallback;
namespace Microsoft.AspNet.Identity.Test
{
// Common functionality tests that all verifies user manager functionality regardless of store implementation
public abstract class UserManagerTestBase<TUser, TRole> : UserManagerTestBase<TUser, TRole, string>
where TUser : IdentityUser, new()
@ -25,10 +28,57 @@ namespace Microsoft.AspNet.Identity.Test
where TRole: IdentityRole<TKey>, new()
where TKey : IEquatable<TKey>
{
protected abstract UserManager<TUser> CreateManager(object context = null);
protected abstract RoleManager<TRole> CreateRoleManager(object context = null);
protected virtual void SetupIdentityServices(IServiceCollection services, object context = null)
{
services.Add(OptionsServices.GetDefaultServices());
services.Add(HostingServices.GetDefaultServices());
services.AddDefaultIdentity<TUser, TRole>();
AddUserStore(services, context);
AddRoleStore(services, context);
services.ConfigureIdentity(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonLetterOrDigit = false;
options.Password.RequireUppercase = false;
options.User.UserNameValidationRegex = null;
});
}
protected virtual UserManager<TUser> CreateManager(object context = null, IServiceCollection services = null)
{
if (services == null)
{
services = new ServiceCollection();
}
if (context == null)
{
context = CreateTestContext();
}
SetupIdentityServices(services, context);
return services.BuildServiceProvider().GetService<UserManager<TUser>>();
}
protected RoleManager<TRole> CreateRoleManager(object context = null, IServiceCollection services = null)
{
if (services == null)
{
services = new ServiceCollection();
}
if (context == null)
{
context = CreateTestContext();
}
SetupIdentityServices(services, context);
return services.BuildServiceProvider().GetService<RoleManager<TRole>>();
}
protected abstract object CreateTestContext();
protected abstract void AddUserStore(IServiceCollection services, object context = null);
protected abstract void AddRoleStore(IServiceCollection services, object context = null);
protected TUser CreateTestUser(string namePrefix = "") {
return new TUser() { UserName = namePrefix + Guid.NewGuid().ToString() };
}
@ -551,9 +601,6 @@ namespace Microsoft.AspNet.Identity.Test
public async Task ConfirmTokenFailsAfterPasswordChange()
{
var manager = CreateManager();
manager.RegisterTokenProvider(new DataProtectorTokenProvider<TUser>(new DataProtectionTokenProviderOptions(),
new EphemeralDataProtectionProvider().CreateProtector("ASP.NET Identity")));
manager.Options.EmailConfirmationTokenProvider = "DataProtection";
var user = new TUser() { UserName = "test" };
Assert.False(user.EmailConfirmed);
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
@ -1144,8 +1191,7 @@ namespace Microsoft.AspNet.Identity.Test
var manager = CreateManager();
var messageService = new TestMessageService();
manager.EmailService = messageService;
const string factorId = "Email";
manager.RegisterTokenProvider(new EmailTokenProvider<TUser>());
const string factorId = "Email"; // default
var user = new TUser() { UserName = "EmailCodeTest", Email = "foo@foo.com" };
user.EmailConfirmed = true;
const string password = "password";
@ -1176,18 +1222,20 @@ namespace Microsoft.AspNet.Identity.Test
[Fact]
public async Task EmailTokenFactorWithFormatTest()
{
var manager = CreateManager();
var messageService = new TestMessageService();
manager.EmailService = messageService;
const string factorId = "EmailTestCode";
// CONSIDER: do we want to support multiple email token options?
const string factorId = "Email"; // default
const string subject = "Custom subject";
const string body = "Your code is {0}!";
manager.RegisterTokenProvider(new EmailTokenProvider<TUser>(new EmailTokenProviderOptions
var services = new ServiceCollection();
services.Configure<EmailTokenProviderOptions>(o =>
{
Name = factorId,
Subject = subject,
BodyFormat = body
}));
o.Name = factorId;
o.Subject = subject;
o.BodyFormat = body;
});
var manager = CreateManager(null, services);
var messageService = new TestMessageService();
manager.EmailService = messageService;
var user = CreateTestUser();
user.Email = user.UserName + "@foo.com";
const string password = "password";
@ -1209,7 +1257,6 @@ namespace Microsoft.AspNet.Identity.Test
{
var manager = CreateManager();
string factorId = "Email"; //default
manager.RegisterTokenProvider(new EmailTokenProvider<TUser>());
var user = CreateTestUser();
user.Email = user.UserName + "@foo.com";
user.EmailConfirmed = true;
@ -1222,7 +1269,6 @@ namespace Microsoft.AspNet.Identity.Test
Assert.False(await manager.VerifyTwoFactorTokenAsync(user, factorId, token));
}
[Fact]
public async Task EnableTwoFactorChangesSecurityStamp()
{
@ -1272,7 +1318,6 @@ namespace Microsoft.AspNet.Identity.Test
var messageService = new TestMessageService();
manager.SmsService = messageService;
const string factorId = "Phone"; // default
manager.RegisterTokenProvider(new PhoneNumberTokenProvider<TUser>());
var user = CreateTestUser();
user.PhoneNumber = "4251234567";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@ -1290,15 +1335,16 @@ namespace Microsoft.AspNet.Identity.Test
[Fact]
public async Task PhoneTokenFactorFormatTest()
{
var manager = CreateManager();
const string factorId = "Phone"; // default
var services = new ServiceCollection();
services.Configure<PhoneNumberTokenProviderOptions>(o =>
{
o.Name = factorId;
o.MessageFormat = "Your code is: {0}";
});
var manager = CreateManager(null, services);
var messageService = new TestMessageService();
manager.SmsService = messageService;
const string factorId = "PhoneTestFactors";
manager.RegisterTokenProvider(new PhoneNumberTokenProvider<TUser>(new PhoneNumberTokenProviderOptions
{
Name = factorId,
MessageFormat = "Your code is: {0}"
}));
var user = CreateTestUser();
user.PhoneNumber = "4251234567";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@ -1342,8 +1388,6 @@ namespace Microsoft.AspNet.Identity.Test
public async Task CanGetValidTwoFactor()
{
var manager = CreateManager();
manager.RegisterTokenProvider(new PhoneNumberTokenProvider<TUser>());
manager.RegisterTokenProvider(new EmailTokenProvider<TUser>());
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
var factors = await manager.GetValidTwoFactorProvidersAsync(user);
@ -1374,7 +1418,6 @@ namespace Microsoft.AspNet.Identity.Test
{
var manager = CreateManager();
var factorId = "Phone"; // default
manager.RegisterTokenProvider(new PhoneNumberTokenProvider<TUser>());
var user = CreateTestUser();
user.PhoneNumber = "4251234567";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@ -1390,8 +1433,6 @@ namespace Microsoft.AspNet.Identity.Test
public async Task VerifyTokenFromWrongTokenProviderFails()
{
var manager = CreateManager();
manager.RegisterTokenProvider(new PhoneNumberTokenProvider<TUser>());
manager.RegisterTokenProvider(new EmailTokenProvider<TUser>());
var user = CreateTestUser();
user.PhoneNumber = "4251234567";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@ -1404,7 +1445,6 @@ namespace Microsoft.AspNet.Identity.Test
public async Task VerifyWithWrongSmsTokenFails()
{
var manager = CreateManager();
manager.RegisterTokenProvider(new PhoneNumberTokenProvider<TUser>());
var user = CreateTestUser();
user.PhoneNumber = "4251234567";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));