React to Options/Cookie changes

Moved cookie instance options into IdentityCookieOptions
IUserTokenProvider changes
This commit is contained in:
Hao Kung 2015-09-02 15:15:40 -07:00
parent a13dfc1eb5
commit 2113ef5abc
37 changed files with 380 additions and 428 deletions

View File

@ -29,7 +29,7 @@ namespace IdentitySample.Models
/// <returns></returns> /// <returns></returns>
private static async Task CreateAdminUser(IServiceProvider serviceProvider) private static async Task CreateAdminUser(IServiceProvider serviceProvider)
{ {
var options = serviceProvider.GetRequiredService<IOptions<IdentityDbContextOptions>>().Options; var options = serviceProvider.GetRequiredService<IOptions<IdentityDbContextOptions>>().Value;
const string adminRole = "Administrator"; const string adminRole = "Administrator";
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>(); var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();

View File

@ -5,6 +5,7 @@ using System;
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Builder namespace Microsoft.AspNet.Builder
{ {
@ -31,10 +32,11 @@ namespace Microsoft.AspNet.Builder
throw new InvalidOperationException(Resources.MustCallAddIdentity); throw new InvalidOperationException(Resources.MustCallAddIdentity);
} }
app.UseCookieAuthentication(null, IdentityOptions.ExternalCookieAuthenticationScheme); var options = app.ApplicationServices.GetRequiredService<IOptions<IdentityOptions>>().Value;
app.UseCookieAuthentication(null, IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme); app.UseCookieAuthentication(options.Cookies.ExternalCookie);
app.UseCookieAuthentication(null, IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme); app.UseCookieAuthentication(options.Cookies.TwoFactorRememberMeCookie);
app.UseCookieAuthentication(null, IdentityOptions.ApplicationCookieAuthenticationScheme); app.UseCookieAuthentication(options.Cookies.TwoFactorUserIdCookie);
app.UseCookieAuthentication(options.Cookies.ApplicationCookie);
return app; return app;
} }
} }

View File

@ -28,7 +28,7 @@ namespace Microsoft.AspNet.Identity
{ {
throw new ArgumentNullException(nameof(dataProtectionProvider)); throw new ArgumentNullException(nameof(dataProtectionProvider));
} }
Options = options?.Options ?? new DataProtectionTokenProviderOptions(); Options = options?.Value ?? new DataProtectionTokenProviderOptions();
// Use the Name as the purpose which should usually be distinct from others // Use the Name as the purpose which should usually be distinct from others
Protector = dataProtectionProvider.CreateProtector(Name ?? "DataProtectorTokenProvider"); Protector = dataProtectionProvider.CreateProtector(Name ?? "DataProtectorTokenProvider");
} }

View File

@ -1,23 +1,7 @@
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
{ {
/// <summary>
/// Options for the <see cref="EmailTokenProvider{TUser}"/> class.
/// </summary>
public class EmailTokenProviderOptions
{
/// <summary>
/// Gets or sets the unique name used for an instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </summary>
/// <value>
/// The unique name used for an instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </value>
public string Name { get; set; } = "Email";
}
/// <summary> /// <summary>
/// TokenProvider that generates tokens from the user's security stamp and notifies a user via email. /// TokenProvider that generates tokens from the user's security stamp and notifies a user via email.
/// </summary> /// </summary>
@ -25,36 +9,6 @@ namespace Microsoft.AspNet.Identity
public class EmailTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser> public class EmailTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser>
where TUser : class where TUser : class
{ {
/// <summary>
/// Initializes a new instance of the <see cref="EmailTokenProvider{TUser}"/> class.
/// </summary>
/// <param name="options">The configured <see cref="DataProtectionTokenProviderOptions"/>.</param>
/// <param name="name">The unique name for this instance of <see cref="EmailTokenProvider{TUser}"/>.</param>
public EmailTokenProvider(IOptions<EmailTokenProviderOptions> options, string name = "")
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
Options = options.GetNamedOptions(name);
}
/// <summary>
/// Gets the options for this instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </summary>
/// <value>
/// The options for this instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </value>
public EmailTokenProviderOptions Options { get; private set; }
/// <summary>
/// Gets the unique name for this instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </summary>
/// <value>
/// The unique name for this instance of <see cref="EmailTokenProvider{TUser}"/>.
/// </value>
public override string Name { get { return Options.Name; } }
/// <summary> /// <summary>
/// Checks if a two factor authentication token can be generated for the specified <paramref name="user"/>. /// Checks if a two factor authentication token can be generated for the specified <paramref name="user"/>.
/// </summary> /// </summary>

View File

@ -11,12 +11,6 @@ namespace Microsoft.AspNet.Identity
/// <typeparam name="TUser">The type encapsulating a user.</typeparam> /// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public interface IUserTokenProvider<TUser> where TUser : class public interface IUserTokenProvider<TUser> where TUser : class
{ {
/// <summary>
/// Gets the name of the token provider.
/// </summary>
/// <value>The name of the token provider.</value>
string Name { get; }
/// <summary> /// <summary>
/// Generates a token for the specified <paramref name="ref"/> and <paramref name="purpose"/>, as an asynchronous operation. /// Generates a token for the specified <paramref name="ref"/> and <paramref name="purpose"/>, as an asynchronous operation.
/// </summary> /// </summary>

View File

@ -121,20 +121,31 @@ namespace Microsoft.AspNet.Identity
/// Adds a token provider. /// Adds a token provider.
/// </summary> /// </summary>
/// <typeparam name="TProvider">The type of the token provider to add.</typeparam> /// <typeparam name="TProvider">The type of the token provider to add.</typeparam>
/// <param name="providerName">The name of the provider to add.</param>
/// <returns>The <see cref="IdentityBuilder"/>.</returns> /// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddTokenProvider<TProvider>() where TProvider : class public virtual IdentityBuilder AddTokenProvider<TProvider>(string providerName) where TProvider : class
{ {
return AddTokenProvider(typeof(TProvider)); return AddTokenProvider(providerName, typeof(TProvider));
} }
/// <summary> /// <summary>
/// Adds a token provider for the <seealso cref="UserType"/>. /// Adds a token provider for the <seealso cref="UserType"/>.
/// </summary> /// </summary>
/// <param name="providerName">The name of the provider to add.</param>
/// <param name="provider">The type of the <see cref="IUserTokenProvider{TUser}"/> to add.</param> /// <param name="provider">The type of the <see cref="IUserTokenProvider{TUser}"/> to add.</param>
/// <returns>The <see cref="IdentityBuilder"/>.</returns> /// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddTokenProvider(Type provider) public virtual IdentityBuilder AddTokenProvider(string providerName, Type provider)
{ {
return AddScoped(typeof(IUserTokenProvider<>).MakeGenericType(UserType), provider); if (!typeof(IUserTokenProvider<>).MakeGenericType(UserType).GetTypeInfo().IsAssignableFrom(provider.GetTypeInfo()))
{
throw new InvalidOperationException(Resources.FormatInvalidManagerType(provider.Name, "IUserTokenProvider", UserType.Name));
}
Services.Configure<IdentityOptions>(options =>
{
options.Tokens.ProviderMap[providerName] = new TokenProviderDescriptor(provider);
});
Services.AddTransient(provider);
return this;
} }
/// <summary> /// <summary>
@ -143,14 +154,12 @@ namespace Microsoft.AspNet.Identity
/// <returns>The <see cref="IdentityBuilder"/>.</returns> /// <returns>The <see cref="IdentityBuilder"/>.</returns>
public virtual IdentityBuilder AddDefaultTokenProviders() public virtual IdentityBuilder AddDefaultTokenProviders()
{ {
Services.Configure<DataProtectionTokenProviderOptions>(options => var dataProtectionProviderType = typeof(DataProtectorTokenProvider<>).MakeGenericType(UserType);
{ var phoneNumberProviderType = typeof(PhoneNumberTokenProvider<>).MakeGenericType(UserType);
options.Name = Resources.DefaultTokenProvider; var emailTokenProviderType = typeof(EmailTokenProvider<>).MakeGenericType(UserType);
}); return AddTokenProvider(TokenOptions.DefaultProvider, dataProtectionProviderType)
.AddTokenProvider(TokenOptions.DefaultEmailProvider, emailTokenProviderType)
return AddTokenProvider(typeof(DataProtectorTokenProvider<>).MakeGenericType(UserType)) .AddTokenProvider(TokenOptions.DefaultPhoneProvider, phoneNumberProviderType);
.AddTokenProvider(typeof(PhoneNumberTokenProvider<>).MakeGenericType(UserType))
.AddTokenProvider(typeof(EmailTokenProvider<>).MakeGenericType(UserType));
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,86 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Authentication.Cookies;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Represents all the options you can use to configure the cookies middleware uesd by the identity system.
/// </summary>
public class IdentityCookieOptions
{
public IdentityCookieOptions()
{
// Configure all of the cookie middlewares
ApplicationCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = ApplicationCookieAuthenticationScheme,
AutomaticAuthentication = true,
LoginPath = new PathString("/Account/Login"),
Notifications = new CookieAuthenticationNotifications
{
OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
}
};
ExternalCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = ExternalCookieAuthenticationScheme,
CookieName = ExternalCookieAuthenticationScheme,
ExpireTimeSpan = TimeSpan.FromMinutes(5)
};
TwoFactorRememberMeCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = TwoFactorRememberMeCookieAuthenticationScheme,
CookieName = TwoFactorRememberMeCookieAuthenticationScheme
};
TwoFactorUserIdCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = TwoFactorUserIdCookieAuthenticationScheme,
CookieName = TwoFactorUserIdCookieAuthenticationScheme,
ExpireTimeSpan = TimeSpan.FromMinutes(5)
};
}
public CookieAuthenticationOptions ApplicationCookie { get; set; }
public CookieAuthenticationOptions ExternalCookie { get; set; }
public CookieAuthenticationOptions TwoFactorRememberMeCookie { get; set; }
public CookieAuthenticationOptions TwoFactorUserIdCookie { get; set; }
/// <summary>
/// Gets or sets the scheme used to identify application authentication cookies.
/// </summary>
/// <value>The scheme used to identify application authentication cookies.</value>
public string ApplicationCookieAuthenticationScheme { get; set; } = ApplicationCookieAuthenticationType;
/// <summary>
/// Gets or sets the scheme used to identify external authentication cookies.
/// </summary>
/// <value>The scheme used to identify external authentication cookies.</value>
public string ExternalCookieAuthenticationScheme { get; set; } = typeof(IdentityCookieOptions).Namespace + ".External.AuthType";
/// <summary>
/// Gets or sets the scheme used to identify Two Factor authentication cookies for round tripping user identities.
/// </summary>
/// <value>The scheme used to identify user identity 2fa authentication cookies.</value>
public string TwoFactorUserIdCookieAuthenticationScheme { get; set; } = typeof(IdentityCookieOptions).Namespace + ".TwoFactorUserId.AuthType";
/// <summary>
/// Gets or sets the scheme used to identify Two Factor authentication cookies for saving the Remember Me state.
/// </summary>
/// <value>The scheme used to identify remember me application authentication cookies.</value>
public string TwoFactorRememberMeCookieAuthenticationScheme { get; set; } = typeof(IdentityCookieOptions).Namespace + ".TwoFactorRemeberMe.AuthType";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an application cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an application cookie.</value>
public static string ApplicationCookieAuthenticationType { get; set; } = typeof(IdentityCookieOptions).Namespace + ".Application.AuthType";
}
}

View File

@ -6,7 +6,7 @@ using System;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
{ {
/// <summary> /// <summary>
/// Represents all the options you can used to configure the identity system. /// Represents all the options you can use to configure the identity system.
/// </summary> /// </summary>
public class IdentityOptions public class IdentityOptions
{ {
@ -50,6 +50,22 @@ namespace Microsoft.AspNet.Identity
/// </value> /// </value>
public SignInOptions SignIn { get; set; } = new SignInOptions(); public SignInOptions SignIn { get; set; } = new SignInOptions();
/// <summary>
/// Gets or sets the <see cref="IdentityCookieOptions"/> for the identity system.
/// </summary>
/// <value>
/// The <see cref="IdentityCookieOptions"/> for the identity system.
/// </value>
public IdentityCookieOptions Cookies { get; set; } = new IdentityCookieOptions();
/// <summary>
/// Gets or sets the <see cref="TokenOptions"/> for the identity system.
/// </summary>
/// <value>
/// The <see cref="TokenOptions"/> for the identity system.
/// </value>
public TokenOptions Tokens { get; set; } = new TokenOptions();
/// <summary> /// <summary>
/// Gets or sets the <see cref="TimeSpan"/> after which security stamps are re-validated. /// Gets or sets the <see cref="TimeSpan"/> after which security stamps are re-validated.
/// </summary> /// </summary>
@ -57,78 +73,5 @@ namespace Microsoft.AspNet.Identity
/// The <see cref="TimeSpan"/> after which security stamps are re-validated. /// The <see cref="TimeSpan"/> after which security stamps are re-validated.
/// </value> /// </value>
public TimeSpan SecurityStampValidationInterval { get; set; } = TimeSpan.FromMinutes(30); public TimeSpan SecurityStampValidationInterval { get; set; } = TimeSpan.FromMinutes(30);
/// <summary>
/// Gets or sets the <see cref="EmailConfirmationTokenProvider"/> used to generate tokens used in account confirmation emails.
/// </summary>
/// <value>
/// The <see cref="EmailConfirmationTokenProvider"/> used to generate tokens used in account confirmation emails.
/// </value>
public string EmailConfirmationTokenProvider { get; set; } = Resources.DefaultTokenProvider;
/// <summary>
/// Gets or sets the <see cref="PasswordResetTokenProvider"/> used to generate tokens used in password reset emails.
/// </summary>
/// <value>
/// The <see cref="PasswordResetTokenProvider"/> used to generate tokens used in password reset emails.
/// </value>
public string PasswordResetTokenProvider { get; set; } = Resources.DefaultTokenProvider;
/// <summary>
/// Gets or sets the <see cref="ChangeEmailTokenProvider"/> used to generate tokens used in email change confirmation emails.
/// </summary>
/// <value>
/// The <see cref="ChangeEmailTokenProvider"/> used to generate tokens used in email change confirmation emails.
/// </value>
public string ChangeEmailTokenProvider { get; set; } = Resources.DefaultTokenProvider;
/// <summary>
/// Gets or sets the scheme used to identify application authentication cookies.
/// </summary>
/// <value>The scheme used to identify application authentication cookies.</value>
public static string ApplicationCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".Application";
/// <summary>
/// Gets or sets the scheme used to identify external authentication cookies.
/// </summary>
/// <value>The scheme used to identify external authentication cookies.</value>
public static string ExternalCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".External";
/// <summary>
/// Gets or sets the scheme used to identify Two Factor authentication cookies for round tripping user identities.
/// </summary>
/// <value>The scheme used to identify user identity 2fa authentication cookies.</value>
public static string TwoFactorUserIdCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId";
/// <summary>
/// Gets or sets the scheme used to identify Two Factor authentication cookies for saving the Remember Me state.
/// </summary>
/// <value>The scheme used to identify remember me application authentication cookies.</value>
public static string TwoFactorRememberMeCookieAuthenticationScheme { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRememberMe";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an application cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an application cookie.</value>
public static string ApplicationCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".Application.AuthType";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an external identity cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an external identity cookie.</value>
public static string ExternalCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".External.AuthType";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an two factor authentication cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an two factor authentication cookie.</value>
public static string TwoFactorUserIdCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId.AuthType";
/// <summary>
/// Gets or sets the authentication type used when constructing an <see cref="ClaimsIdentity"/> from an two factor remember me authentication cookie.
/// </summary>
/// <value>The authentication type used when constructing an <see cref="ClaimsIdentity"/> from an two factor remember me authentication cookie.</value>
public static string TwoFactorRememberMeCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorRemeberMe.AuthType";
} }
} }

View File

@ -2,10 +2,8 @@
// 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 System;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Authentication; using Microsoft.AspNet.Authentication;
using Microsoft.AspNet.Authentication.Cookies; using Microsoft.AspNet.Identity;
using Microsoft.Framework.Configuration; using Microsoft.Framework.Configuration;
using Microsoft.Framework.DependencyInjection.Extensions; using Microsoft.Framework.DependencyInjection.Extensions;
@ -16,39 +14,6 @@ namespace Microsoft.Framework.DependencyInjection
/// </summary> /// </summary>
public static class IdentityServiceCollectionExtensions public static class IdentityServiceCollectionExtensions
{ {
/// <summary>
/// Configures a set of <see cref="IdentityOptions"/> for the application
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="setupAction">An action to configure the <see cref="IdentityOptions"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> instance this method extends.</returns>
public static IServiceCollection ConfigureIdentity(this IServiceCollection services, Action<IdentityOptions> setupAction)
{
return services.Configure(setupAction);
}
/// <summary>
/// Configures a set of <see cref="IdentityOptions"/> for the application
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="config">The configuration for the <see cref="IdentityOptions>"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> instance this method extends.</returns>
public static IServiceCollection ConfigureIdentity(this IServiceCollection services, IConfiguration config)
{
return services.Configure<IdentityOptions>(config);
}
/// <summary>
/// Configures a set of <see cref="CookieAuthenticationOptions"/> for the application
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="setupAction">An action to configure the <see cref="CookieAuthenticationOptions"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> instance this method extends.</returns>
public static IServiceCollection ConfigureIdentityApplicationCookie(this IServiceCollection services, Action<CookieAuthenticationOptions> setupAction)
{
return services.ConfigureCookieAuthentication(setupAction, IdentityOptions.ApplicationCookieAuthenticationScheme);
}
/// <summary> /// <summary>
/// Adds the default identity system configuration for the specified User and Role types. /// Adds the default identity system configuration for the specified User and Role types.
/// </summary> /// </summary>
@ -99,43 +64,14 @@ namespace Microsoft.Framework.DependencyInjection
if (setupAction != null) if (setupAction != null)
{ {
services.ConfigureIdentity(setupAction); services.Configure<IdentityOptions>(setupAction);
} }
services.Configure<SharedAuthenticationOptions>(options => services.Configure<SharedAuthenticationOptions>(options =>
{ {
options.SignInScheme = IdentityOptions.ExternalCookieAuthenticationScheme; // This is the Default value for ExternalCookieAuthenticationScheme
options.SignInScheme = new IdentityCookieOptions().ExternalCookieAuthenticationScheme;
}); });
// Configure all of the cookie middlewares
services.ConfigureIdentityApplicationCookie(options =>
{
options.AuthenticationScheme = IdentityOptions.ApplicationCookieAuthenticationScheme;
options.AutomaticAuthentication = true;
options.LoginPath = new PathString("/Account/Login");
options.Notifications = new CookieAuthenticationNotifications
{
OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
};
});
services.ConfigureCookieAuthentication(options =>
{
options.AuthenticationScheme = IdentityOptions.ExternalCookieAuthenticationScheme;
options.CookieName = IdentityOptions.ExternalCookieAuthenticationScheme;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
}, IdentityOptions.ExternalCookieAuthenticationScheme);
services.ConfigureCookieAuthentication(options =>
{
options.AuthenticationScheme = IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme;
options.CookieName = IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme;
}, IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme);
services.ConfigureCookieAuthentication(options =>
{
options.AuthenticationScheme = IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme;
options.CookieName = IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme;
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
}, IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme);
return new IdentityBuilder(typeof(TUser), typeof(TRole), services); return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
} }
} }

View File

@ -40,7 +40,7 @@ namespace Microsoft.AspNet.Identity
/// <param name="options">The options for this instance.</param> /// <param name="options">The options for this instance.</param>
public PasswordHasher(IOptions<PasswordHasherOptions> optionsAccessor = null) public PasswordHasher(IOptions<PasswordHasherOptions> optionsAccessor = null)
{ {
var options = optionsAccessor?.Options ?? new PasswordHasherOptions(); var options = optionsAccessor?.Value ?? new PasswordHasherOptions();
_compatibilityMode = options.CompatibilityMode; _compatibilityMode = options.CompatibilityMode;
switch (_compatibilityMode) switch (_compatibilityMode)

View File

@ -1,23 +1,8 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
{ {
/// <summary>
/// Encapsulations options for a <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </summary>
public class PhoneNumberTokenProviderOptions
{
/// <summary>
/// Gets or sets the name for the <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </summary>
/// <value>
/// The name for the <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </value>
public string Name { get; set; } = "Phone";
}
/// <summary> /// <summary>
/// Represents a token provider that generates tokens from a user's security stamp and /// Represents a token provider that generates tokens from a user's security stamp and
/// sends them to the user via their phone number. /// sends them to the user via their phone number.
@ -26,31 +11,6 @@ namespace Microsoft.AspNet.Identity
public class PhoneNumberTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser> public class PhoneNumberTokenProvider<TUser> : TotpSecurityStampBasedTokenProvider<TUser>
where TUser : class where TUser : class
{ {
/// <summary>
/// Creates a new instance of <see cref="PhoneNumberTokenProvider{TUser}"/> with the specified <paramref name="options"/>.
/// </summary>
/// <param name="options">The options to use for the created instance of a <see cref="PhoneNumberTokenProvider{TUser}"/>.</param>
public PhoneNumberTokenProvider(IOptions<PhoneNumberTokenProviderOptions> options)
{
if (options == null || options.Options == null)
{
throw new ArgumentNullException(nameof(options));
}
Options = options.Options;
}
/// <summary>
/// Gets the options for this instance of <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </summary>
/// <value>The options for this instance of <see cref="PhoneNumberTokenProvider{TUser}"/>.</value>
public PhoneNumberTokenProviderOptions Options { get; private set; }
/// <summary>
/// Gets the name for this instance of <see cref="PhoneNumberTokenProvider{TUser}"/>.
/// </summary>
/// <value>The name for this instance of <see cref="PhoneNumberTokenProvider{TUser}"/>.</value>
public override string Name { get { return Options.Name; } }
/// <summary> /// <summary>
/// Returns a flag indicating whether the token provider can generate a token suitable for two factor authentication token for /// Returns a flag indicating whether the token provider can generate a token suitable for two factor authentication token for
/// the specified <paramref name="ref"/>. /// the specified <paramref name="ref"/>.

View File

@ -53,7 +53,7 @@ namespace System.Security.Claims
throw new ArgumentNullException(nameof(principal)); throw new ArgumentNullException(nameof(principal));
} }
return principal?.Identities != null && return principal?.Identities != null &&
principal.Identities.Any(i => i.AuthenticationType == IdentityOptions.ApplicationCookieAuthenticationType); principal.Identities.Any(i => i.AuthenticationType == IdentityCookieOptions.ApplicationCookieAuthenticationType);
} }
/// <summary> /// <summary>

View File

@ -42,22 +42,6 @@ namespace Microsoft.AspNet.Identity
return GetString("DefaultError"); return GetString("DefaultError");
} }
/// <summary>
/// Default Token Provider
/// </summary>
internal static string DefaultTokenProvider
{
get { return GetString("DefaultTokenProvider"); }
}
/// <summary>
/// Default Token Provider
/// </summary>
internal static string FormatDefaultTokenProvider()
{
return GetString("DefaultTokenProvider");
}
/// <summary> /// <summary>
/// Email '{0}' is already taken. /// Email '{0}' is already taken.
/// </summary> /// </summary>
@ -123,7 +107,7 @@ namespace Microsoft.AspNet.Identity
} }
/// <summary> /// <summary>
/// Type {0} must be derived from {1}&lt;{2}&gt;. /// Type {0} must derive from {1}&lt;{2}&gt;.
/// </summary> /// </summary>
internal static string InvalidManagerType internal static string InvalidManagerType
{ {
@ -131,7 +115,7 @@ namespace Microsoft.AspNet.Identity
} }
/// <summary> /// <summary>
/// Type {0} must be derived from {1}&lt;{2}&gt;. /// Type {0} must derive from {1}&lt;{2}&gt;.
/// </summary> /// </summary>
internal static string FormatInvalidManagerType(object p0, object p1, object p2) internal static string FormatInvalidManagerType(object p0, object p1, object p2)
{ {

View File

@ -125,10 +125,6 @@
<value>An unknown failure has occured.</value> <value>An unknown failure has occured.</value>
<comment>Default identity result error message</comment> <comment>Default identity result error message</comment>
</data> </data>
<data name="DefaultTokenProvider" xml:space="preserve">
<value>Default Token Provider</value>
<comment>Name of the default token provider</comment>
</data>
<data name="DuplicateEmail" xml:space="preserve"> <data name="DuplicateEmail" xml:space="preserve">
<value>Email '{0}' is already taken.</value> <value>Email '{0}' is already taken.</value>
<comment>Error for duplicate emails</comment> <comment>Error for duplicate emails</comment>

View File

@ -74,7 +74,7 @@ namespace Microsoft.AspNet.Identity
{ {
var timeElapsed = currentUtc.Subtract(issuedUtc.Value); var timeElapsed = currentUtc.Subtract(issuedUtc.Value);
var accessor = context.HttpContext.RequestServices.GetRequiredService<IOptions<IdentityOptions>>(); var accessor = context.HttpContext.RequestServices.GetRequiredService<IOptions<IdentityOptions>>();
validate = timeElapsed > accessor.Options.SecurityStampValidationInterval; validate = timeElapsed > accessor.Value.SecurityStampValidationInterval;
} }
if (validate) if (validate)
{ {

View File

@ -54,7 +54,7 @@ namespace Microsoft.AspNet.Identity
UserManager = userManager; UserManager = userManager;
Context = contextAccessor.HttpContext; Context = contextAccessor.HttpContext;
ClaimsFactory = claimsFactory; ClaimsFactory = claimsFactory;
Options = optionsAccessor?.Options ?? new IdentityOptions(); Options = optionsAccessor?.Value ?? new IdentityOptions();
Logger = logger; Logger = logger;
} }
@ -109,7 +109,7 @@ namespace Microsoft.AspNet.Identity
/// <returns>The task object representing the asynchronous operation.</returns> /// <returns>The task object representing the asynchronous operation.</returns>
public virtual async Task RefreshSignInAsync(TUser user) public virtual async Task RefreshSignInAsync(TUser user)
{ {
var auth = new AuthenticateContext(IdentityOptions.ApplicationCookieAuthenticationScheme); var auth = new AuthenticateContext(Options.Cookies.ApplicationCookieAuthenticationScheme);
await Context.Authentication.AuthenticateAsync(auth); await Context.Authentication.AuthenticateAsync(auth);
var authenticationMethod = auth.Principal?.FindFirstValue(ClaimTypes.AuthenticationMethod); var authenticationMethod = auth.Principal?.FindFirstValue(ClaimTypes.AuthenticationMethod);
await SignInAsync(user, new AuthenticationProperties(auth.Properties), authenticationMethod); await SignInAsync(user, new AuthenticationProperties(auth.Properties), authenticationMethod);
@ -142,7 +142,7 @@ namespace Microsoft.AspNet.Identity
{ {
userPrincipal.Identities.First().AddClaim(new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod)); userPrincipal.Identities.First().AddClaim(new Claim(ClaimTypes.AuthenticationMethod, authenticationMethod));
} }
await Context.Authentication.SignInAsync(IdentityOptions.ApplicationCookieAuthenticationScheme, await Context.Authentication.SignInAsync(Options.Cookies.ApplicationCookieAuthenticationScheme,
userPrincipal, userPrincipal,
authenticationProperties ?? new AuthenticationProperties()); authenticationProperties ?? new AuthenticationProperties());
} }
@ -152,9 +152,9 @@ namespace Microsoft.AspNet.Identity
/// </summary> /// </summary>
public virtual async Task SignOutAsync() public virtual async Task SignOutAsync()
{ {
await Context.Authentication.SignOutAsync(IdentityOptions.ApplicationCookieAuthenticationScheme); await Context.Authentication.SignOutAsync(Options.Cookies.ApplicationCookieAuthenticationScheme);
await Context.Authentication.SignOutAsync(IdentityOptions.ExternalCookieAuthenticationScheme); await Context.Authentication.SignOutAsync(Options.Cookies.ExternalCookieAuthenticationScheme);
await Context.Authentication.SignOutAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme); await Context.Authentication.SignOutAsync(Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme);
} }
/// <summary> /// <summary>
@ -260,7 +260,7 @@ namespace Microsoft.AspNet.Identity
public virtual async Task<bool> IsTwoFactorClientRememberedAsync(TUser user) public virtual async Task<bool> IsTwoFactorClientRememberedAsync(TUser user)
{ {
var userId = await UserManager.GetUserIdAsync(user); var userId = await UserManager.GetUserIdAsync(user);
var result = await Context.Authentication.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme); var result = await Context.Authentication.AuthenticateAsync(Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme);
return (result != null && result.FindFirstValue(ClaimTypes.Name) == userId); return (result != null && result.FindFirstValue(ClaimTypes.Name) == userId);
} }
@ -273,9 +273,9 @@ namespace Microsoft.AspNet.Identity
public virtual async Task RememberTwoFactorClientAsync(TUser user) public virtual async Task RememberTwoFactorClientAsync(TUser user)
{ {
var userId = await UserManager.GetUserIdAsync(user); var userId = await UserManager.GetUserIdAsync(user);
var rememberBrowserIdentity = new ClaimsIdentity(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType); var rememberBrowserIdentity = new ClaimsIdentity(Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme);
rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.Name, userId)); rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.Name, userId));
await Context.Authentication.SignInAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme, await Context.Authentication.SignInAsync(Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme,
new ClaimsPrincipal(rememberBrowserIdentity), new ClaimsPrincipal(rememberBrowserIdentity),
new AuthenticationProperties { IsPersistent = true }); new AuthenticationProperties { IsPersistent = true });
} }
@ -286,7 +286,7 @@ namespace Microsoft.AspNet.Identity
/// <returns>The task object representing the asynchronous operation.</returns> /// <returns>The task object representing the asynchronous operation.</returns>
public virtual Task ForgetTwoFactorClientAsync() public virtual Task ForgetTwoFactorClientAsync()
{ {
return Context.Authentication.SignOutAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme); return Context.Authentication.SignOutAsync(Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme);
} }
/// <summary> /// <summary>
@ -325,7 +325,7 @@ namespace Microsoft.AspNet.Identity
// Cleanup external cookie // Cleanup external cookie
if (twoFactorInfo.LoginProvider != null) if (twoFactorInfo.LoginProvider != null)
{ {
await Context.Authentication.SignOutAsync(IdentityOptions.ExternalCookieAuthenticationScheme); await Context.Authentication.SignOutAsync(Options.Cookies.ExternalCookieAuthenticationScheme);
} }
if (rememberClient) if (rememberClient)
{ {
@ -397,7 +397,7 @@ namespace Microsoft.AspNet.Identity
/// for the sign-in attempt.</returns> /// for the sign-in attempt.</returns>
public virtual async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null) public virtual async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null)
{ {
var auth = new AuthenticateContext(IdentityOptions.ExternalCookieAuthenticationScheme); var auth = new AuthenticateContext(Options.Cookies.ExternalCookieAuthenticationScheme);
await Context.Authentication.AuthenticateAsync(auth); await Context.Authentication.AuthenticateAsync(auth);
if (auth.Principal == null || auth.Properties == null || !auth.Properties.ContainsKey(LoginProviderKey)) if (auth.Principal == null || auth.Properties == null || !auth.Properties.ContainsKey(LoginProviderKey))
{ {
@ -451,9 +451,9 @@ namespace Microsoft.AspNet.Identity
/// <param name="userId">The user whose is logging in via 2fa.</param> /// <param name="userId">The user whose is logging in via 2fa.</param>
/// <param name="loginProvider">The 2fa provider.</param> /// <param name="loginProvider">The 2fa provider.</param>
/// <returns>A <see cref="ClaimsPrincipal"/> containing the user 2fa information.</returns> /// <returns>A <see cref="ClaimsPrincipal"/> containing the user 2fa information.</returns>
internal static ClaimsPrincipal StoreTwoFactorInfo(string userId, string loginProvider) internal ClaimsPrincipal StoreTwoFactorInfo(string userId, string loginProvider)
{ {
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType); var identity = new ClaimsIdentity(Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, userId)); identity.AddClaim(new Claim(ClaimTypes.Name, userId));
if (loginProvider != null) if (loginProvider != null)
{ {
@ -462,13 +462,13 @@ namespace Microsoft.AspNet.Identity
return new ClaimsPrincipal(identity); return new ClaimsPrincipal(identity);
} }
private static ClaimsIdentity CreateIdentity(TwoFactorAuthenticationInfo info) private ClaimsIdentity CreateIdentity(TwoFactorAuthenticationInfo info)
{ {
if (info == null) if (info == null)
{ {
return null; return null;
} }
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType); var identity = new ClaimsIdentity(Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, info.UserId)); identity.AddClaim(new Claim(ClaimTypes.Name, info.UserId));
if (info.LoginProvider != null) if (info.LoginProvider != null)
{ {
@ -488,14 +488,14 @@ namespace Microsoft.AspNet.Identity
{ {
// Store the userId for use after two factor check // Store the userId for use after two factor check
var userId = await UserManager.GetUserIdAsync(user); var userId = await UserManager.GetUserIdAsync(user);
await Context.Authentication.SignInAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme, StoreTwoFactorInfo(userId, loginProvider)); await Context.Authentication.SignInAsync(Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme, StoreTwoFactorInfo(userId, loginProvider));
return SignInResult.TwoFactorRequired; return SignInResult.TwoFactorRequired;
} }
} }
// Cleanup external cookie // Cleanup external cookie
if (loginProvider != null) if (loginProvider != null)
{ {
await Context.Authentication.SignOutAsync(IdentityOptions.ExternalCookieAuthenticationScheme); await Context.Authentication.SignOutAsync(Options.Cookies.ExternalCookieAuthenticationScheme);
} }
await SignInAsync(user, isPersistent, loginProvider); await SignInAsync(user, isPersistent, loginProvider);
return SignInResult.Success; return SignInResult.Success;
@ -503,7 +503,7 @@ namespace Microsoft.AspNet.Identity
private async Task<TwoFactorAuthenticationInfo> RetrieveTwoFactorInfoAsync() private async Task<TwoFactorAuthenticationInfo> RetrieveTwoFactorInfoAsync()
{ {
var result = await Context.Authentication.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme); var result = await Context.Authentication.AuthenticateAsync(Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme);
if (result != null) if (result != null)
{ {
return new TwoFactorAuthenticationInfo return new TwoFactorAuthenticationInfo

View File

@ -0,0 +1,44 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace Microsoft.AspNet.Identity
{
public class TokenOptions
{
public static readonly string DefaultProvider = "Default";
public static readonly string DefaultEmailProvider = "Email";
public static readonly string DefaultPhoneProvider = "Phone";
/// <summary>
/// Will be used to construct UserTokenProviders with the key used as the providerName.
/// </summary>
public Dictionary<string, TokenProviderDescriptor> ProviderMap { get; set; } = new Dictionary<string, TokenProviderDescriptor>();
/// <summary>
/// Gets or sets the <see cref="EmailConfirmationTokenProvider"/> used to generate tokens used in account confirmation emails.
/// </summary>
/// <value>
/// The <see cref="EmailConfirmationTokenProvider"/> used to generate tokens used in account confirmation emails.
/// </value>
public string EmailConfirmationTokenProvider { get; set; } = DefaultProvider;
/// <summary>
/// Gets or sets the <see cref="PasswordResetTokenProvider"/> used to generate tokens used in password reset emails.
/// </summary>
/// <value>
/// The <see cref="PasswordResetTokenProvider"/> used to generate tokens used in password reset emails.
/// </value>
public string PasswordResetTokenProvider { get; set; } = DefaultProvider;
/// <summary>
/// Gets or sets the <see cref="ChangeEmailTokenProvider"/> used to generate tokens used in email change confirmation emails.
/// </summary>
/// <value>
/// The <see cref="ChangeEmailTokenProvider"/> used to generate tokens used in email change confirmation emails.
/// </value>
public string ChangeEmailTokenProvider { get; set; } = DefaultProvider;
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNet.Identity
{
public class TokenProviderDescriptor
{
public TokenProviderDescriptor(Type type)
{
ProviderType = type;
}
public Type ProviderType { get; }
}
}

View File

@ -12,12 +12,6 @@ namespace Microsoft.AspNet.Identity
public abstract class TotpSecurityStampBasedTokenProvider<TUser> : IUserTokenProvider<TUser> public abstract class TotpSecurityStampBasedTokenProvider<TUser> : IUserTokenProvider<TUser>
where TUser : class where TUser : class
{ {
/// <summary>
/// Gets the name of the token provider.
/// </summary>
/// <value>The name of the token provider.</value>
public abstract string Name { get; }
/// <summary> /// <summary>
/// Generates a token for the specified <paramref name="ref"/> and <paramref name="purpose"/>, as an asynchronous operation. /// Generates a token for the specified <paramref name="ref"/> and <paramref name="purpose"/>, as an asynchronous operation.
/// </summary> /// </summary>

View File

@ -38,13 +38,13 @@ namespace Microsoft.AspNet.Identity
{ {
throw new ArgumentNullException(nameof(roleManager)); throw new ArgumentNullException(nameof(roleManager));
} }
if (optionsAccessor == null || optionsAccessor.Options == null) if (optionsAccessor == null || optionsAccessor.Value == null)
{ {
throw new ArgumentNullException(nameof(optionsAccessor)); throw new ArgumentNullException(nameof(optionsAccessor));
} }
UserManager = userManager; UserManager = userManager;
RoleManager = roleManager; RoleManager = roleManager;
Options = optionsAccessor.Options; Options = optionsAccessor.Value;
} }
/// <summary> /// <summary>
@ -85,7 +85,7 @@ namespace Microsoft.AspNet.Identity
} }
var userId = await UserManager.GetUserIdAsync(user); var userId = await UserManager.GetUserIdAsync(user);
var userName = await UserManager.GetUserNameAsync(user); var userName = await UserManager.GetUserNameAsync(user);
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationType, var id = new ClaimsIdentity(Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme,
Options.ClaimsIdentity.UserNameClaimType, Options.ClaimsIdentity.UserNameClaimType,
Options.ClaimsIdentity.RoleClaimType); Options.ClaimsIdentity.RoleClaimType);
id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId)); id.AddClaim(new Claim(Options.ClaimsIdentity.UserIdClaimType, userId));

View File

@ -12,6 +12,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
@ -51,7 +52,7 @@ namespace Microsoft.AspNet.Identity
IEnumerable<IPasswordValidator<TUser>> passwordValidators, IEnumerable<IPasswordValidator<TUser>> passwordValidators,
ILookupNormalizer keyNormalizer, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IdentityErrorDescriber errors,
IEnumerable<IUserTokenProvider<TUser>> tokenProviders, IServiceProvider services,
ILogger<UserManager<TUser>> logger, ILogger<UserManager<TUser>> logger,
IHttpContextAccessor contextAccessor) IHttpContextAccessor contextAccessor)
{ {
@ -60,7 +61,7 @@ namespace Microsoft.AspNet.Identity
throw new ArgumentNullException(nameof(store)); throw new ArgumentNullException(nameof(store));
} }
Store = store; Store = store;
Options = optionsAccessor?.Options ?? new IdentityOptions(); Options = optionsAccessor?.Value ?? new IdentityOptions();
_context = contextAccessor?.HttpContext; _context = contextAccessor?.HttpContext;
PasswordHasher = passwordHasher; PasswordHasher = passwordHasher;
KeyNormalizer = keyNormalizer; KeyNormalizer = keyNormalizer;
@ -82,11 +83,15 @@ namespace Microsoft.AspNet.Identity
} }
} }
if (tokenProviders != null) if (services != null)
{ {
foreach (var tokenProvider in tokenProviders) foreach (var providerName in Options.Tokens.ProviderMap.Keys)
{ {
RegisterTokenProvider(tokenProvider); var provider = services.GetRequiredService(Options.Tokens.ProviderMap[providerName].ProviderType) as IUserTokenProvider<TUser>;
if (provider != null)
{
RegisterTokenProvider(providerName, provider);
}
} }
} }
} }
@ -715,7 +720,7 @@ namespace Microsoft.AspNet.Identity
public virtual Task<string> GeneratePasswordResetTokenAsync(TUser user) public virtual Task<string> GeneratePasswordResetTokenAsync(TUser user)
{ {
ThrowIfDisposed(); ThrowIfDisposed();
return GenerateUserTokenAsync(user, Options.PasswordResetTokenProvider, "ResetPassword"); return GenerateUserTokenAsync(user, Options.Tokens.PasswordResetTokenProvider, "ResetPassword");
} }
/// <summary> /// <summary>
@ -738,7 +743,7 @@ namespace Microsoft.AspNet.Identity
} }
// Make sure the token is valid and the stamp matches // Make sure the token is valid and the stamp matches
if (!await VerifyUserTokenAsync(user, Options.PasswordResetTokenProvider, "ResetPassword", token)) if (!await VerifyUserTokenAsync(user, Options.Tokens.PasswordResetTokenProvider, "ResetPassword", token))
{ {
return IdentityResult.Failed(ErrorDescriber.InvalidToken()); return IdentityResult.Failed(ErrorDescriber.InvalidToken());
} }
@ -1260,7 +1265,7 @@ namespace Microsoft.AspNet.Identity
public virtual Task<string> GenerateEmailConfirmationTokenAsync(TUser user) public virtual Task<string> GenerateEmailConfirmationTokenAsync(TUser user)
{ {
ThrowIfDisposed(); ThrowIfDisposed();
return GenerateUserTokenAsync(user, Options.EmailConfirmationTokenProvider, "EmailConfirmation"); return GenerateUserTokenAsync(user, Options.Tokens.EmailConfirmationTokenProvider, "EmailConfirmation");
} }
/// <summary> /// <summary>
@ -1281,7 +1286,7 @@ namespace Microsoft.AspNet.Identity
throw new ArgumentNullException("user"); throw new ArgumentNullException("user");
} }
if (!await VerifyUserTokenAsync(user, Options.EmailConfirmationTokenProvider, "EmailConfirmation", token)) if (!await VerifyUserTokenAsync(user, Options.Tokens.EmailConfirmationTokenProvider, "EmailConfirmation", token))
{ {
return IdentityResult.Failed(ErrorDescriber.InvalidToken()); return IdentityResult.Failed(ErrorDescriber.InvalidToken());
} }
@ -1319,7 +1324,7 @@ namespace Microsoft.AspNet.Identity
public virtual Task<string> GenerateChangeEmailTokenAsync(TUser user, string newEmail) public virtual Task<string> GenerateChangeEmailTokenAsync(TUser user, string newEmail)
{ {
ThrowIfDisposed(); ThrowIfDisposed();
return GenerateUserTokenAsync(user, Options.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail)); return GenerateUserTokenAsync(user, Options.Tokens.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail));
} }
/// <summary> /// <summary>
@ -1341,7 +1346,7 @@ namespace Microsoft.AspNet.Identity
} }
// Make sure the token is valid and the stamp matches // Make sure the token is valid and the stamp matches
if (!await VerifyUserTokenAsync(user, Options.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail), token)) if (!await VerifyUserTokenAsync(user, Options.Tokens.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail), token))
{ {
return IdentityResult.Failed(ErrorDescriber.InvalidToken()); return IdentityResult.Failed(ErrorDescriber.InvalidToken());
} }
@ -1556,15 +1561,16 @@ namespace Microsoft.AspNet.Identity
/// <summary> /// <summary>
/// Registers a token provider. /// Registers a token provider.
/// </summary> /// </summary>
/// <param name="providerName">The name of the provider to register.</param>
/// <param name="provider">The provider to register.</param> /// <param name="provider">The provider to register.</param>
public virtual void RegisterTokenProvider(IUserTokenProvider<TUser> provider) public virtual void RegisterTokenProvider(string providerName, IUserTokenProvider<TUser> provider)
{ {
ThrowIfDisposed(); ThrowIfDisposed();
if (provider == null) if (provider == null)
{ {
throw new ArgumentNullException("provider"); throw new ArgumentNullException("provider");
} }
_tokenProviders[provider.Name] = provider; _tokenProviders[providerName] = provider;
} }
/// <summary> /// <summary>

View File

@ -1,8 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNet.Identity namespace Microsoft.AspNet.Identity
{ {
/// <summary> /// <summary>

View File

@ -13,5 +13,8 @@
<PropertyGroup> <PropertyGroup>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project> </Project>

View File

@ -37,7 +37,7 @@ namespace Microsoft.AspNet.Identity.InMemory
public async Task CanChangePasswordOptions() public async Task CanChangePasswordOptions()
{ {
var clock = new TestClock(); var clock = new TestClock();
var server = CreateServer(services => services.ConfigureIdentity(options => var server = CreateServer(services => services.Configure<IdentityOptions>(options =>
{ {
options.Password.RequireUppercase = false; options.Password.RequireUppercase = false;
options.Password.RequireNonLetterOrDigit = false; options.Password.RequireNonLetterOrDigit = false;
@ -53,11 +53,11 @@ namespace Microsoft.AspNet.Identity.InMemory
public async Task CanCreateMeLoginAndCookieStopsWorkingAfterExpiration() public async Task CanCreateMeLoginAndCookieStopsWorkingAfterExpiration()
{ {
var clock = new TestClock(); var clock = new TestClock();
var server = CreateServer(services => services.ConfigureIdentityApplicationCookie(appCookieOptions => var server = CreateServer(services => services.Configure<IdentityOptions>(options =>
{ {
appCookieOptions.SystemClock = clock; options.Cookies.ApplicationCookie.SystemClock = clock;
appCookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(10); options.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromMinutes(10);
appCookieOptions.SlidingExpiration = false; options.Cookies.ApplicationCookie.SlidingExpiration = false;
})); }));
var transaction1 = await SendAsync(server, "http://example.com/createMe"); var transaction1 = await SendAsync(server, "http://example.com/createMe");
@ -92,9 +92,9 @@ namespace Microsoft.AspNet.Identity.InMemory
public async Task CanCreateMeLoginAndSecurityStampExtendsExpiration(bool rememberMe) public async Task CanCreateMeLoginAndSecurityStampExtendsExpiration(bool rememberMe)
{ {
var clock = new TestClock(); var clock = new TestClock();
var server = CreateServer(services => services.ConfigureIdentityApplicationCookie(appCookieOptions => var server = CreateServer(services => services.Configure<IdentityOptions>(options =>
{ {
appCookieOptions.SystemClock = clock; options.Cookies.ApplicationCookie.SystemClock = clock;
})); }));
var transaction1 = await SendAsync(server, "http://example.com/createMe"); var transaction1 = await SendAsync(server, "http://example.com/createMe");
@ -148,7 +148,7 @@ namespace Microsoft.AspNet.Identity.InMemory
transaction2.Response.StatusCode.ShouldBe(HttpStatusCode.OK); transaction2.Response.StatusCode.ShouldBe(HttpStatusCode.OK);
string setCookie = transaction2.SetCookie; string setCookie = transaction2.SetCookie;
setCookie.ShouldContain(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme + "="); setCookie.ShouldContain(new IdentityCookieOptions().TwoFactorRememberMeCookieAuthenticationScheme + "=");
setCookie.ShouldContain("; expires="); setCookie.ShouldContain("; expires=");
var transaction3 = await SendAsync(server, "http://example.com/isTwoFactorRememebered", transaction2.CookieNameValue); var transaction3 = await SendAsync(server, "http://example.com/isTwoFactorRememebered", transaction2.CookieNameValue);

View File

@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var auth = new Mock<AuthenticationManager>(); var auth = new Mock<AuthenticationManager>();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable(); context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
auth.Setup(a => a.SignInAsync(IdentityOptions.ApplicationCookieAuthenticationScheme, auth.Setup(a => a.SignInAsync(new IdentityCookieOptions().ApplicationCookieAuthenticationScheme,
It.IsAny<ClaimsPrincipal>(), It.IsAny<ClaimsPrincipal>(),
It.IsAny<AuthenticationProperties>())).Returns(Task.FromResult(0)).Verifiable(); It.IsAny<AuthenticationProperties>())).Returns(Task.FromResult(0)).Verifiable();
// REVIEW: is persistant mocking broken // REVIEW: is persistant mocking broken

View File

@ -13,5 +13,8 @@
<PropertyGroup> <PropertyGroup>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project> </Project>

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Identity.Test namespace Microsoft.AspNet.Identity.Test
@ -105,10 +106,30 @@ namespace Microsoft.AspNet.Identity.Test
services.AddIdentity<TestUser,TestRole>().AddDefaultTokenProviders(); services.AddIdentity<TestUser,TestRole>().AddDefaultTokenProviders();
var provider = services.BuildServiceProvider(); var provider = services.BuildServiceProvider();
var tokenProviders = provider.GetRequiredService<IEnumerable<IUserTokenProvider<TestUser>>>(); var tokenProviders = provider.GetRequiredService<IOptions<IdentityOptions>>().Value.Tokens.ProviderMap.Values;
Assert.Equal(3, tokenProviders.Count()); Assert.Equal(3, tokenProviders.Count());
} }
[Fact]
public void AddManagerWithWrongTypesThrows()
{
var services = new ServiceCollection();
var builder = services.AddIdentity<TestUser, TestRole>();
Assert.Throws<InvalidOperationException>(() => builder.AddUserManager<UserManager<TestUser>>());
Assert.Throws<InvalidOperationException>(() => builder.AddRoleManager<RoleManager<TestRole>>());
Assert.Throws<InvalidOperationException>(() => builder.AddUserManager<object>());
Assert.Throws<InvalidOperationException>(() => builder.AddRoleManager<object>());
}
[Fact]
public void AddTokenProviderWithWrongTypesThrows()
{
var services = new ServiceCollection();
var builder = services.AddIdentity<TestUser, TestRole>();
Assert.Throws<InvalidOperationException>(() => builder.AddTokenProvider<object>("whatevs"));
Assert.Throws<InvalidOperationException>(() => builder.AddTokenProvider("whatevs", typeof(object)));
}
private class MyUberThingy : IUserValidator<TestUser>, IPasswordValidator<TestUser>, IRoleValidator<TestRole>, IUserStore<TestUser>, IRoleStore<TestRole> private class MyUberThingy : IUserValidator<TestUser>, IPasswordValidator<TestUser>, IRoleValidator<TestRole>, IUserStore<TestUser>, IRoleStore<TestRole>
{ {
public Task<IdentityResult> CreateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) public Task<IdentityResult> CreateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))

View File

@ -66,10 +66,10 @@ namespace Microsoft.AspNet.Identity.Test
var services = new ServiceCollection(); var services = new ServiceCollection();
services.AddIdentity<TestUser,TestRole>(); services.AddIdentity<TestUser,TestRole>();
services.ConfigureIdentity(config.GetSection("identity")); services.Configure<IdentityOptions>(config.GetSection("identity"));
var accessor = services.BuildServiceProvider().GetRequiredService<IOptions<IdentityOptions>>(); var accessor = services.BuildServiceProvider().GetRequiredService<IOptions<IdentityOptions>>();
Assert.NotNull(accessor); Assert.NotNull(accessor);
var options = accessor.Options; var options = accessor.Value;
Assert.Equal(roleClaimType, options.ClaimsIdentity.RoleClaimType); Assert.Equal(roleClaimType, options.ClaimsIdentity.RoleClaimType);
Assert.Equal(useridClaimType, options.ClaimsIdentity.UserIdClaimType); Assert.Equal(useridClaimType, options.ClaimsIdentity.UserIdClaimType);
Assert.Equal(usernameClaimType, options.ClaimsIdentity.UserNameClaimType); Assert.Equal(usernameClaimType, options.ClaimsIdentity.UserNameClaimType);
@ -96,11 +96,11 @@ namespace Microsoft.AspNet.Identity.Test
var builder = new ConfigurationBuilder(new MemoryConfigurationSource(dic)); var builder = new ConfigurationBuilder(new MemoryConfigurationSource(dic));
var config = builder.Build(); var config = builder.Build();
var services = new ServiceCollection(); var services = new ServiceCollection();
services.ConfigureIdentity(config.GetSection("identity")); services.Configure<IdentityOptions>(config.GetSection("identity"));
services.AddIdentity<TestUser, TestRole>(o => { o.User.RequireUniqueEmail = false; o.Lockout.MaxFailedAccessAttempts++; }); services.AddIdentity<TestUser, TestRole>(o => { o.User.RequireUniqueEmail = false; o.Lockout.MaxFailedAccessAttempts++; });
var accessor = services.BuildServiceProvider().GetRequiredService<IOptions<IdentityOptions>>(); var accessor = services.BuildServiceProvider().GetRequiredService<IOptions<IdentityOptions>>();
Assert.NotNull(accessor); Assert.NotNull(accessor);
var options = accessor.Options; var options = accessor.Value;
Assert.False(options.User.RequireUniqueEmail); Assert.False(options.User.RequireUniqueEmail);
Assert.Equal(1001, options.Lockout.MaxFailedAccessAttempts); Assert.Equal(1001, options.Lockout.MaxFailedAccessAttempts);
} }
@ -124,7 +124,7 @@ namespace Microsoft.AspNet.Identity.Test
Assert.IsType(typeof(PasswordsNegativeLengthSetup), setup); Assert.IsType(typeof(PasswordsNegativeLengthSetup), setup);
var optionsGetter = serviceProvider.GetRequiredService<IOptions<IdentityOptions>>(); var optionsGetter = serviceProvider.GetRequiredService<IOptions<IdentityOptions>>();
Assert.NotNull(optionsGetter); Assert.NotNull(optionsGetter);
var myOptions = optionsGetter.Options; var myOptions = optionsGetter.Value;
Assert.True(myOptions.Password.RequireLowercase); Assert.True(myOptions.Password.RequireLowercase);
Assert.True(myOptions.Password.RequireDigit); Assert.True(myOptions.Password.RequireDigit);
Assert.True(myOptions.Password.RequireNonLetterOrDigit); Assert.True(myOptions.Password.RequireNonLetterOrDigit);
@ -135,16 +135,14 @@ namespace Microsoft.AspNet.Identity.Test
[Fact] [Fact]
public void CanSetupIdentityOptions() public void CanSetupIdentityOptions()
{ {
var services = new ServiceCollection() var services = new ServiceCollection();
.AddOptions() services.AddIdentity<TestUser,TestRole>(options => options.User.RequireUniqueEmail = true);
.ConfigureIdentity(options => options.User.RequireUniqueEmail = true);
services.AddIdentity<TestUser,TestRole>();
var serviceProvider = services.BuildServiceProvider(); var serviceProvider = services.BuildServiceProvider();
var optionsGetter = serviceProvider.GetRequiredService<IOptions<IdentityOptions>>(); var optionsGetter = serviceProvider.GetRequiredService<IOptions<IdentityOptions>>();
Assert.NotNull(optionsGetter); Assert.NotNull(optionsGetter);
var myOptions = optionsGetter.Options; var myOptions = optionsGetter.Value;
Assert.True(myOptions.User.RequireUniqueEmail); Assert.True(myOptions.User.RequireUniqueEmail);
} }
} }

View File

@ -164,14 +164,14 @@ namespace Microsoft.AspNet.Identity.Test
var options = new PasswordHasherOptionsAccessor(); var options = new PasswordHasherOptionsAccessor();
if (compatMode != null) if (compatMode != null)
{ {
options.Options.CompatibilityMode = (PasswordHasherCompatibilityMode)compatMode; options.Value.CompatibilityMode = (PasswordHasherCompatibilityMode)compatMode;
} }
if (iterCount != null) if (iterCount != null)
{ {
options.Options.IterationCount = (int)iterCount; options.Value.IterationCount = (int)iterCount;
} }
Assert.NotNull(options.Options.Rng); // should have a default value Assert.NotNull(options.Value.Rng); // should have a default value
options.Options.Rng = new SequentialRandomNumberGenerator(); options.Value.Rng = new SequentialRandomNumberGenerator();
return options; return options;
} }
} }

View File

@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Identity.Test
private static ClaimsPrincipal CreateAppIdentity(string authType = null) private static ClaimsPrincipal CreateAppIdentity(string authType = null)
{ {
authType = authType ?? IdentityOptions.ApplicationCookieAuthenticationType; authType = authType ?? new IdentityCookieOptions().ApplicationCookieAuthenticationScheme;
return new ClaimsPrincipal(new ClaimsIdentity( return new ClaimsPrincipal(new ClaimsIdentity(
new[] new[]
{ {

View File

@ -21,10 +21,11 @@ namespace Microsoft.AspNet.Identity.Test
[Fact] [Fact]
public async Task OnValidatePrincipalThrowsWithEmptyServiceCollection() public async Task OnValidatePrincipalThrowsWithEmptyServiceCollection()
{ {
var scheme = new IdentityOptions().Cookies.ApplicationCookieAuthenticationScheme;
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
httpContext.Setup(c => c.RequestServices).Returns(new ServiceCollection().BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(new ServiceCollection().BuildServiceProvider());
var id = new ClaimsPrincipal(new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme)); var id = new ClaimsPrincipal(new ClaimsIdentity(scheme));
var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow }, IdentityOptions.ApplicationCookieAuthenticationScheme); var ticket = new AuthenticationTicket(id, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow }, scheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => SecurityStampValidator.ValidatePrincipalAsync(context)); var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => SecurityStampValidator.ValidatePrincipalAsync(context));
Assert.True(ex.Message.Contains("No service for type 'Microsoft.Framework.OptionsModel.IOptions")); Assert.True(ex.Message.Contains("No service for type 'Microsoft.Framework.OptionsModel.IOptions"));
@ -40,11 +41,11 @@ namespace Microsoft.AspNet.Identity.Test
var claimsManager = new Mock<IUserClaimsPrincipalFactory<TestUser>>(); var claimsManager = new Mock<IUserClaimsPrincipalFactory<TestUser>>();
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero }; var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero };
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Value).Returns(identityOptions);
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object); contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object);
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme); var id = new ClaimsIdentity(identityOptions.Cookies.ApplicationCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var principal = new ClaimsPrincipal(id); var principal = new ClaimsPrincipal(id);
@ -61,7 +62,7 @@ namespace Microsoft.AspNet.Identity.Test
var ticket = new AuthenticationTicket(principal, var ticket = new AuthenticationTicket(principal,
properties, properties,
IdentityOptions.ApplicationCookieAuthenticationScheme); identityOptions.Cookies.ApplicationCookieAuthenticationScheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
Assert.NotNull(context.Properties); Assert.NotNull(context.Properties);
Assert.NotNull(context.Options); Assert.NotNull(context.Options);
@ -80,7 +81,7 @@ namespace Microsoft.AspNet.Identity.Test
var claimsManager = new Mock<IUserClaimsPrincipalFactory<TestUser>>(); var claimsManager = new Mock<IUserClaimsPrincipalFactory<TestUser>>();
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero }; var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero };
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Value).Returns(identityOptions);
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object); contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object);
@ -92,12 +93,12 @@ namespace Microsoft.AspNet.Identity.Test
services.AddInstance(signInManager.Object); services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<TestUser>()); services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<TestUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme); var id = new ClaimsIdentity(identityOptions.Cookies.ApplicationCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(new ClaimsPrincipal(id), var ticket = new AuthenticationTicket(new ClaimsPrincipal(id),
new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow }, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow },
IdentityOptions.ApplicationCookieAuthenticationScheme); identityOptions.Cookies.ApplicationCookieAuthenticationScheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
Assert.NotNull(context.Properties); Assert.NotNull(context.Properties);
Assert.NotNull(context.Options); Assert.NotNull(context.Options);
@ -116,7 +117,7 @@ namespace Microsoft.AspNet.Identity.Test
var claimsManager = new Mock<IUserClaimsPrincipalFactory<TestUser>>(); var claimsManager = new Mock<IUserClaimsPrincipalFactory<TestUser>>();
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero }; var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero };
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Value).Returns(identityOptions);
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object); contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object);
var signInManager = new Mock<SignInManager<TestUser>>(userManager.Object, var signInManager = new Mock<SignInManager<TestUser>>(userManager.Object,
@ -127,12 +128,12 @@ namespace Microsoft.AspNet.Identity.Test
services.AddInstance(signInManager.Object); services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<TestUser>()); services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<TestUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme); var id = new ClaimsIdentity(identityOptions.Cookies.ApplicationCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(new ClaimsPrincipal(id), var ticket = new AuthenticationTicket(new ClaimsPrincipal(id),
new AuthenticationProperties(), new AuthenticationProperties(),
IdentityOptions.ApplicationCookieAuthenticationScheme); identityOptions.Cookies.ApplicationCookieAuthenticationScheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
Assert.NotNull(context.Properties); Assert.NotNull(context.Properties);
Assert.NotNull(context.Options); Assert.NotNull(context.Options);
@ -151,7 +152,7 @@ namespace Microsoft.AspNet.Identity.Test
var claimsManager = new Mock<IUserClaimsPrincipalFactory<TestUser>>(); var claimsManager = new Mock<IUserClaimsPrincipalFactory<TestUser>>();
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.FromDays(1) }; var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.FromDays(1) };
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Value).Returns(identityOptions);
var contextAccessor = new Mock<IHttpContextAccessor>(); var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object); contextAccessor.Setup(a => a.HttpContext).Returns(httpContext.Object);
var signInManager = new Mock<SignInManager<TestUser>>(userManager.Object, var signInManager = new Mock<SignInManager<TestUser>>(userManager.Object,
@ -163,12 +164,12 @@ namespace Microsoft.AspNet.Identity.Test
services.AddInstance(signInManager.Object); services.AddInstance(signInManager.Object);
services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<TestUser>()); services.AddInstance<ISecurityStampValidator>(new SecurityStampValidator<TestUser>());
httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider()); httpContext.Setup(c => c.RequestServices).Returns(services.BuildServiceProvider());
var id = new ClaimsIdentity(IdentityOptions.ApplicationCookieAuthenticationScheme); var id = new ClaimsIdentity(identityOptions.Cookies.ApplicationCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); id.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id));
var ticket = new AuthenticationTicket(new ClaimsPrincipal(id), var ticket = new AuthenticationTicket(new ClaimsPrincipal(id),
new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow }, new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow },
IdentityOptions.ApplicationCookieAuthenticationScheme); identityOptions.Cookies.ApplicationCookieAuthenticationScheme);
var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions()); var context = new CookieValidatePrincipalContext(httpContext.Object, ticket, new CookieAuthenticationOptions());
Assert.NotNull(context.Properties); Assert.NotNull(context.Properties);
Assert.NotNull(context.Options); Assert.NotNull(context.Options);

View File

@ -122,7 +122,7 @@ namespace Microsoft.AspNet.Identity.Test
var roleManager = MockHelpers.MockRoleManager<TestRole>(); var roleManager = MockHelpers.MockRoleManager<TestRole>();
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Value).Returns(identityOptions);
var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object); var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object);
var logStore = new StringBuilder(); var logStore = new StringBuilder();
var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore); var logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore);
@ -155,7 +155,7 @@ namespace Microsoft.AspNet.Identity.Test
var roleManager = MockHelpers.MockRoleManager<TestRole>(); var roleManager = MockHelpers.MockRoleManager<TestRole>();
identityOptions = identityOptions ?? new IdentityOptions(); identityOptions = identityOptions ?? new IdentityOptions();
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Value).Returns(identityOptions);
var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager, roleManager.Object, options.Object); var claimsFactory = new UserClaimsPrincipalFactory<TestUser, TestRole>(manager, roleManager.Object, options.Object);
var sm = new SignInManager<TestUser>(manager, contextAccessor.Object, claimsFactory, options.Object, null); var sm = new SignInManager<TestUser>(manager, contextAccessor.Object, claimsFactory, options.Object, null);
sm.Logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore ?? new StringBuilder()).Object; sm.Logger = MockHelpers.MockILogger<SignInManager<TestUser>>(logStore ?? new StringBuilder()).Object;
@ -268,11 +268,11 @@ namespace Microsoft.AspNet.Identity.Test
manager.Setup(m => m.ResetAccessFailedCountAsync(user)).ReturnsAsync(IdentityResult.Success).Verifiable(); manager.Setup(m => m.ResetAccessFailedCountAsync(user)).ReturnsAsync(IdentityResult.Success).Verifiable();
} }
var context = new Mock<HttpContext>(); var context = new Mock<HttpContext>();
var helper = SetupSignInManager(manager.Object, context.Object);
var auth = new Mock<AuthenticationManager>(); var auth = new Mock<AuthenticationManager>();
auth.Setup(a => a.SignInAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme, auth.Setup(a => a.SignInAsync(helper.Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme,
It.Is<ClaimsPrincipal>(id => id.FindFirstValue(ClaimTypes.Name) == user.Id))).Returns(Task.FromResult(0)).Verifiable(); It.Is<ClaimsPrincipal>(id => id.FindFirstValue(ClaimTypes.Name) == user.Id))).Returns(Task.FromResult(0)).Verifiable();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable(); context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
var helper = SetupSignInManager(manager.Object, context.Object);
// Act // Act
var result = await helper.PasswordSignInAsync(user.UserName, "password", false, false); var result = await helper.PasswordSignInAsync(user.UserName, "password", false, false);
@ -340,7 +340,7 @@ namespace Microsoft.AspNet.Identity.Test
} }
// REVIEW: auth changes we lost the ability to mock is persistent // REVIEW: auth changes we lost the ability to mock is persistent
//var properties = new AuthenticationProperties { IsPersistent = isPersistent }; //var properties = new AuthenticationProperties { IsPersistent = isPersistent };
auth.Setup(a => a.AuthenticateAsync(It.Is<AuthenticateContext>(c => c.AuthenticationScheme == IdentityOptions.ApplicationCookieAuthenticationScheme))) auth.Setup(a => a.AuthenticateAsync(It.Is<AuthenticateContext>(c => c.AuthenticationScheme == IdentityCookieOptions.ApplicationCookieAuthenticationType)))
.Returns(Task.FromResult(0)).Verifiable(); .Returns(Task.FromResult(0)).Verifiable();
var manager = SetupUserManager(user); var manager = SetupUserManager(user);
@ -398,17 +398,18 @@ namespace Microsoft.AspNet.Identity.Test
var auth = new Mock<AuthenticationManager>(); var auth = new Mock<AuthenticationManager>();
var twoFactorInfo = new SignInManager<TestUser>.TwoFactorAuthenticationInfo { UserId = user.Id }; var twoFactorInfo = new SignInManager<TestUser>.TwoFactorAuthenticationInfo { UserId = user.Id };
var loginProvider = "loginprovider"; var loginProvider = "loginprovider";
var id = SignInManager<TestUser>.StoreTwoFactorInfo(user.Id, externalLogin ? loginProvider : null); var helper = SetupSignInManager(manager.Object, context.Object);
var id = helper.StoreTwoFactorInfo(user.Id, externalLogin ? loginProvider : null);
if (externalLogin) if (externalLogin)
{ {
auth.Setup(a => a.SignInAsync( auth.Setup(a => a.SignInAsync(
IdentityOptions.ApplicationCookieAuthenticationScheme, helper.Options.Cookies.ApplicationCookieAuthenticationScheme,
It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider
&& i.FindFirstValue(ClaimTypes.NameIdentifier) == user.Id), && i.FindFirstValue(ClaimTypes.NameIdentifier) == user.Id),
It.IsAny<AuthenticationProperties>())).Returns(Task.FromResult(0)).Verifiable(); It.IsAny<AuthenticationProperties>())).Returns(Task.FromResult(0)).Verifiable();
// REVIEW: restore ability to test is persistent // REVIEW: restore ability to test is persistent
//It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent))).Verifiable(); //It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent))).Verifiable();
auth.Setup(a => a.SignOutAsync(IdentityOptions.ExternalCookieAuthenticationScheme)).Returns(Task.FromResult(0)).Verifiable(); auth.Setup(a => a.SignOutAsync(helper.Options.Cookies.ExternalCookieAuthenticationScheme)).Returns(Task.FromResult(0)).Verifiable();
} }
else else
{ {
@ -417,15 +418,14 @@ namespace Microsoft.AspNet.Identity.Test
if (rememberClient) if (rememberClient)
{ {
auth.Setup(a => a.SignInAsync( auth.Setup(a => a.SignInAsync(
IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme, helper.Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme,
It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id
&& i.Identities.First().AuthenticationType == IdentityOptions.TwoFactorRememberMeCookieAuthenticationType), && i.Identities.First().AuthenticationType == helper.Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme),
It.IsAny<AuthenticationProperties>())).Returns(Task.FromResult(0)).Verifiable(); It.IsAny<AuthenticationProperties>())).Returns(Task.FromResult(0)).Verifiable();
//It.Is<AuthenticationProperties>(v => v.IsPersistent == true))).Returns(Task.FromResult(0)).Verifiable(); //It.Is<AuthenticationProperties>(v => v.IsPersistent == true))).Returns(Task.FromResult(0)).Verifiable();
} }
auth.Setup(a => a.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme)).ReturnsAsync(id).Verifiable(); auth.Setup(a => a.AuthenticateAsync(helper.Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme)).ReturnsAsync(id).Verifiable();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable(); context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
var helper = SetupSignInManager(manager.Object, context.Object);
// Act // Act
var result = await helper.TwoFactorSignInAsync(provider, code, isPersistent, rememberClient); var result = await helper.TwoFactorSignInAsync(provider, code, isPersistent, rememberClient);
@ -447,9 +447,9 @@ namespace Microsoft.AspNet.Identity.Test
var auth = new Mock<AuthenticationManager>(); var auth = new Mock<AuthenticationManager>();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable(); context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
auth.Setup(a => a.SignInAsync( auth.Setup(a => a.SignInAsync(
IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme, manager.Object.Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme,
It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id It.Is<ClaimsPrincipal>(i => i.FindFirstValue(ClaimTypes.Name) == user.Id
&& i.Identities.First().AuthenticationType == IdentityOptions.TwoFactorRememberMeCookieAuthenticationType), && i.Identities.First().AuthenticationType == manager.Object.Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme),
It.Is<AuthenticationProperties>(v => v.IsPersistent == true))).Returns(Task.FromResult(0)).Verifiable(); It.Is<AuthenticationProperties>(v => v.IsPersistent == true))).Returns(Task.FromResult(0)).Verifiable();
var helper = SetupSignInManager(manager.Object, context.Object); var helper = SetupSignInManager(manager.Object, context.Object);
@ -483,9 +483,9 @@ namespace Microsoft.AspNet.Identity.Test
var auth = new Mock<AuthenticationManager>(); var auth = new Mock<AuthenticationManager>();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable(); context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
SetupSignIn(auth); SetupSignIn(auth);
var id = new ClaimsIdentity(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType); var id = new ClaimsIdentity(manager.Object.Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme);
id.AddClaim(new Claim(ClaimTypes.Name, user.Id)); id.AddClaim(new Claim(ClaimTypes.Name, user.Id));
auth.Setup(a => a.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationScheme)).ReturnsAsync(new ClaimsPrincipal(id)).Verifiable(); auth.Setup(a => a.AuthenticateAsync(manager.Object.Options.Cookies.TwoFactorRememberMeCookieAuthenticationScheme)).ReturnsAsync(new ClaimsPrincipal(id)).Verifiable();
var helper = SetupSignInManager(manager.Object, context.Object); var helper = SetupSignInManager(manager.Object, context.Object);
// Act // Act
@ -509,9 +509,9 @@ namespace Microsoft.AspNet.Identity.Test
var auth = new Mock<AuthenticationManager>(); var auth = new Mock<AuthenticationManager>();
context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable(); context.Setup(c => c.Authentication).Returns(auth.Object).Verifiable();
auth.Setup(a => a.SignOutAsync(authenticationScheme)).Returns(Task.FromResult(0)).Verifiable(); auth.Setup(a => a.SignOutAsync(authenticationScheme)).Returns(Task.FromResult(0)).Verifiable();
auth.Setup(a => a.SignOutAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationScheme)).Returns(Task.FromResult(0)).Verifiable(); auth.Setup(a => a.SignOutAsync(manager.Object.Options.Cookies.TwoFactorUserIdCookieAuthenticationScheme)).Returns(Task.FromResult(0)).Verifiable();
auth.Setup(a => a.SignOutAsync(IdentityOptions.ExternalCookieAuthenticationScheme)).Returns(Task.FromResult(0)).Verifiable(); auth.Setup(a => a.SignOutAsync(manager.Object.Options.Cookies.ExternalCookieAuthenticationScheme)).Returns(Task.FromResult(0)).Verifiable();
IdentityOptions.ApplicationCookieAuthenticationScheme = authenticationScheme; IdentityCookieOptions.ApplicationCookieAuthenticationType = authenticationScheme;
var helper = SetupSignInManager(manager.Object, context.Object); var helper = SetupSignInManager(manager.Object, context.Object);
// Act // Act
@ -631,7 +631,7 @@ namespace Microsoft.AspNet.Identity.Test
private static void SetupSignIn(Mock<AuthenticationManager> auth, string userId = null, bool? isPersistent = null, string loginProvider = null) private static void SetupSignIn(Mock<AuthenticationManager> auth, string userId = null, bool? isPersistent = null, string loginProvider = null)
{ {
auth.Setup(a => a.SignInAsync(IdentityOptions.ApplicationCookieAuthenticationScheme, auth.Setup(a => a.SignInAsync(IdentityCookieOptions.ApplicationCookieAuthenticationType,
It.Is<ClaimsPrincipal>(id => It.Is<ClaimsPrincipal>(id =>
(userId == null || id.FindFirstValue(ClaimTypes.NameIdentifier) == userId) && (userId == null || id.FindFirstValue(ClaimTypes.NameIdentifier) == userId) &&
(loginProvider == null || id.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider)), (loginProvider == null || id.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider)),

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Throws<ArgumentNullException>("optionsAccessor", Assert.Throws<ArgumentNullException>("optionsAccessor",
() => new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager, roleManager, options.Object)); () => new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager, roleManager, options.Object));
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Value).Returns(identityOptions);
var factory = new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager, roleManager, options.Object); var factory = new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager, roleManager, options.Object);
await Assert.ThrowsAsync<ArgumentNullException>("user", await Assert.ThrowsAsync<ArgumentNullException>("user",
async () => await factory.CreateAsync(null)); async () => await factory.CreateAsync(null));
@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Identity.Test
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
var identityOptions = new IdentityOptions(); var identityOptions = new IdentityOptions();
options.Setup(a => a.Options).Returns(identityOptions); options.Setup(a => a.Value).Returns(identityOptions);
var factory = new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager.Object, roleManager.Object, options.Object); var factory = new UserClaimsPrincipalFactory<TestUser, TestRole>(userManager.Object, roleManager.Object, options.Object);
// Act // Act
@ -83,7 +83,7 @@ namespace Microsoft.AspNet.Identity.Test
var manager = userManager.Object; var manager = userManager.Object;
Assert.NotNull(identity); Assert.NotNull(identity);
Assert.Equal(1, principal.Identities.Count()); Assert.Equal(1, principal.Identities.Count());
Assert.Equal(IdentityOptions.ApplicationCookieAuthenticationType, identity.AuthenticationType); Assert.Equal(identityOptions.Cookies.TwoFactorRememberMeCookieAuthenticationScheme, identity.AuthenticationType);
var claims = identity.Claims.ToList(); var claims = identity.Claims.ToList();
Assert.NotNull(claims); Assert.NotNull(claims);
Assert.True( Assert.True(

View File

@ -48,17 +48,6 @@ namespace Microsoft.AspNet.Identity.Test
provider.GetRequiredService<CustomRoleManager>()); provider.GetRequiredService<CustomRoleManager>());
} }
[Fact]
public void AddManagerWithWrongTypesThrows()
{
var services = new ServiceCollection();
var builder = services.AddIdentity<TestUser, TestRole>();
Assert.Throws<InvalidOperationException>(() => builder.AddUserManager<UserManager<TestUser>>());
Assert.Throws<InvalidOperationException>(() => builder.AddRoleManager<RoleManager<TestRole>>());
Assert.Throws<InvalidOperationException>(() => builder.AddUserManager<object>());
Assert.Throws<InvalidOperationException>(() => builder.AddRoleManager<object>());
}
public class CustomUserManager : UserManager<TestUser> public class CustomUserManager : UserManager<TestUser>
{ {
public CustomUserManager() : base(new Mock<IUserStore<TestUser>>().Object, null, null, null, null, null, null, null, null, null) public CustomUserManager() : base(new Mock<IUserStore<TestUser>>().Object, null, null, null, null, null, null, null, null, null)
@ -714,7 +703,7 @@ namespace Microsoft.AspNet.Identity.Test
await Assert.ThrowsAsync<ArgumentNullException>("providerKey", await Assert.ThrowsAsync<ArgumentNullException>("providerKey",
async () => await manager.RemoveLoginAsync(null, "", null)); async () => await manager.RemoveLoginAsync(null, "", null));
await Assert.ThrowsAsync<ArgumentNullException>("email", async () => await manager.FindByEmailAsync(null)); await Assert.ThrowsAsync<ArgumentNullException>("email", async () => await manager.FindByEmailAsync(null));
Assert.Throws<ArgumentNullException>("provider", () => manager.RegisterTokenProvider(null)); Assert.Throws<ArgumentNullException>("provider", () => manager.RegisterTokenProvider("whatever", null));
await Assert.ThrowsAsync<ArgumentNullException>("roles", async () => await manager.AddToRolesAsync(new TestUser(), null)); await Assert.ThrowsAsync<ArgumentNullException>("roles", async () => await manager.AddToRolesAsync(new TestUser(), null));
await Assert.ThrowsAsync<ArgumentNullException>("roles", async () => await manager.RemoveFromRolesAsync(new TestUser(), null)); await Assert.ThrowsAsync<ArgumentNullException>("roles", async () => await manager.RemoveFromRolesAsync(new TestUser(), null));
} }
@ -723,7 +712,7 @@ namespace Microsoft.AspNet.Identity.Test
public async Task MethodsFailWithUnknownUserTest() public async Task MethodsFailWithUnknownUserTest()
{ {
var manager = MockHelpers.TestUserManager(new EmptyStore()); var manager = MockHelpers.TestUserManager(new EmptyStore());
manager.RegisterTokenProvider(new NoOpTokenProvider()); manager.RegisterTokenProvider("whatever", new NoOpTokenProvider());
await Assert.ThrowsAsync<ArgumentNullException>("user", await Assert.ThrowsAsync<ArgumentNullException>("user",
async () => await manager.GetUserNameAsync(null)); async () => await manager.GetUserNameAsync(null));
await Assert.ThrowsAsync<ArgumentNullException>("user", await Assert.ThrowsAsync<ArgumentNullException>("user",

View File

@ -3,14 +3,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Text; using System.Text;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Moq; using Moq;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
using System.Linq;
using Microsoft.AspNet.Hosting;
namespace Microsoft.AspNet.Identity.Test namespace Microsoft.AspNet.Identity.Test
{ {
@ -70,7 +67,7 @@ namespace Microsoft.AspNet.Identity.Test
var options = new Mock<IOptions<IdentityOptions>>(); var options = new Mock<IOptions<IdentityOptions>>();
var idOptions = new IdentityOptions(); var idOptions = new IdentityOptions();
idOptions.Lockout.AllowedForNewUsers = false; idOptions.Lockout.AllowedForNewUsers = false;
options.Setup(o => o.Options).Returns(idOptions); options.Setup(o => o.Value).Returns(idOptions);
var userValidators = new List<IUserValidator<TUser>>(); var userValidators = new List<IUserValidator<TUser>>();
var validator = new Mock<IUserValidator<TUser>>(); var validator = new Mock<IUserValidator<TUser>>();
userValidators.Add(validator.Object); userValidators.Add(validator.Object);
@ -78,7 +75,7 @@ namespace Microsoft.AspNet.Identity.Test
pwdValidators.Add(new PasswordValidator<TUser>()); pwdValidators.Add(new PasswordValidator<TUser>());
var userManager = new UserManager<TUser>(store, options.Object, new PasswordHasher<TUser>(), var userManager = new UserManager<TUser>(store, options.Object, new PasswordHasher<TUser>(),
userValidators, pwdValidators, new UpperInvariantLookupNormalizer(), userValidators, pwdValidators, new UpperInvariantLookupNormalizer(),
new IdentityErrorDescriber(), Enumerable.Empty<IUserTokenProvider<TUser>>(), new IdentityErrorDescriber(), null,
new Mock<ILogger<UserManager<TUser>>>().Object, new Mock<ILogger<UserManager<TUser>>>().Object,
null); null);
validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>())) validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>()))

View File

@ -8,11 +8,6 @@ namespace Microsoft.AspNet.Identity.Test
{ {
internal class PasswordHasherOptionsAccessor : IOptions<PasswordHasherOptions> internal class PasswordHasherOptionsAccessor : IOptions<PasswordHasherOptions>
{ {
public PasswordHasherOptions Options { get; } = new PasswordHasherOptions(); public PasswordHasherOptions Value { get; } = new PasswordHasherOptions();
public PasswordHasherOptions GetNamedOptions(string name)
{
throw new NotImplementedException();
}
} }
} }

View File

@ -32,23 +32,22 @@ namespace Microsoft.AspNet.Identity.Test
protected virtual void SetupIdentityServices(IServiceCollection services, object context = null) protected virtual void SetupIdentityServices(IServiceCollection services, object context = null)
{ {
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddIdentity<TUser, TRole>().AddDefaultTokenProviders(); services.AddIdentity<TUser, TRole>(options =>
AddUserStore(services, context);
AddRoleStore(services, context);
services.AddLogging();
services.AddInstance<ILogger<UserManager<TUser>>>(new TestLogger<UserManager<TUser>>());
services.AddInstance<ILogger<RoleManager<TRole>>>(new TestLogger<RoleManager<TRole>>());
services.ConfigureIdentity(options =>
{ {
options.Password.RequireDigit = false; options.Password.RequireDigit = false;
options.Password.RequireLowercase = false; options.Password.RequireLowercase = false;
options.Password.RequireNonLetterOrDigit = false; options.Password.RequireNonLetterOrDigit = false;
options.Password.RequireUppercase = false; options.Password.RequireUppercase = false;
options.User.AllowedUserNameCharacters = null; options.User.AllowedUserNameCharacters = null;
}); }).AddDefaultTokenProviders();
AddUserStore(services, context);
AddRoleStore(services, context);
services.AddLogging();
services.AddInstance<ILogger<UserManager<TUser>>>(new TestLogger<UserManager<TUser>>());
services.AddInstance<ILogger<RoleManager<TRole>>>(new TestLogger<RoleManager<TRole>>());
} }
protected virtual UserManager<TUser> CreateManager(object context = null, IServiceCollection services = null) protected virtual UserManager<TUser> CreateManager(object context = null, IServiceCollection services = null, Action<IServiceCollection> configureServices = null)
{ {
if (services == null) if (services == null)
{ {
@ -59,6 +58,10 @@ namespace Microsoft.AspNet.Identity.Test
context = CreateTestContext(); context = CreateTestContext();
} }
SetupIdentityServices(services, context); SetupIdentityServices(services, context);
if (configureServices != null)
{
configureServices(services);
}
return services.BuildServiceProvider().GetService<UserManager<TUser>>(); return services.BuildServiceProvider().GetService<UserManager<TUser>>();
} }
@ -648,8 +651,6 @@ namespace Microsoft.AspNet.Identity.Test
private class StaticTokenProvider : IUserTokenProvider<TUser> private class StaticTokenProvider : IUserTokenProvider<TUser>
{ {
public string Name { get; } = "Static";
public async Task<string> GenerateAsync(string purpose, UserManager<TUser> manager, TUser user) public async Task<string> GenerateAsync(string purpose, UserManager<TUser> manager, TUser user)
{ {
return MakeToken(purpose, await manager.GetUserIdAsync(user)); return MakeToken(purpose, await manager.GetUserIdAsync(user));
@ -680,8 +681,8 @@ namespace Microsoft.AspNet.Identity.Test
public async Task CanResetPasswordWithStaticTokenProvider() public async Task CanResetPasswordWithStaticTokenProvider()
{ {
var manager = CreateManager(); var manager = CreateManager();
manager.RegisterTokenProvider(new StaticTokenProvider()); manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.PasswordResetTokenProvider = "Static"; manager.Options.Tokens.PasswordResetTokenProvider = "Static";
var user = CreateTestUser(); var user = CreateTestUser();
const string password = "password"; const string password = "password";
const string newPassword = "newpassword"; const string newPassword = "newpassword";
@ -701,8 +702,8 @@ namespace Microsoft.AspNet.Identity.Test
public async Task PasswordValidatorCanBlockResetPasswordWithStaticTokenProvider() public async Task PasswordValidatorCanBlockResetPasswordWithStaticTokenProvider()
{ {
var manager = CreateManager(); var manager = CreateManager();
manager.RegisterTokenProvider(new StaticTokenProvider()); manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.PasswordResetTokenProvider = "Static"; manager.Options.Tokens.PasswordResetTokenProvider = "Static";
var user = CreateTestUser(); var user = CreateTestUser();
const string password = "password"; const string password = "password";
const string newPassword = "newpassword"; const string newPassword = "newpassword";
@ -723,8 +724,8 @@ namespace Microsoft.AspNet.Identity.Test
public async Task ResetPasswordWithStaticTokenProviderFailsWithWrongToken() public async Task ResetPasswordWithStaticTokenProviderFailsWithWrongToken()
{ {
var manager = CreateManager(); var manager = CreateManager();
manager.RegisterTokenProvider(new StaticTokenProvider()); manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.PasswordResetTokenProvider = "Static"; manager.Options.Tokens.PasswordResetTokenProvider = "Static";
var user = CreateTestUser(); var user = CreateTestUser();
const string password = "password"; const string password = "password";
const string newPassword = "newpassword"; const string newPassword = "newpassword";
@ -741,7 +742,7 @@ namespace Microsoft.AspNet.Identity.Test
public async Task CanGenerateAndVerifyUserTokenWithStaticTokenProvider() public async Task CanGenerateAndVerifyUserTokenWithStaticTokenProvider()
{ {
var manager = CreateManager(); var manager = CreateManager();
manager.RegisterTokenProvider(new StaticTokenProvider()); manager.RegisterTokenProvider("Static", new StaticTokenProvider());
var user = CreateTestUser(); var user = CreateTestUser();
var user2 = CreateTestUser(); var user2 = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user)); IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@ -765,8 +766,8 @@ namespace Microsoft.AspNet.Identity.Test
public async Task CanConfirmEmailWithStaticToken() public async Task CanConfirmEmailWithStaticToken()
{ {
var manager = CreateManager(); var manager = CreateManager();
manager.RegisterTokenProvider(new StaticTokenProvider()); manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.EmailConfirmationTokenProvider = "Static"; manager.Options.Tokens.EmailConfirmationTokenProvider = "Static";
var user = CreateTestUser(); var user = CreateTestUser();
Assert.False(await manager.IsEmailConfirmedAsync(user)); Assert.False(await manager.IsEmailConfirmedAsync(user));
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user)); IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@ -783,8 +784,8 @@ namespace Microsoft.AspNet.Identity.Test
public async Task ConfirmEmailWithStaticTokenFailsWithWrongToken() public async Task ConfirmEmailWithStaticTokenFailsWithWrongToken()
{ {
var manager = CreateManager(); var manager = CreateManager();
manager.RegisterTokenProvider(new StaticTokenProvider()); manager.RegisterTokenProvider("Static", new StaticTokenProvider());
manager.Options.EmailConfirmationTokenProvider = "Static"; manager.Options.Tokens.EmailConfirmationTokenProvider = "Static";
var user = CreateTestUser(); var user = CreateTestUser();
Assert.False(await manager.IsEmailConfirmedAsync(user)); Assert.False(await manager.IsEmailConfirmedAsync(user));
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user)); IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
@ -1449,6 +1450,27 @@ namespace Microsoft.AspNet.Identity.Test
Assert.NotEqual(stamp, await manager.GetSecurityStampAsync(user)); Assert.NotEqual(stamp, await manager.GetSecurityStampAsync(user));
} }
[Fact]
public async Task CanChangeEmailWithDifferentTokenProvider()
{
var manager = CreateManager(context: null, services: null,
configureServices: s => s.Configure<IdentityOptions>(
o => o.Tokens.ProviderMap["NewProvider2"] = new TokenProviderDescriptor(typeof(EmailTokenProvider<TUser>))));
manager.Options.Tokens.ChangeEmailTokenProvider = "NewProvider2";
var user = CreateTestUser("foouser");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
var email = await manager.GetUserNameAsync(user) + "@diddly.bop";
IdentityResultAssert.IsSuccess(await manager.SetEmailAsync(user, email));
Assert.False(await manager.IsEmailConfirmedAsync(user));
var stamp = await manager.GetSecurityStampAsync(user);
var newEmail = await manager.GetUserNameAsync(user) + "@en.vec";
var token1 = await manager.GenerateChangeEmailTokenAsync(user, newEmail);
IdentityResultAssert.IsSuccess(await manager.ChangeEmailAsync(user, newEmail, token1));
Assert.True(await manager.IsEmailConfirmedAsync(user));
Assert.Equal(await manager.GetEmailAsync(user), newEmail);
Assert.NotEqual(stamp, await manager.GetSecurityStampAsync(user));
}
[Fact] [Fact]
public async Task ChangeEmailFailsWithWrongToken() public async Task ChangeEmailFailsWithWrongToken()
{ {