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": { "IdentityConnection": {
"Connectionstring": "Server=(localdb)\\v11.0;Database=IdentityMvc-8-12-14;Trusted_Connection=True;MultipleActiveResultSets=true" "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"); 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); options.SecurityStampValidationInterval = TimeSpan.FromMinutes(20);
}); });

View File

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

View File

@ -2,6 +2,7 @@ using System;
using System.Globalization; using System.Globalization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
{ {
@ -24,14 +25,15 @@ namespace Microsoft.AspNet.Identity
public class EmailTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser> public class EmailTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser>
where TUser : class 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 EmailTokenProviderOptions Options { get; private set; }
public override string Name { get { return Options.Name; } } public override string Name { get { return Options.Name; } }

View File

@ -43,9 +43,10 @@ namespace Microsoft.AspNet.Identity
return AddInstance(validator); 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) 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 TUser : class
where TRole : class where TRole : class
{ {
return services.AddIdentity<TUser, TRole>(config, configureOptions) services.Configure<DataProtectionTokenProviderOptions>(options =>
.AddTokenProvider(new DataProtectorTokenProvider<TUser>( {
new DataProtectionTokenProviderOptions options.Name = Resources.DefaultTokenProvider;
{ });
Name = Resources.DefaultTokenProvider, return services.AddIdentity<TUser, TRole>(config)
}, .AddTokenProvider<DataProtectorTokenProvider<TUser>>()
// TODO: This needs to get IDataProtectionProvider from the environment .AddTokenProvider<PhoneNumberTokenProvider<TUser>>()
new EphemeralDataProtectionProvider().CreateProtector("ASP.NET Identity"))) .AddTokenProvider<EmailTokenProvider<TUser>>();
.AddTokenProvider(new PhoneNumberTokenProvider<TUser>())
.AddTokenProvider(new EmailTokenProvider<TUser>());
} }
public static IdentityBuilder<TUser, IdentityRole> AddIdentity<TUser>(this IServiceCollection services) public static IdentityBuilder<TUser, IdentityRole> AddIdentity<TUser>(this IServiceCollection services)

View File

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

View File

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

View File

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

View File

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

View File

@ -23,20 +23,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
return db; 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) public static RoleManager<IdentityRole> CreateRoleManager(InMemoryContext context)
{ {
var services = new ServiceCollection(); 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>>(); return services.BuildServiceProvider().GetRequiredService<RoleManager<IdentityRole>>();
} }

View File

@ -1,5 +1,6 @@
{ {
"dependencies": { "dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.Http": "1.0.0-*", "Microsoft.AspNet.Http": "1.0.0-*",
"Microsoft.AspNet.Identity": "3.0.0-*", "Microsoft.AspNet.Identity": "3.0.0-*",
"Microsoft.AspNet.Identity.EntityFramework": "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 System.Threading.Tasks;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Identity.Test; using Microsoft.AspNet.Identity.Test;
using Microsoft.Data.Entity;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback; using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Identity.EntityFramework.Test namespace Microsoft.AspNet.Identity.EntityFramework.Test
{ {
public abstract class SqlStoreTestBase<TUser, TRole, TKey> : UserManagerTestBase<TUser, TRole, TKey> public abstract class SqlStoreTestBase<TUser, TRole, TKey> : UserManagerTestBase<TUser, TRole, TKey>
where TUser : IdentityUser<TKey>, new() where TUser : IdentityUser<TKey>, new()
where TRole : IdentityRole<TKey>, new() where TRole : IdentityRole<TKey>, new()
@ -59,24 +60,14 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
return CreateContext(); return CreateContext();
} }
protected override UserManager<TUser> CreateManager(object context = null) protected override void AddUserStore(IServiceCollection services, object context = null)
{ {
if (context == null) services.AddInstance<IUserStore<TUser>>(new UserStore<TUser, TRole, TestDbContext, TKey>((TestDbContext)context));
{
context = CreateTestContext();
}
return MockHelpers.CreateManager(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); services.AddInstance<IRoleStore<TRole>>(new RoleStore<TRole, TestDbContext, TKey>((TestDbContext)context));
if (context == null)
{
context = CreateTestContext();
}
services.AddIdentity<TUser, TRole>().AddRoleStore(new RoleStore<TRole, TestDbContext, TKey>((TestDbContext)context));
return services.BuildServiceProvider().GetRequiredService<RoleManager<TRole>>();
} }
public void EnsureDatabase() public void EnsureDatabase()

View File

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

View File

@ -16,11 +16,11 @@ using Xunit;
namespace Microsoft.AspNet.Identity.EntityFramework.Test namespace Microsoft.AspNet.Identity.EntityFramework.Test
{ {
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { }
[TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")] [TestCaseOrderer("Microsoft.AspNet.Identity.Test.PriorityOrderer", "Microsoft.AspNet.Identity.EntityFramework.Test")]
public class UserStoreTest : UserManagerTestBase<IdentityUser, IdentityRole> 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;"; private readonly string ConnectionString = @"Server=(localdb)\v11.0;Database=SqlUserStoreTest" + DateTime.Now.Month + "-" + DateTime.Now.Day + "-" + DateTime.Now.Year + ";Trusted_Connection=True;";
[TestPriority(-1000)] [TestPriority(-1000)]
@ -145,34 +145,14 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
return db; 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) services.AddInstance<IRoleStore<IdentityRole>>(new RoleStore<IdentityRole, IdentityDbContext>((IdentityDbContext)context));
{
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);
} }
[Fact] [Fact]

View File

@ -36,7 +36,9 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
app.UseServices(services => app.UseServices(services =>
{ {
services.AddInstance(contextAccessor.Object); 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 // 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. // 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. // 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.AspNet.Identity.Test;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity.InMemory.Test namespace Microsoft.AspNet.Identity.InMemory.Test
{ {
@ -16,27 +13,14 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
return null; return null;
} }
protected override UserManager<IdentityUser> CreateManager(object context) protected override void AddUserStore(IServiceCollection services, object context = null)
{ {
var services = new ServiceCollection(); services.AddSingleton<IUserStore<IdentityUser>, InMemoryUserStore<IdentityUser>>();
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>>();
} }
protected override RoleManager<IdentityRole> CreateRoleManager(object context) protected override void AddRoleStore(IServiceCollection services, object context = null)
{ {
var services = new ServiceCollection(); services.AddSingleton<IRoleStore<IdentityRole>, InMemoryRoleStore<IdentityRole>>();
services.AddIdentity().AddInMemory();
return services.BuildServiceProvider().GetRequiredService<RoleManager<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": { "dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.Http" : "1.0.0-*", "Microsoft.AspNet.Http" : "1.0.0-*",
"Microsoft.AspNet.Identity" : "3.0.0-*", "Microsoft.AspNet.Identity" : "3.0.0-*",
"Microsoft.AspNet.PipelineCore" : "1.0.0-*", "Microsoft.AspNet.PipelineCore" : "1.0.0-*",

View File

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

View File

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