React to options / DI / startup changes

This commit is contained in:
Hao Kung 2014-10-08 13:11:49 -07:00
parent 665780b18f
commit ffa226dfa9
25 changed files with 295 additions and 393 deletions

View File

@ -28,6 +28,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
global.json = global.json
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Hosting", "..\Hosting\src\Microsoft.AspNet.Hosting\Microsoft.AspNet.Hosting.kproj", "{3944F036-7E75-47E8-AA52-C4B89A64EC3A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -108,6 +110,16 @@ Global
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{E1BFA023-CFFD-49CE-8466-1C28DD2EC1F6}.Release|x86.ActiveCfg = Release|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Debug|x86.ActiveCfg = Debug|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Release|Any CPU.Build.0 = Release|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{3944F036-7E75-47E8-AA52-C4B89A64EC3A}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -22,7 +22,6 @@ namespace IdentitySample.Models
public SignInManager<ApplicationUser> SignInManager { get; private set; }
//
// GET: /Account/Login
[HttpGet]
@ -30,7 +29,7 @@ namespace IdentitySample.Models
public IActionResult Login(string returnUrl = null)
{
ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProviders = Context.GetExternalAuthenticationTypes().ToList();
ViewBag.LoginProviders = SignInManager.GetExternalAuthenticationTypes().ToList();
return View();
}
@ -118,7 +117,7 @@ namespace IdentitySample.Models
{
// Request a redirect to the external login provider
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
var properties = Context.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
var properties = SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return new ChallengeResult(provider, properties);
}
@ -128,7 +127,7 @@ namespace IdentitySample.Models
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null)
{
var info = await Context.GetExternalLoginInfo();
var info = await SignInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction("Login");
@ -171,7 +170,7 @@ namespace IdentitySample.Models
if (ModelState.IsValid)
{
// Get the information about the user from the external login provider
var info = await Context.GetExternalLoginInfo();
var info = await SignInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return View("ExternalLoginFailure");

View File

@ -302,7 +302,7 @@ namespace IdentitySample
return View("Error");
}
var userLogins = await UserManager.GetLoginsAsync(user);
var otherLogins = Context.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList();
var otherLogins = SignInManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList();
ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1;
return View(new ManageLoginsViewModel
{
@ -319,7 +319,7 @@ namespace IdentitySample
{
// Request a redirect to the external login provider to link a login for the current user
var redirectUrl = Url.Action("LinkLoginCallback", "Manage");
var properties = Context.ConfigureExternalAuthenticationProperties(provider, redirectUrl, User.Identity.GetUserId());
var properties = SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, User.Identity.GetUserId());
return new ChallengeResult(provider, properties);
}
@ -333,7 +333,7 @@ namespace IdentitySample
{
return View("Error");
}
var info = await Context.GetExternalLoginInfo(User.Identity.GetUserId());
var info = await SignInManager.GetExternalLoginInfoAsync(User.Identity.GetUserId());
if (info == null)
{
return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });

View File

@ -1,79 +1,15 @@
using System;
using IdentitySample.Models;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Diagnostics;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Security.Facebook;
using Microsoft.AspNet.Security.Google;
using Microsoft.AspNet.Security.Twitter;
using Microsoft.Data.Entity;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
using IdentitySample.Models;
using System;
namespace IdentitySamples
{
public static class UseExt
{
/**
* TODO: Middleware constructors need to take IOptionsAccessor<TOptions>
* Move options setup into a different method?
* Cookie options need to be different, named service/option instances? i.e. Singleton Named Options
SetupNamedOption("ApplicationCookie", options => { })
UseCookieAuthentication("ApplicationCookie")
SetupNamedOption("ExternalCookie", options => { })
UseCookieAuthentication("ApplicationCookie")
// Overloads which use default/no name
SetupOption(options => { })
UseGoogleAuthentication()
*/
public static IApplicationBuilder UseGoogleAuthentication(this IApplicationBuilder builder)
{
return builder.UseMiddleware<GoogleAuthenticationMiddleware>();
//return builder.UseGoogleAuthentication(b =>
// b.ApplicationServices.GetService<IOptionsAccessor<GoogleAuthenticationOptions>>().Options);
}
public static IApplicationBuilder UseGoogleAuthentication(this IApplicationBuilder builder, Func<IApplicationBuilder, GoogleAuthenticationOptions> func)
{
return builder.UseGoogleAuthentication(func(builder));
}
public static IApplicationBuilder UseFacebookAuthentication(this IApplicationBuilder builder)
{
// This should go inside of the middleware delegate
return builder.UseFacebookAuthentication(b =>
b.ApplicationServices.GetService<IOptionsAccessor<FacebookAuthenticationOptions>>().Options);
}
public static IApplicationBuilder UseFacebookAuthentication(this IApplicationBuilder builder, Func<IApplicationBuilder, FacebookAuthenticationOptions> func)
{
return builder.UseFacebookAuthentication(func(builder));
}
public static IApplicationBuilder UseTwitterAuthentication(this IApplicationBuilder builder)
{
return builder.UseTwitterAuthentication(b =>
b.ApplicationServices.GetService<IOptionsAccessor<TwitterAuthenticationOptions>>().Options);
}
public static IApplicationBuilder UseTwitterAuthentication(this IApplicationBuilder builder, Func<IApplicationBuilder, TwitterAuthenticationOptions> func)
{
return builder.UseTwitterAuthentication(func(builder));
}
}
public partial class Startup
{
public Startup()
@ -89,102 +25,63 @@ namespace IdentitySamples
public IConfiguration Configuration { get; private set; }
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework().AddSqlServer();
services.AddScoped<ApplicationDbContext>();
services.ConfigureOptions<IdentityDbContextOptions>(options =>
{
options.DefaultAdminUserName = Configuration.Get("DefaultAdminUsername");
options.DefaultAdminPassword = Configuration.Get("DefaultAdminPassword");
options.UseSqlServer(Configuration.Get("Data:IdentityConnection:ConnectionString"));
});
services.AddDefaultIdentity<ApplicationDbContext, ApplicationUser, IdentityRole>(Configuration, options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequireNonLetterOrDigit = false;
options.SecurityStampValidationInterval = TimeSpan.FromMinutes(20);
});
services.ConfigureFacebookAuthentication(options =>
{
options.AppId = "901611409868059";
options.AppSecret = "4aa3c530297b1dcebc8860334b39668b";
});
services.ConfigureGoogleAuthentication(options =>
{
options.ClientId = "514485782433-fr3ml6sq0imvhi8a7qir0nb46oumtgn9.apps.googleusercontent.com";
options.ClientSecret = "V2nDD9SkFbvLTqAUBWBBxYAL";
});
services.ConfigureTwitterAuthentication(options =>
{
options.ConsumerKey = "BSdJJ0CrDuvEhpkchnukXZBUv";
options.ConsumerSecret = "xKUNuKhsRdHD03eLn67xhPAyE1wFFEndFo1X2UJaK2m1jdAxf4";
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseServices(services =>
{
// Add EF services to the services container
services.AddEntityFramework()
.AddSqlServer();
// Configure DbContext
services.SetupOptions<IdentityDbContextOptions>(options =>
app.UseErrorPage(ErrorPageOptions.ShowAll)
.UseServices()
.UseStaticFiles()
.UseIdentity()
.UseFacebookAuthentication()
.UseGoogleAuthentication()
.UseTwitterAuthentication()
.UseMvc(routes =>
{
options.DefaultAdminUserName = Configuration.Get("DefaultAdminUsername");
options.DefaultAdminPassword = Configuration.Get("DefaultAdminPassword");
options.UseSqlServer(Configuration.Get("Data:IdentityConnection:ConnectionString"));
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
});
// Add Identity services to the services container
services.AddDefaultIdentity<ApplicationDbContext, ApplicationUser, IdentityRole>(Configuration);
// move this into add identity along with the
//service.SetupOptions<ExternalAuthenticationOptions>(options => options.SignInAsAuthenticationType = "External")
services.SetupOptions<IdentityOptions>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequireNonLetterOrDigit = false;
options.SecurityStampValidationInterval = TimeSpan.Zero;
});
services.SetupOptions<GoogleAuthenticationOptions>(options =>
{
options.ClientId = "514485782433-fr3ml6sq0imvhi8a7qir0nb46oumtgn9.apps.googleusercontent.com";
options.ClientSecret = "V2nDD9SkFbvLTqAUBWBBxYAL";
});
services.AddInstance(new GoogleAuthenticationOptions
{
ClientId = "514485782433-fr3ml6sq0imvhi8a7qir0nb46oumtgn9.apps.googleusercontent.com",
ClientSecret = "V2nDD9SkFbvLTqAUBWBBxYAL"
});
services.SetupOptions<FacebookAuthenticationOptions>(options =>
{
options.AppId = "901611409868059";
options.AppSecret = "4aa3c530297b1dcebc8860334b39668b";
});
services.SetupOptions<FacebookAuthenticationOptions>(options =>
{
options.AppId = "901611409868059";
options.AppSecret = "4aa3c530297b1dcebc8860334b39668b";
});
services.SetupOptions<TwitterAuthenticationOptions>(options =>
{
options.ConsumerKey = "BSdJJ0CrDuvEhpkchnukXZBUv";
options.ConsumerSecret = "xKUNuKhsRdHD03eLn67xhPAyE1wFFEndFo1X2UJaK2m1jdAxf4";
});
// Add MVC services to the services container
services.AddMvc();
});
/* Error page middleware displays a nice formatted HTML page for any unhandled exceptions in the request pipeline.
* Note: ErrorPageOptions.ShowAll to be used only at development time. Not recommended for production.
*/
app.UseErrorPage(ErrorPageOptions.ShowAll);
// Add static files to the request pipeline
app.UseStaticFiles();
// Setup identity cookie middleware
// Add cookie-based authentication to the request pipeline
app.UseIdentity();
app.UseGoogleAuthentication();
app.UseFacebookAuthentication();
app.UseTwitterAuthentication();
// Add MVC to the request pipeline
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
});
//Populates the Admin user and role
//Populates the Admin user and role
SampleData.InitializeIdentityDatabaseAsync(app.ApplicationServices).Wait();
}
// TODO: Move services here
public IServiceProvider ConfigureServices(ServiceCollection services)
{
return services.BuildServiceProvider();
}
}
}

View File

@ -1,6 +1,7 @@
// 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;
using Microsoft.AspNet.Identity.SqlServer;
using Microsoft.Data.Entity;
@ -11,6 +12,7 @@ namespace Microsoft.Framework.DependencyInjection
{
public static class IdentityEntityFrameworkServiceCollectionExtensions
{
// MOVE to builder extension
public static IdentityBuilder<IdentityUser, IdentityRole> AddIdentitySqlServer(this IServiceCollection services)
{
return services.AddIdentitySqlServer<IdentityDbContext, IdentityUser, IdentityRole>();
@ -22,54 +24,42 @@ namespace Microsoft.Framework.DependencyInjection
return services.AddIdentitySqlServer<TContext, IdentityUser, IdentityRole>();
}
public static IdentityBuilder<TUser, TRole> AddDefaultIdentity<TContext, TUser, TRole>(this IServiceCollection services, IConfiguration config)
public static IdentityBuilder<TUser, TRole> AddDefaultIdentity<TContext, TUser, TRole>(this IServiceCollection services, IConfiguration config = null,
Action<IdentityOptions> configureOptions = null)
where TUser : IdentityUser, new()
where TRole : IdentityRole, new()
where TContext : DbContext
{
return services.AddDefaultIdentity<TUser, TRole>(config)
return services.AddDefaultIdentity<TUser, TRole>(config, configureOptions)
.AddEntityFramework<TContext, TUser, TRole>();
}
public static IdentityBuilder<TUser, IdentityRole> AddIdentitySqlServer<TContext, TUser>(this IServiceCollection services)
public static IdentityBuilder<TUser, IdentityRole> AddIdentitySqlServer<TContext, TUser>(this IServiceCollection services, Action<IdentityOptions> configureOptions = null)
where TUser : IdentityUser, new()
where TContext : DbContext
{
return services.AddIdentitySqlServer<TContext, TUser, IdentityRole>();
return services.AddIdentitySqlServer<TContext, TUser, IdentityRole>(null, configureOptions);
}
public static IdentityBuilder<TUser, TRole> AddSqlServer<TContext, TUser, TRole>(this IServiceCollection services)
public static IdentityBuilder<TUser, TRole> AddIdentitySqlServer<TContext, TUser, TRole>(this IServiceCollection services, IConfiguration config = null, Action<IdentityOptions> configureOptions = null)
where TUser : IdentityUser, new()
where TRole : IdentityRole, new()
where TContext : DbContext
{
var builder = services.AddIdentity<TUser, TRole>();
var builder = services.AddIdentity<TUser, TRole>(config, configureOptions);
services.AddScoped<IUserStore<TUser>, UserStore<TUser, TRole, TContext>>();
services.AddScoped<IRoleStore<TRole>, RoleStore<TRole, TContext>>();
services.AddScoped<TContext>();
return builder;
}
public static IdentityBuilder<TUser, TRole> AddIdentitySqlServer<TContext, TUser, TRole>(this IServiceCollection services)
where TUser : IdentityUser, new()
where TRole : IdentityRole, new()
where TContext : DbContext
{
var builder = services.AddIdentity<TUser, TRole>();
services.AddScoped<IUserStore<TUser>, UserStore<TUser, TRole, TContext>>();
services.AddScoped<IRoleStore<TRole>, RoleStore<TRole, TContext>>();
services.AddScoped<TContext>();
return builder;
}
public static IdentityBuilder<TUser, TRole> AddIdentitySqlServer<TContext, TUser, TRole, TKey>(this IServiceCollection services)
public static IdentityBuilder<TUser, TRole> AddIdentitySqlServer<TContext, TUser, TRole, TKey>(this IServiceCollection services, IConfiguration config = null, Action<IdentityOptions> configureOptions = null)
where TUser : IdentityUser<TKey>, new()
where TRole : IdentityRole<TKey>, new()
where TContext : DbContext
where TKey : IEquatable<TKey>
{
var builder = services.AddIdentity<TUser, TRole>();
var builder = services.AddIdentity<TUser, TRole>(config, configureOptions);
services.AddScoped<IUserStore<TUser>, UserStore<TUser, TRole, TContext, TKey>>();
services.AddScoped<IRoleStore<TRole>, RoleStore<TRole, TContext, TKey>>();
services.AddScoped<TContext>();

View File

@ -5,6 +5,8 @@ using System;
using Microsoft.AspNet.Identity;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.AspNet.Security.Cookies;
using Microsoft.Framework.ConfigurationModel;
namespace Microsoft.AspNet.Builder
{
@ -19,12 +21,11 @@ namespace Microsoft.AspNet.Builder
{
throw new ArgumentNullException("app");
}
var options = app.ApplicationServices.GetService<IOptionsAccessor<IdentityOptions>>().Options;
app.SetDefaultSignInAsAuthenticationType(options.DefaultSignInAsAuthenticationType);
app.UseCookieAuthentication(options.ExternalCookie);
app.UseCookieAuthentication(options.ApplicationCookie);
app.UseCookieAuthentication(options.TwoFactorRememberMeCookie);
app.UseCookieAuthentication(options.TwoFactorUserIdCookie);
app.UseCookieAuthentication(null, IdentityOptions.ExternalCookieAuthenticationType);
app.UseCookieAuthentication(null, IdentityOptions.ApplicationCookieAuthenticationType);
app.UseCookieAuthentication(null, IdentityOptions.TwoFactorRememberMeCookieAuthenticationType);
app.UseCookieAuthentication(null, IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
app.UseCookieAuthentication(null, IdentityOptions.ApplicationCookieAuthenticationType);
return app;
}
}

View File

@ -58,7 +58,7 @@ namespace Microsoft.AspNet.Identity
}
var userId = await UserManager.GetUserIdAsync(user, cancellationToken);
var userName = await UserManager.GetUserNameAsync(user, cancellationToken);
var id = new ClaimsIdentity(Options.ApplicationCookie.AuthenticationType, Options.ClaimsIdentity.UserNameClaimType,
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType, Options.ClaimsIdentity.UserNameClaimType,
Options.ClaimsIdentity.RoleClaimType);
id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));
id.AddClaim(new Claim(Options.ClaimsIdentity.UserNameClaimType, userName, ClaimValueTypes.String));

View File

@ -8,10 +8,6 @@ namespace Microsoft.AspNet.Identity
public class ClaimsIdentityOptions
{
public static readonly string DefaultSecurityStampClaimType = "AspNet.Identity.SecurityStamp";
public static readonly string DefaultAuthenticationType = typeof(ClaimsIdentityOptions).Namespace + ".Application";
public static readonly string DefaultExternalLoginAuthenticationType = typeof(ClaimsIdentityOptions).Namespace + ".ExternalLogin";
public static readonly string DefaultTwoFactorRememberMeAuthenticationType = typeof(ClaimsIdentityOptions).Namespace + ".TwoFactorRememberMe";
public static readonly string DefaultTwoFactorUserIdAuthenticationType = typeof(ClaimsIdentityOptions).Namespace + ".TwoFactorUserId";
/// <summary>
/// Claim type used for role claims

View File

@ -1,75 +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 System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Http.Security;
using System.Linq;
using System;
using System.Security.Principal;
namespace Microsoft.AspNet.Http
{
public static class HttpContextExtensions
{
private const string LoginProviderKey = "LoginProvider";
private const string XsrfKey = "XsrfId";
public static IEnumerable<AuthenticationDescription> GetExternalAuthenticationTypes(this HttpContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
return context.GetAuthenticationTypes().Where(d => !string.IsNullOrEmpty(d.Caption));
}
public static async Task<ExternalLoginInfo> GetExternalLoginInfo(this HttpContext context, string expectedXsrf = null)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// REVIEW: should we consider taking the external authentication type as an argument?
var auth = await context.AuthenticateAsync(ClaimsIdentityOptions.DefaultExternalLoginAuthenticationType);
if (auth == null || auth.Identity == null || auth.Properties.Dictionary == null || !auth.Properties.Dictionary.ContainsKey(LoginProviderKey))
{
return null;
}
if (expectedXsrf != null)
{
if (!auth.Properties.Dictionary.ContainsKey(XsrfKey))
{
return null;
}
var userId = auth.Properties.Dictionary[XsrfKey] as string;
if (userId != expectedXsrf)
{
return null;
}
}
var providerKey = auth.Identity.FindFirstValue(ClaimTypes.NameIdentifier);
var provider = auth.Properties.Dictionary[LoginProviderKey] as string;
if (providerKey == null || provider == null)
{
return null;
}
return new ExternalLoginInfo(auth.Identity, provider, providerKey, auth.Description.Caption);
}
public static AuthenticationProperties ConfigureExternalAuthenticationProperties(this HttpContext context, string provider, string redirectUrl, string userId = null)
{
var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
properties.Dictionary[LoginProviderKey] = provider;
if (userId != null)
{
properties.Dictionary[XsrfKey] = userId;
}
return properties;
}
}
}

View File

@ -16,8 +16,6 @@ namespace Microsoft.AspNet.Identity
Services = services;
}
// Rename to Add
public IdentityBuilder<TUser, TRole> AddInstance<T>(T obj)
{
Services.AddInstance(obj);
@ -49,17 +47,12 @@ namespace Microsoft.AspNet.Identity
return AddInstance(tokenProvider);
}
public IdentityBuilder<TUser, TRole> SetupOptions(Action<IdentityOptions> action, int order)
public IdentityBuilder<TUser, TRole> ConfigureIdentity(Action<IdentityOptions> action, int order = 0)
{
Services.AddSetup(new OptionsSetup<IdentityOptions>(action) { Order = order });
Services.AddOptionsAction(new OptionsAction<IdentityOptions>(action) { Order = order });
return this;
}
public IdentityBuilder<TUser, TRole> SetupOptions(Action<IdentityOptions> action)
{
return SetupOptions(action, 0);
}
public IdentityBuilder<TUser, TRole> AddUserManager<TManager>() where TManager : UserManager<TUser>
{
Services.AddScoped<TManager>();

View File

@ -29,47 +29,9 @@ namespace Microsoft.AspNet.Identity
public string PasswordResetTokenProvider { get; set; } = Resources.DefaultTokenProvider;
//public string ApplicationCookieAuthenticationType { get; set; }
//public string ExternalCookieAuthenticationType { get; set; }
//public string TwoFactorCookieAuthenticationType { get; set; }
//public string TwoFactorFactorCookieAuthenticationType { get; set; }
public CookieAuthenticationOptions ApplicationCookie { get; set; } = new CookieAuthenticationOptions
{
AuthenticationType = ClaimsIdentityOptions.DefaultAuthenticationType,
//CookieName = ".AspNet.Identity." + ClaimsIdentityOptions.DefaultAuthenticationType,
LoginPath = new PathString("/Account/Login"),
Notifications = new CookieAuthenticationNotifications
{
OnValidateIdentity = SecurityStampValidator.ValidateIdentityAsync
}
};
// Move to setups for named per cookie option
public string DefaultSignInAsAuthenticationType { get; set; } = ClaimsIdentityOptions.DefaultExternalLoginAuthenticationType;
public CookieAuthenticationOptions ExternalCookie { get; set; } = new CookieAuthenticationOptions
{
AuthenticationType = ClaimsIdentityOptions.DefaultExternalLoginAuthenticationType,
AuthenticationMode = AuthenticationMode.Passive,
CookieName = ClaimsIdentityOptions.DefaultExternalLoginAuthenticationType,
ExpireTimeSpan = TimeSpan.FromMinutes(5),
};
public CookieAuthenticationOptions TwoFactorRememberMeCookie { get; set; } = new CookieAuthenticationOptions
{
AuthenticationType = ClaimsIdentityOptions.DefaultTwoFactorRememberMeAuthenticationType,
AuthenticationMode = AuthenticationMode.Passive,
CookieName = ClaimsIdentityOptions.DefaultTwoFactorRememberMeAuthenticationType
};
public CookieAuthenticationOptions TwoFactorUserIdCookie { get; set; } = new CookieAuthenticationOptions
{
AuthenticationType = ClaimsIdentityOptions.DefaultTwoFactorUserIdAuthenticationType,
AuthenticationMode = AuthenticationMode.Passive,
CookieName = ClaimsIdentityOptions.DefaultTwoFactorUserIdAuthenticationType,
ExpireTimeSpan = TimeSpan.FromMinutes(5),
};
public static string ApplicationCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".Application";
public static string ExternalCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".External";
public static string TwoFactorUserIdCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId";
public static string TwoFactorRememberMeCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRemeberMe";
}
}

View File

@ -5,16 +5,23 @@ using System;
using Microsoft.AspNet.Identity;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.AspNet.Security.DataProtection;
using Microsoft.AspNet.Security.Cookies;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Security;
namespace Microsoft.Framework.DependencyInjection
{
public static class IdentityServiceCollectionExtensions
{
public static IdentityBuilder<IdentityUser, IdentityRole> AddIdentity(this IServiceCollection services,
IConfiguration identityConfig)
public static IServiceCollection ConfigureIdentity(this IServiceCollection services, Action<IdentityOptions> configure)
{
services.SetupOptions<IdentityOptions>(identityConfig);
return services.AddIdentity<IdentityUser, IdentityRole>();
return services.ConfigureOptions(configure);
}
public static IdentityBuilder<IdentityUser, IdentityRole> AddIdentity(this IServiceCollection services,
IConfiguration identityConfig = null, Action<IdentityOptions> configureOptions = null)
{
return services.AddIdentity<IdentityUser, IdentityRole>(identityConfig, configureOptions);
}
public static IdentityBuilder<IdentityUser, IdentityRole> AddIdentity(this IServiceCollection services)
@ -23,28 +30,73 @@ namespace Microsoft.Framework.DependencyInjection
}
public static IdentityBuilder<TUser, TRole> AddIdentity<TUser, TRole>(this IServiceCollection services,
IConfiguration identityConfig = null)
IConfiguration identityConfig = null, Action<IdentityOptions> configureOptions = null)
where TUser : class
where TRole : class
{
if (identityConfig != null)
{
services.SetupOptions<IdentityOptions>(identityConfig);
services.ConfigureOptions<IdentityOptions>(identityConfig);
}
if (configureOptions != null)
{
services.ConfigureIdentity(configureOptions);
}
services.Add(IdentityServices.GetDefaultServices<TUser, TRole>(identityConfig));
services.AddScoped<UserManager<TUser>>();
services.AddScoped<SignInManager<TUser>>();
services.AddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
services.AddScoped<RoleManager<TRole>>();
services.AddScoped<IClaimsIdentityFactory<TUser>, ClaimsIdentityFactory<TUser, TRole>>();
services.ConfigureOptions<ExternalAuthenticationOptions>(options =>
{
options.SignInAsAuthenticationType = IdentityOptions.ExternalCookieAuthenticationType;
});
services.ConfigureOptions<CookieAuthenticationOptions>(options =>
{
options.AuthenticationType = IdentityOptions.ApplicationCookieAuthenticationType;
//CookieName = ".AspNet.Identity." + ClaimsIdentityOptions.DefaultAuthenticationType,
options.LoginPath = new PathString("/Account/Login");
options.Notifications = new CookieAuthenticationNotifications
{
OnValidateIdentity = SecurityStampValidator.ValidateIdentityAsync
};
}, IdentityOptions.ApplicationCookieAuthenticationType);
services.ConfigureOptions<CookieAuthenticationOptions>(options =>
{
options.AuthenticationType = IdentityOptions.ExternalCookieAuthenticationType;
options.AuthenticationMode = AuthenticationMode.Passive;
options.CookieName = IdentityOptions.ExternalCookieAuthenticationType;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
}, IdentityOptions.ExternalCookieAuthenticationType);
services.ConfigureOptions<CookieAuthenticationOptions>(options =>
{
options.AuthenticationType = IdentityOptions.TwoFactorRememberMeCookieAuthenticationType;
options.AuthenticationMode = AuthenticationMode.Passive;
options.CookieName = IdentityOptions.TwoFactorRememberMeCookieAuthenticationType;
}, IdentityOptions.TwoFactorRememberMeCookieAuthenticationType);
services.ConfigureOptions<CookieAuthenticationOptions>(options =>
{
options.AuthenticationType = IdentityOptions.TwoFactorUserIdCookieAuthenticationType;
options.AuthenticationMode = AuthenticationMode.Passive;
options.CookieName = IdentityOptions.TwoFactorUserIdCookieAuthenticationType;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
}, IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
return new IdentityBuilder<TUser, TRole>(services);
}
public static IdentityBuilder<TUser, TRole> AddDefaultIdentity<TUser, TRole>(this IServiceCollection services, IConfiguration config = null)
public static IdentityBuilder<TUser, TRole> AddDefaultIdentity<TUser, TRole>(this IServiceCollection services, IConfiguration config = null, Action<IdentityOptions> configureOptions = null)
where TUser : class
where TRole : class
{
return services.AddIdentity<TUser, TRole>(config)
return services.AddIdentity<TUser, TRole>(config, configureOptions)
.AddTokenProvider(new DataProtectorTokenProvider<TUser>(
new DataProtectionTokenProviderOptions
{

View File

@ -10,6 +10,8 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Security;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNet.Identity
{
@ -74,8 +76,6 @@ namespace Microsoft.AspNet.Identity
CancellationToken cancellationToken = default(CancellationToken))
{
var userIdentity = await CreateUserIdentityAsync(user);
// Should always clear any external login cookies when signing in for real
Context.Response.SignOut(Options.ExternalCookie.AuthenticationType);
if (authenticationMethod != null)
{
userIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod));
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Identity
// TODO: Should this be async?
public virtual void SignOut()
{
Context.Response.SignOut(Options.ApplicationCookie.AuthenticationType);
Context.Response.SignOut(IdentityOptions.ApplicationCookieAuthenticationType);
}
private async Task<bool> IsLockedOut(TUser user, CancellationToken token)
@ -151,7 +151,7 @@ namespace Microsoft.AspNet.Identity
{
return null;
}
var identity = new ClaimsIdentity(ClaimsIdentityOptions.DefaultTwoFactorUserIdAuthenticationType);
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, info.UserId));
if (info.LoginProvider != null)
{
@ -185,7 +185,7 @@ namespace Microsoft.AspNet.Identity
{
var userId = await UserManager.GetUserIdAsync(user, cancellationToken);
var result =
await Context.AuthenticateAsync(Options.TwoFactorRememberMeCookie.AuthenticationType);
await Context.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType);
return (result != null && result.Identity != null && result.Identity.Name == userId);
}
@ -193,14 +193,14 @@ namespace Microsoft.AspNet.Identity
CancellationToken cancellationToken = default(CancellationToken))
{
var userId = await UserManager.GetUserIdAsync(user, cancellationToken);
var rememberBrowserIdentity = new ClaimsIdentity(ClaimsIdentityOptions.DefaultTwoFactorRememberMeAuthenticationType);
var rememberBrowserIdentity = new ClaimsIdentity(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType);
rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.Name, userId));
Context.Response.SignIn(new AuthenticationProperties { IsPersistent = true }, rememberBrowserIdentity);
}
public virtual Task ForgetTwoFactorClientAsync()
{
Context.Response.SignOut(Options.TwoFactorRememberMeCookie.AuthenticationType);
Context.Response.SignOut(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType);
return Task.FromResult(0);
}
@ -225,6 +225,11 @@ namespace Microsoft.AspNet.Identity
{
// When token is verified correctly, clear the access failed count used for lockout
await UserManager.ResetAccessFailedCountAsync(user, cancellationToken);
// Cleanup external cookie
if (twoFactorInfo.LoginProvider != null)
{
Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationType);
}
await SignInAsync(user, isPersistent, twoFactorInfo.LoginProvider, cancellationToken);
if (rememberClient)
{
@ -254,7 +259,7 @@ namespace Microsoft.AspNet.Identity
return await UserManager.FindByIdAsync(info.UserId, cancellationToken);
}
public async Task<SignInStatus> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent,
public virtual async Task<SignInStatus> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent,
CancellationToken cancellationToken = default(CancellationToken))
{
var user = await UserManager.FindByLoginAsync(loginProvider, providerKey, cancellationToken);
@ -269,6 +274,56 @@ namespace Microsoft.AspNet.Identity
return await SignInOrTwoFactorAsync(user, isPersistent, cancellationToken, loginProvider);
}
private const string LoginProviderKey = "LoginProvider";
private const string XsrfKey = "XsrfId";
public virtual IEnumerable<AuthenticationDescription> GetExternalAuthenticationTypes()
{
return Context.GetAuthenticationTypes().Where(d => !string.IsNullOrEmpty(d.Caption));
}
public virtual async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null,
CancellationToken cancellationToken = default(CancellationToken))
{
var auth = await Context.AuthenticateAsync(IdentityOptions.ExternalCookieAuthenticationType);
if (auth == null || auth.Identity == null || auth.Properties.Dictionary == null || !auth.Properties.Dictionary.ContainsKey(LoginProviderKey))
{
return null;
}
if (expectedXsrf != null)
{
if (!auth.Properties.Dictionary.ContainsKey(XsrfKey))
{
return null;
}
var userId = auth.Properties.Dictionary[XsrfKey] as string;
if (userId != expectedXsrf)
{
return null;
}
}
var providerKey = auth.Identity.FindFirstValue(ClaimTypes.NameIdentifier);
var provider = auth.Properties.Dictionary[LoginProviderKey] as string;
if (providerKey == null || provider == null)
{
return null;
}
return new ExternalLoginInfo(auth.Identity, provider, providerKey, auth.Description.Caption);
}
public AuthenticationProperties ConfigureExternalAuthenticationProperties(string provider, string redirectUrl, string userId = null)
{
var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
properties.Dictionary[LoginProviderKey] = provider;
if (userId != null)
{
properties.Dictionary[XsrfKey] = userId;
}
return properties;
}
private async Task<SignInStatus> SignInOrTwoFactorAsync(TUser user, bool isPersistent,
CancellationToken cancellationToken, string loginProvider = null)
{
@ -284,13 +339,18 @@ namespace Microsoft.AspNet.Identity
return SignInStatus.RequiresVerification;
}
}
// Cleanup external cookie
if (loginProvider != null)
{
Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationType);
}
await SignInAsync(user, isPersistent, loginProvider, cancellationToken);
return SignInStatus.Success;
}
private async Task<TwoFactorAuthenticationInfo> RetrieveTwoFactorInfoAsync(CancellationToken cancellationToken)
{
var result = await Context.AuthenticateAsync(ClaimsIdentityOptions.DefaultTwoFactorUserIdAuthenticationType);
var result = await Context.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
if (result != null && result.Identity != null)
{
return new TwoFactorAuthenticationInfo
@ -304,7 +364,7 @@ namespace Microsoft.AspNet.Identity
internal static ClaimsIdentity StoreTwoFactorInfo(string userId, string loginProvider)
{
var identity = new ClaimsIdentity(ClaimsIdentityOptions.DefaultTwoFactorUserIdAuthenticationType);
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, userId));
if (loginProvider != null)
{

View File

@ -19,17 +19,20 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
public class HttpSignInTest
{
#if ASPNET50
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task VerifyAccountControllerSignIn(bool isPersistent)
{
var app = new ApplicationBuilder(new ServiceCollection().BuildServiceProvider());
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = ClaimsIdentityOptions.DefaultAuthenticationType
});
//app.UseServices(services =>
//{
// services.SetupOptions<CookieAuthenticationOptions>(options =>
// {
// options.AuthenticationType = IdentityOptions.ApplicationCookieAuthenticationType;
// });
//});
app.UseCookieAuthentication();
var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>();
@ -61,6 +64,5 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
response.VerifyAll();
contextAccessor.VerifyAll();
}
#endif
}
}

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
var services = new ServiceCollection();
services.Add(OptionsServices.GetDefaultServices());
services.AddIdentity().AddInMemory();
services.SetupOptions<IdentityOptions>(options =>
services.ConfigureIdentity(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.InMemory.Test
services.Add(OptionsServices.GetDefaultServices());
services.AddEntityFramework().AddInMemoryStore();
services.AddIdentityInMemory((InMemoryContext)context);
services.SetupOptions<IdentityOptions>(options =>
services.ConfigureIdentity(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;

View File

@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
services.Add(OptionsServices.GetDefaultServices());
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.AddEntityFramework().AddSqlServer();
services.SetupOptions<DbContextOptions>(options => options.UseSqlServer(ConnectionString));
services.ConfigureOptions<DbContextOptions>(options => options.UseSqlServer(ConnectionString));
var serviceProvider = services.BuildServiceProvider();
return new CustomDbContext<TKey>(serviceProvider);
}

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
services.Add(OptionsServices.GetDefaultServices());
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.AddEntityFramework().AddSqlServer();
services.SetupOptions<DbContextOptions>(options => options.UseSqlServer(ConnectionString));
services.ConfigureOptions<DbContextOptions>(options => options.UseSqlServer(ConnectionString));
var serviceProvider = services.BuildServiceProvider();
var db = new IdentityDbContext(serviceProvider,
serviceProvider.GetService<IOptionsAccessor<DbContextOptions>>().Options);
@ -59,7 +59,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
{
services.AddEntityFramework().AddSqlServer();
services.AddIdentitySqlServer();
services.SetupOptions<DbContextOptions>(options =>
services.ConfigureOptions<DbContextOptions>(options =>
options.UseSqlServer(ConnectionString));
// todo: constructor resolution doesn't work well with IdentityDbContext since it has 4 constructors
services.AddInstance(context);

View File

@ -50,7 +50,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
services.AddEntityFramework().AddSqlServer();
services.Add(OptionsServices.GetDefaultServices());
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.SetupOptions<DbContextOptions>(options =>
services.ConfigureOptions<DbContextOptions>(options =>
options.UseSqlServer(ConnectionString));
var serviceProvider = services.BuildServiceProvider();
var db = new ApplicationDbContext(serviceProvider,
@ -64,8 +64,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
services.AddEntityFramework().AddSqlServer();
services.Add(OptionsServices.GetDefaultServices());
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.SetupOptions<DbContextOptions>(options =>
options.UseSqlServer(ConnectionString));
services.ConfigureOptions<DbContextOptions>(options => options.UseSqlServer(ConnectionString));
var serviceProvider = services.BuildServiceProvider();
var db = new ApplicationDbContext(serviceProvider,
serviceProvider.GetService<IOptionsAccessor<DbContextOptions>>());
@ -118,7 +117,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.AddEntityFramework().AddSqlServer();
services.AddIdentitySqlServer<ApplicationDbContext, TUser, TRole, TKey>();
services.SetupOptions<DbContextOptions>(options =>
services.ConfigureOptions<DbContextOptions>(options =>
options.UseSqlServer(ConnectionString));
});
@ -145,7 +144,8 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
{
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.AddEntityFramework().AddSqlServer();
services.AddIdentitySqlServer<ApplicationDbContext, TUser, TRole, TKey>().SetupOptions(options =>
services.AddIdentitySqlServer<ApplicationDbContext, TUser, TRole, TKey>();
services.ConfigureIdentity(options =>
{
options.Password.RequiredLength = 1;
options.Password.RequireLowercase = false;
@ -154,7 +154,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
options.Password.RequireDigit = false;
options.User.UserNameValidationRegex = null;
});
services.SetupOptions<DbContextOptions>(options =>
services.ConfigureOptions<DbContextOptions>(options =>
options.UseSqlServer(ConnectionString));
});

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.AddEntityFramework().AddSqlServer();
services.Add(OptionsServices.GetDefaultServices());
services.SetupOptions<DbContextOptions>(options =>
services.ConfigureOptions<DbContextOptions>(options =>
options.UseSqlServer(ConnectionString));
var serviceProvider = services.BuildServiceProvider();
var db = new ApplicationDbContext(serviceProvider,
@ -67,8 +67,8 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
{
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.AddEntityFramework().AddSqlServer();
services.AddIdentitySqlServer<ApplicationDbContext, ApplicationUser>();
services.SetupOptions<DbContextOptions>(options =>
services.AddDefaultIdentity<ApplicationDbContext, ApplicationUser, IdentityRole>();
services.ConfigureOptions<DbContextOptions>(options =>
options.UseSqlServer(ConnectionString));
});
@ -95,7 +95,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
{
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
services.AddEntityFramework().AddSqlServer();
services.AddIdentitySqlServer<ApplicationDbContext, ApplicationUser>().SetupOptions(options =>
services.AddIdentitySqlServer<ApplicationDbContext, ApplicationUser>(options =>
{
options.Password.RequiredLength = 1;
options.Password.RequireLowercase = false;
@ -103,7 +103,7 @@ namespace Microsoft.AspNet.Identity.SqlServer.Test
options.Password.RequireUppercase = false;
options.Password.RequireDigit = false;
});
services.SetupOptions<DbContextOptions>(options =>
services.ConfigureOptions<DbContextOptions>(options =>
options.UseSqlServer(ConnectionString));
});

View File

@ -82,8 +82,7 @@ namespace Microsoft.AspNet.Identity.Test
// Assert
var manager = userManager.Object;
Assert.NotNull(identity);
Assert.Equal(ClaimsIdentityOptions.DefaultAuthenticationType, identity.AuthenticationType);
Assert.Equal(identityOptions.ApplicationCookie.AuthenticationType, identity.AuthenticationType);
Assert.Equal(IdentityOptions.ApplicationCookieAuthenticationType, identity.AuthenticationType);
var claims = identity.Claims.ToList();
Assert.NotNull(claims);
Assert.True(

View File

@ -84,14 +84,30 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Equal(1000, options.Lockout.MaxFailedAccessAttempts);
}
public class PasswordsNegativeLengthSetup : IOptionsSetup<IdentityOptions>
[Fact]
public void IdentityOptionsActionOverridesConfig()
{
public int Order { get { return 0; } }
public string Name { get; set; }
public void Setup(IdentityOptions options)
var dic = new Dictionary<string, string>
{
options.Password.RequiredLength = -1;
}
{"identity:user:requireUniqueEmail", "true"},
{"identity:lockout:MaxFailedAccessAttempts", "1000"}
};
var config = new Configuration { new MemoryConfigurationSource(dic) };
var services = new ServiceCollection { OptionsServices.GetDefaultServices() };
services.AddIdentity(config.GetSubKey("identity"),
o => { o.User.RequireUniqueEmail = false; o.Lockout.MaxFailedAccessAttempts++; });
var accessor = services.BuildServiceProvider().GetService<IOptionsAccessor<IdentityOptions>>();
Assert.NotNull(accessor);
var options = accessor.Options;
Assert.False(options.User.RequireUniqueEmail);
Assert.Equal(1001, options.Lockout.MaxFailedAccessAttempts);
}
public class PasswordsNegativeLengthSetup : OptionsAction<IdentityOptions>
{
public PasswordsNegativeLengthSetup()
: base(options => options.Password.RequiredLength = -1)
{ }
}
[Fact]
@ -101,15 +117,13 @@ namespace Microsoft.AspNet.Identity.Test
builder.UseServices(services =>
{
services.AddIdentity<IdentityUser>();
services.AddSetup<PasswordsNegativeLengthSetup>();
services.AddOptionsAction<PasswordsNegativeLengthSetup>();
});
var setup = builder.ApplicationServices.GetService<IOptionsSetup<IdentityOptions>>();
var setup = builder.ApplicationServices.GetService<IOptionsAction<IdentityOptions>>();
Assert.IsType(typeof(PasswordsNegativeLengthSetup), setup);
var optionsGetter = builder.ApplicationServices.GetService<IOptionsAccessor<IdentityOptions>>();
Assert.NotNull(optionsGetter);
setup.Setup(optionsGetter.Options);
var myOptions = optionsGetter.Options;
Assert.True(myOptions.Password.RequireLowercase);
Assert.True(myOptions.Password.RequireDigit);
@ -124,7 +138,7 @@ namespace Microsoft.AspNet.Identity.Test
var app = new ApplicationBuilder(new ServiceCollection().BuildServiceProvider());
app.UseServices(services =>
{
services.AddIdentity<IdentityUser>().SetupOptions(options => options.User.RequireUniqueEmail = true);
services.AddIdentity<IdentityUser>().ConfigureIdentity(options => options.User.RequireUniqueEmail = true);
});
var optionsGetter = app.ApplicationServices.GetService<IOptionsAccessor<IdentityOptions>>();

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Identity.Test
{
var httpContext = new Mock<HttpContext>();
httpContext.Setup(c => c.RequestServices).Returns(new ServiceCollection().BuildServiceProvider());
var id = new ClaimsIdentity(ClaimsIdentityOptions.DefaultAuthenticationType);
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType);
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow });
var context = new CookieValidateIdentityContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
await Assert.ThrowsAsync<Exception>(() => SecurityStampValidator.ValidateIdentityAsync(context));
@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Identity.Test
services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(ClaimsIdentityOptions.DefaultAuthenticationType);
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow, IsPersistent = isPersistent });
@ -87,7 +87,7 @@ namespace Microsoft.AspNet.Identity.Test
services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(ClaimsIdentityOptions.DefaultAuthenticationType);
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow });
@ -121,7 +121,7 @@ namespace Microsoft.AspNet.Identity.Test
services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(ClaimsIdentityOptions.DefaultAuthenticationType);
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties());
@ -156,7 +156,7 @@ namespace Microsoft.AspNet.Identity.Test
services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<IdentityUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(ClaimsIdentityOptions.DefaultAuthenticationType);
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow });

View File

@ -280,7 +280,7 @@ namespace Microsoft.AspNet.Identity.Test
contextAccessor.Setup(a => a.Value).Returns(context.Object);
var roleManager = MockHelpers.MockRoleManager<TestRole>();
var identityOptions = new IdentityOptions();
response.Setup(r => r.SignOut(identityOptions.ExternalCookie.AuthenticationType)).Verifiable();
response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationType)).Verifiable();
var options = new Mock<IOptionsAccessor<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
@ -351,6 +351,7 @@ namespace Microsoft.AspNet.Identity.Test
It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent),
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.NameIdentifier) == user.Id
&& i.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider))).Verifiable();
response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationType)).Verifiable();
}
else
{
@ -363,11 +364,10 @@ namespace Microsoft.AspNet.Identity.Test
response.Setup(r => r.SignIn(
It.Is<AuthenticationProperties>(v => v.IsPersistent == true),
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id
&& i.AuthenticationType == ClaimsIdentityOptions.DefaultTwoFactorRememberMeAuthenticationType))).Verifiable();
&& i.AuthenticationType == IdentityOptions.TwoFactorRememberMeCookieAuthenticationType))).Verifiable();
}
response.Setup(r => r.SignOut(identityOptions.ExternalCookie.AuthenticationType)).Verifiable();
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
context.Setup(c => c.AuthenticateAsync(ClaimsIdentityOptions.DefaultTwoFactorUserIdAuthenticationType)).ReturnsAsync(authResult).Verifiable();
context.Setup(c => c.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationType)).ReturnsAsync(authResult).Verifiable();
contextAccessor.Setup(a => a.Value).Returns(context.Object);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object);
@ -402,7 +402,7 @@ namespace Microsoft.AspNet.Identity.Test
response.Setup(r => r.SignIn(
It.Is<AuthenticationProperties>(v => v.IsPersistent == true),
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id
&& i.AuthenticationType == ClaimsIdentityOptions.DefaultTwoFactorRememberMeAuthenticationType))).Verifiable();
&& i.AuthenticationType == IdentityOptions.TwoFactorRememberMeCookieAuthenticationType))).Verifiable();
contextAccessor.Setup(a => a.Value).Returns(context.Object).Verifiable();
options.Setup(a => a.Options).Returns(identityOptions).Verifiable();
@ -440,20 +440,19 @@ namespace Microsoft.AspNet.Identity.Test
var context = new Mock<HttpContext>();
var response = new Mock<HttpResponse>();
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent), It.Is<ClaimsIdentity>(i => i.AuthenticationType == ClaimsIdentityOptions.DefaultAuthenticationType))).Verifiable();
var id = new ClaimsIdentity(ClaimsIdentityOptions.DefaultTwoFactorRememberMeAuthenticationType);
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent), It.Is<ClaimsIdentity>(i => i.AuthenticationType == IdentityOptions.ApplicationCookieAuthenticationType))).Verifiable();
var id = new ClaimsIdentity(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType);
id.AddClaim(new Claim(ClaimTypes.Name, user.Id));
var authResult = new AuthenticationResult(id, new AuthenticationProperties(), new AuthenticationDescription());
context.Setup(c => c.AuthenticateAsync(ClaimsIdentityOptions.DefaultTwoFactorRememberMeAuthenticationType)).ReturnsAsync(authResult).Verifiable();
context.Setup(c => c.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType)).ReturnsAsync(authResult).Verifiable();
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
contextAccessor.Setup(a => a.Value).Returns(context.Object);
var roleManager = MockHelpers.MockRoleManager<TestRole>();
var identityOptions = new IdentityOptions();
response.Setup(r => r.SignOut(identityOptions.ExternalCookie.AuthenticationType)).Verifiable();
var options = new Mock<IOptionsAccessor<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions);
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
claimsFactory.Setup(m => m.CreateAsync(user, CancellationToken.None)).ReturnsAsync(new ClaimsIdentity(identityOptions.ApplicationCookie.AuthenticationType)).Verifiable();
claimsFactory.Setup(m => m.CreateAsync(user, CancellationToken.None)).ReturnsAsync(new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType)).Verifiable();
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
// Act
@ -485,7 +484,7 @@ namespace Microsoft.AspNet.Identity.Test
var identityOptions = new IdentityOptions();
var options = new Mock<IOptionsAccessor<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions);
identityOptions.ApplicationCookie.AuthenticationType = authenticationType;
IdentityOptions.ApplicationCookieAuthenticationType = authenticationType;
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);

View File

@ -8,6 +8,7 @@ using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Framework.OptionsModel;
using Moq;
using System;
using System.Collections.Generic;
namespace Microsoft.AspNet.Identity.Test
{
@ -18,7 +19,7 @@ namespace Microsoft.AspNet.Identity.Test
var services = new ServiceCollection();
services.Add(OptionsServices.GetDefaultServices());
services.AddIdentity<TUser>().AddUserStore(store);
services.SetupOptions<IdentityOptions>(options =>
services.ConfigureIdentity(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
@ -40,7 +41,7 @@ namespace Microsoft.AspNet.Identity.Test
new UserValidator<TUser>(),
new PasswordValidator<TUser>(),
new UpperInvariantUserNameNormalizer(),
null);
new List<IUserTokenProvider<TUser>>());
}
public static Mock<RoleManager<TRole>> MockRoleManager<TRole>() where TRole : class