Remove identity message apis

Fixes https://github.com/aspnet/Identity/issues/359
This commit is contained in:
Hao Kung 2015-03-05 13:32:35 -08:00
parent 04599f92c1
commit c2e96fa570
21 changed files with 58 additions and 575 deletions

View File

@ -2,13 +2,15 @@
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using IdentitySample.Models;
using IdentitySamples;
using Microsoft.AspNet.Authentication;
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Authorization;
namespace IdentitySample.Models
namespace IdentitySample.Controllers
{
[Authorize]
public class AccountController : Controller
@ -92,13 +94,8 @@ namespace IdentitySample.Models
{
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Context.Request.Scheme);
var email = new IdentityMessage
{
Destination = model.Email,
Subject = "Confirm your account",
Body = "Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>"
};
await UserManager.SendMessageAsync("Email", email);
await MessageServices.SendEmailAsync(model.Email, "Confirm your account",
"Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");
ViewBag.Link = callbackUrl;
return View("DisplayEmail");
}
@ -255,13 +252,8 @@ namespace IdentitySample.Models
var code = await UserManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Context.Request.Scheme);
var email = new IdentityMessage
{
Destination = model.Email,
Subject = "Reset Password",
Body = "Please reset your password by clicking here: <a href=\"" + callbackUrl + "\">link</a>"
};
await UserManager.SendMessageAsync("Email", email);
await MessageServices.SendEmailAsync(model.Email, "Reset Password",
"Please reset your password by clicking here: <a href=\"" + callbackUrl + "\">link</a>");
ViewBag.Link = callbackUrl;
return View("ForgotPasswordConfirmation");
}
@ -351,11 +343,29 @@ namespace IdentitySample.Models
return View();
}
// Generate the token and send it
if (!await SignInManager.SendTwoFactorCodeAsync(model.SelectedProvider))
var user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
return View("Error");
}
// Generate the token and send it
var code = await UserManager.GenerateTwoFactorTokenAsync(user, model.SelectedProvider);
if (string.IsNullOrWhiteSpace(code))
{
return View("Error");
}
var message = "Your security code is: " + code;
if (model.SelectedProvider == "Email")
{
await MessageServices.SendEmailAsync(await UserManager.GetEmailAsync(user), "Security Code", message);
}
else if (model.SelectedProvider == "Phone")
{
await MessageServices.SendSmsAsync(await UserManager.GetPhoneNumberAsync(user), message);
}
return RedirectToAction("VerifyCode", new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
}

View File

@ -1,6 +1,6 @@
using Microsoft.AspNet.Mvc;
namespace IdentitySample.Models
namespace IdentitySample.Controllers
{
public class HomeController : Controller
{

View File

@ -2,11 +2,12 @@
using System.Security.Principal;
using System.Threading.Tasks;
using IdentitySample.Models;
using IdentitySamples;
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc;
namespace IdentitySample
namespace IdentitySample.Controllers
{
[Authorize]
public class ManageController : Controller
@ -98,12 +99,7 @@ namespace IdentitySample
// Generate the token and send it
var user = await GetCurrentUserAsync();
var code = await UserManager.GenerateChangePhoneNumberTokenAsync(user, model.Number);
var message = new IdentityMessage
{
Destination = model.Number,
Body = "Your security code is: " + code
};
await UserManager.SendMessageAsync("SMS", message);
await MessageServices.SendSmsAsync(model.Number, "Your security code is: " + code);
return RedirectToAction("VerifyPhoneNumber", new { PhoneNumber = model.Number });
}

View File

@ -0,0 +1,20 @@
using System.Threading.Tasks;
namespace IdentitySamples
{
public static class MessageServices
{
public static Task SendEmailAsync(string email, string subject, string message)
{
// Plug in your email service
return Task.FromResult(0);
}
public static Task SendSmsAsync(string number, string message)
{
// Plug in your sms service
return Task.FromResult(0);
}
}
}

View File

@ -1,16 +1,12 @@
using System;
using IdentitySample.Models;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Diagnostics;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Routing;
using Microsoft.Data.Entity;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Logging;
using Microsoft.Framework.Logging.Console;
using System.Threading.Tasks;
using System.Threading;
namespace IdentitySamples
{
@ -42,9 +38,7 @@ namespace IdentitySamples
services.AddIdentity<ApplicationUser, IdentityRole>(Configuration)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddMessageProvider<EmailMessageProvider>()
.AddMessageProvider<SmsMessageProvider>();
.AddDefaultTokenProviders();
services.ConfigureFacebookAuthentication(options =>
{
@ -86,39 +80,5 @@ namespace IdentitySamples
SampleData.InitializeIdentityDatabaseAsync(app.ApplicationServices).Wait();
}
public class EmailMessageProvider : IIdentityMessageProvider
{
public string Name
{
get
{
return "Email";
}
}
public Task SendAsync(IdentityMessage message, CancellationToken cancellationToken = default(CancellationToken))
{
// Plug in your service
return Task.FromResult(0);
}
}
public class SmsMessageProvider : IIdentityMessageProvider
{
public string Name
{
get
{
return "SMS";
}
}
public Task SendAsync(IdentityMessage message, CancellationToken cancellationToken = default(CancellationToken))
{
// Plug in your service
return Task.FromResult(0);
}
}
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Framework.OptionsModel;
@ -8,16 +6,7 @@ namespace Microsoft.AspNet.Identity
{
public class EmailTokenProviderOptions
{
public string Name { get; set; } = Resources.DefaultEmailTokenProviderName;
public string MessageProvider { get; set; } = "Email";
public string Subject { get; set; } = "Security Code";
/// <summary>
/// Format string which will be used for the email body, it will be passed the token for the first parameter
/// </summary>
public string BodyFormat { get; set; } = "Your security code is: {0}";
public string Name { get; set; } = "Email";
}
/// <summary>
@ -65,27 +54,5 @@ namespace Microsoft.AspNet.Identity
var email = await manager.GetEmailAsync(user);
return "Email:" + purpose + ":" + email;
}
/// <summary>
/// Notifies the user with a token via email using the Subject and BodyFormat
/// </summary>
/// <param name="token"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
public override async Task NotifyAsync(string token, UserManager<TUser> manager, TUser user)
{
if (manager == null)
{
throw new ArgumentNullException(nameof(manager));
}
var msg = new IdentityMessage
{
Destination = await manager.GetEmailAsync(user),
Subject = Options.Subject,
Body = string.Format(CultureInfo.CurrentCulture, Options.BodyFormat, token)
};
await manager.SendMessageAsync(Options.MessageProvider, msg);
}
}
}

View File

@ -1,15 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
{
public interface IIdentityMessageProvider
{
string Name { get; }
Task SendAsync(IdentityMessage message, CancellationToken cancellationToken);
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity
@ -35,15 +34,6 @@ namespace Microsoft.AspNet.Identity
/// <returns></returns>
Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user);
/// <summary>
/// Notifies the user that a token has been generated, i.e. via email or sms, or can no-op
/// </summary>
/// <param name="token"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
Task NotifyAsync(string token, UserManager<TUser> manager, TUser user);
/// <summary>
/// Returns true if provider can be used for this user to generate two factor tokens, i.e. could require a user to have an email
/// </summary>

View File

@ -66,11 +66,6 @@ namespace Microsoft.AspNet.Identity
return AddScoped(typeof(IUserTokenProvider<>).MakeGenericType(UserType), provider);
}
public virtual IdentityBuilder AddMessageProvider<TProvider>() where TProvider : IIdentityMessageProvider
{
return AddScoped(typeof(IIdentityMessageProvider), typeof(TProvider));
}
public virtual IdentityBuilder AddDefaultTokenProviders()
{
Services.Configure<DataProtectionTokenProviderOptions>(options =>

View File

@ -1,26 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Identity
{
/// <summary>
/// Represents a message
/// </summary>
public class IdentityMessage
{
/// <summary>
/// Target for the message, i.e. email or phone number
/// </summary>
public virtual string Destination { get; set; }
/// <summary>
/// Subject
/// </summary>
public virtual string Subject { get; set; }
/// <summary>
/// Message contents
/// </summary>
public virtual string Body { get; set; }
}
}

View File

@ -7,14 +7,7 @@ namespace Microsoft.AspNet.Identity
{
public class PhoneNumberTokenProviderOptions
{
public string Name { get; set; } = Resources.DefaultPhoneNumberTokenProviderName;
public string MessageProvider { get; set; } = "SMS";
/// <summary>
/// Message contents which should contain a format string which the token will be the only argument
/// </summary>
public string MessageFormat { get; set; } = Resources.DefaultPhoneNumberTokenProviderMessageFormat;
public string Name { get; set; } = "Phone";
}
/// <summary>
@ -69,26 +62,5 @@ namespace Microsoft.AspNet.Identity
var phoneNumber = await manager.GetPhoneNumberAsync(user);
return "PhoneNumber:" + purpose + ":" + phoneNumber;
}
/// <summary>
/// Notifies the user with a token via SMS using the MessageFormat
/// </summary>
/// <param name="token"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
public override async Task NotifyAsync(string token, UserManager<TUser> manager, TUser user)
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
var msg = new IdentityMessage
{
Destination = await manager.GetPhoneNumberAsync(user),
Body = string.Format(CultureInfo.CurrentCulture, Options.MessageFormat, token)
};
await manager.SendMessageAsync(Options.MessageProvider, msg);
}
}
}

View File

@ -26,54 +26,6 @@ namespace Microsoft.AspNet.Identity
return GetString("ConcurrencyFailure");
}
/// <summary>
/// Your security code is: {0}
/// </summary>
internal static string DefaultEmailTokenProviderBodyFormat
{
get { return GetString("DefaultEmailTokenProviderBodyFormat"); }
}
/// <summary>
/// Your security code is: {0}
/// </summary>
internal static string FormatDefaultEmailTokenProviderBodyFormat(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("DefaultEmailTokenProviderBodyFormat"), p0);
}
/// <summary>
/// Email
/// </summary>
internal static string DefaultEmailTokenProviderName
{
get { return GetString("DefaultEmailTokenProviderName"); }
}
/// <summary>
/// Email
/// </summary>
internal static string FormatDefaultEmailTokenProviderName()
{
return GetString("DefaultEmailTokenProviderName");
}
/// <summary>
/// Security code
/// </summary>
internal static string DefaultEmailTokenProviderSubject
{
get { return GetString("DefaultEmailTokenProviderSubject"); }
}
/// <summary>
/// Security code
/// </summary>
internal static string FormatDefaultEmailTokenProviderSubject()
{
return GetString("DefaultEmailTokenProviderSubject");
}
/// <summary>
/// An unknown failure has occured.
/// </summary>
@ -90,38 +42,6 @@ namespace Microsoft.AspNet.Identity
return GetString("DefaultError");
}
/// <summary>
/// Your security code is: {0}
/// </summary>
internal static string DefaultPhoneNumberTokenProviderMessageFormat
{
get { return GetString("DefaultPhoneNumberTokenProviderMessageFormat"); }
}
/// <summary>
/// Your security code is: {0}
/// </summary>
internal static string FormatDefaultPhoneNumberTokenProviderMessageFormat(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("DefaultPhoneNumberTokenProviderMessageFormat"), p0);
}
/// <summary>
/// Phone
/// </summary>
internal static string DefaultPhoneNumberTokenProviderName
{
get { return GetString("DefaultPhoneNumberTokenProviderName"); }
}
/// <summary>
/// Phone
/// </summary>
internal static string FormatDefaultPhoneNumberTokenProviderName()
{
return GetString("DefaultPhoneNumberTokenProviderName");
}
/// <summary>
/// Default Token Provider
/// </summary>
@ -298,22 +218,6 @@ namespace Microsoft.AspNet.Identity
return GetString("LoginAlreadyAssociated");
}
/// <summary>
/// No IUserMessageProvider named '{0}' is registered.
/// </summary>
internal static string NoMessageProvider
{
get { return GetString("NoMessageProvider"); }
}
/// <summary>
/// No IUserMessageProvider named '{0}' is registered.
/// </summary>
internal static string FormatNoMessageProvider(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("NoMessageProvider"), p0);
}
/// <summary>
/// No IUserTokenProvider named '{0}' is registered.
/// </summary>

View File

@ -121,30 +121,10 @@
<value>Optimistic concurrency failure, object has been modified.</value>
<comment>Error when optimistic concurrency fails</comment>
</data>
<data name="DefaultEmailTokenProviderBodyFormat" xml:space="preserve">
<value>Your security code is: {0}</value>
<comment>Default body format for the email</comment>
</data>
<data name="DefaultEmailTokenProviderName" xml:space="preserve">
<value>Email</value>
<comment>Default name for the email token provider</comment>
</data>
<data name="DefaultEmailTokenProviderSubject" xml:space="preserve">
<value>Security code</value>
<comment>Default subject for the email</comment>
</data>
<data name="DefaultError" xml:space="preserve">
<value>An unknown failure has occured.</value>
<comment>Default identity result error message</comment>
</data>
<data name="DefaultPhoneNumberTokenProviderMessageFormat" xml:space="preserve">
<value>Your security code is: {0}</value>
<comment>Default message format for the phone number token provider</comment>
</data>
<data name="DefaultPhoneNumberTokenProviderName" xml:space="preserve">
<value>Phone</value>
<comment>Default name for the phone number token provider</comment>
</data>
<data name="DefaultTokenProvider" xml:space="preserve">
<value>Default Token Provider</value>
<comment>Name of the default token provider</comment>
@ -189,10 +169,6 @@
<value>A user with this login already exists.</value>
<comment>Error when a login already linked</comment>
</data>
<data name="NoMessageProvider" xml:space="preserve">
<value>No IUserMessageProvider named '{0}' is registered.</value>
<comment>Error when there is no IUserMessageProvider</comment>
</data>
<data name="NoTokenProvider" xml:space="preserve">
<value>No IUserTokenProvider named '{0}' is registered.</value>
<comment>Error when there is no IUserTokenProvider</comment>

View File

@ -202,24 +202,6 @@ namespace Microsoft.AspNet.Identity
return identity;
}
public virtual async Task<bool> SendTwoFactorCodeAsync(string provider)
{
var twoFactorInfo = await RetrieveTwoFactorInfoAsync();
if (twoFactorInfo == null || twoFactorInfo.UserId == null)
{
return false;
}
var user = await UserManager.FindByIdAsync(twoFactorInfo.UserId);
if (user == null)
{
return false;
}
var token = await UserManager.GenerateTwoFactorTokenAsync(user, provider);
await UserManager.NotifyTwoFactorTokenAsync(user, provider, token);
return await LogResultAsync(true, user);
}
public virtual async Task<bool> IsTwoFactorClientRememberedAsync(TUser user)
{
var userId = await UserManager.GetUserIdAsync(user);

View File

@ -15,18 +15,6 @@ namespace Microsoft.AspNet.Identity
{
public abstract string Name { get; }
/// <summary>
/// This token provider does not notify the user by default
/// </summary>
/// <param name="token"></param>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <returns></returns>
public virtual Task NotifyAsync(string token, UserManager<TUser> manager, TUser user)
{
return Task.FromResult(0);
}
/// <summary>
/// Generate a token for the user using their security stamp
/// </summary>

View File

@ -24,8 +24,6 @@ namespace Microsoft.AspNet.Identity
{
private readonly Dictionary<string, IUserTokenProvider<TUser>> _tokenProviders =
new Dictionary<string, IUserTokenProvider<TUser>>();
private readonly Dictionary<string, IIdentityMessageProvider> _msgProviders =
new Dictionary<string, IIdentityMessageProvider>();
private TimeSpan _defaultLockout = TimeSpan.Zero;
private bool _disposed;
@ -42,7 +40,6 @@ namespace Microsoft.AspNet.Identity
/// <param name="keyNormalizer"></param>
/// <param name="errors"></param>
/// <param name="tokenProviders"></param>
/// <param name="msgProviders"></param>
/// <param name="loggerFactory"></param>
public UserManager(IUserStore<TUser> store,
IOptions<IdentityOptions> optionsAccessor,
@ -52,7 +49,6 @@ namespace Microsoft.AspNet.Identity
ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors,
IEnumerable<IUserTokenProvider<TUser>> tokenProviders,
IEnumerable<IIdentityMessageProvider> msgProviders,
ILogger<UserManager<TUser>> logger,
IHttpContextAccessor contextAccessor)
{
@ -91,13 +87,6 @@ namespace Microsoft.AspNet.Identity
RegisterTokenProvider(tokenProvider);
}
}
if (msgProviders != null)
{
foreach (var msgProvider in msgProviders)
{
RegisterMessageProvider(msgProvider);
}
}
}
/// <summary>
@ -1527,20 +1516,6 @@ namespace Microsoft.AspNet.Identity
_tokenProviders[provider.Name] = provider;
}
/// <summary>
/// Register a user message provider
/// </summary>
/// <param name="provider"></param>
public virtual void RegisterMessageProvider(IIdentityMessageProvider provider)
{
ThrowIfDisposed();
if (provider == null)
{
throw new ArgumentNullException("provider");
}
_msgProviders[provider.Name] = provider;
}
/// <summary>
/// Returns a list of valid two factor providers for a user
/// </summary>
@ -1619,33 +1594,6 @@ namespace Microsoft.AspNet.Identity
return token;
}
/// <summary>
/// Notify a user with a token from a specific user factor provider
/// </summary>
/// <param name="user"></param>
/// <param name="tokenProvider"></param>
/// <param name="token"></param>
/// <returns></returns>
public virtual async Task<IdentityResult> NotifyTwoFactorTokenAsync(TUser user, string tokenProvider, string token)
{
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
if (tokenProvider == null)
{
throw new ArgumentNullException(nameof(tokenProvider));
}
if (!_tokenProviders.ContainsKey(tokenProvider))
{
throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture,
Resources.NoTokenProvider, tokenProvider));
}
await _tokenProviders[tokenProvider].NotifyAsync(token, this, user);
return await LogResultAsync(IdentityResult.Success, user);
}
// IUserFactorStore methods
internal IUserTwoFactorStore<TUser> GetUserTwoFactorStore()
{
@ -1692,30 +1640,6 @@ namespace Microsoft.AspNet.Identity
return await LogResultAsync(await UpdateUserAsync(user), user);
}
// Messaging methods
/// <summary>
/// Send a message to the user using the specified provider
/// </summary>
/// <param name="messageProvider"></param>
/// <param name="message"></param>
/// <returns></returns>
public virtual async Task<IdentityResult> SendMessageAsync(string messageProvider, IdentityMessage message)
{
ThrowIfDisposed();
if (message == null)
{
throw new ArgumentNullException(nameof(message));
}
if (!_msgProviders.ContainsKey(messageProvider))
{
throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture,
Resources.NoMessageProvider, messageProvider));
}
await _msgProviders[messageProvider].SendAsync(message, CancellationToken);
return IdentityResult.Success;
}
// IUserLockoutStore methods
internal IUserLockoutStore<TUser> GetUserLockoutStore()
{

View File

@ -234,7 +234,7 @@ namespace Microsoft.AspNet.Identity.Test
private class MyUserManager : UserManager<TestUser>
{
public MyUserManager(IUserStore<TestUser> store) : base(store, null, null, null, null, null, null, null, null, null, null) { }
public MyUserManager(IUserStore<TestUser> store) : base(store, null, null, null, null, null, null, null, null, null) { }
}
private class MyRoleManager : RoleManager<TestRole>

View File

@ -631,7 +631,7 @@ namespace Microsoft.AspNet.Identity.Test
public async Task ManagerPublicNullChecks()
{
Assert.Throws<ArgumentNullException>("store",
() => new UserManager<TestUser>(null, null, null, null, null, null, null, null, null, null, null));
() => new UserManager<TestUser>(null, null, null, null, null, null, null, null, null, null));
var manager = MockHelpers.TestUserManager(new NotImplementedStore());
@ -736,8 +736,6 @@ namespace Microsoft.AspNet.Identity.Test
async () => await manager.GenerateTwoFactorTokenAsync(null, null));
await Assert.ThrowsAsync<ArgumentNullException>("user",
async () => await manager.VerifyTwoFactorTokenAsync(null, null, null));
await Assert.ThrowsAsync<ArgumentNullException>("user",
async () => await manager.NotifyTwoFactorTokenAsync(null, null, null));
await Assert.ThrowsAsync<ArgumentNullException>("user",
async () => await manager.GetValidTwoFactorProvidersAsync(null));
await Assert.ThrowsAsync<ArgumentNullException>("user",
@ -797,7 +795,6 @@ namespace Microsoft.AspNet.Identity.Test
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GenerateEmailConfirmationTokenAsync(null));
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.IsEmailConfirmedAsync(null));
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.ConfirmEmailAsync(null, null));
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.SendMessageAsync(null, null));
}
private class BadPasswordValidator<TUser> : IPasswordValidator<TUser> where TUser : class

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Identity.Test
public static Mock<UserManager<TUser>> MockUserManager<TUser>() where TUser : class
{
var store = new Mock<IUserStore<TUser>>();
var mgr = new Mock<UserManager<TUser>>(store.Object, null, null, null, null, null, null, null, null, null, null);
var mgr = new Mock<UserManager<TUser>>(store.Object, null, null, null, null, null, null, null, null, null);
mgr.Object.UserValidators.Add(new UserValidator<TUser>());
mgr.Object.PasswordValidators.Add(new PasswordValidator<TUser>());
return mgr;
@ -63,7 +63,6 @@ namespace Microsoft.AspNet.Identity.Test
var userManager = new UserManager<TUser>(store, options.Object, new PasswordHasher<TUser>(),
userValidators, pwdValidators, new UpperInvariantLookupNormalizer(),
new IdentityErrorDescriber(), Enumerable.Empty<IUserTokenProvider<TUser>>(),
Enumerable.Empty<IIdentityMessageProvider>(),
new Logger<UserManager<TUser>>(new LoggerFactory()),
null);
validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>()))

View File

@ -1,23 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Identity.Test
{
public class TestMessageService<TUser> : IIdentityMessageProvider
{
public IdentityMessage Message { get; set; }
public string Name { get; set; } = "Test";
public Task SendAsync(IdentityMessage message, CancellationToken cancellationToken = default(CancellationToken))
{
Message = message;
return Task.FromResult(0);
}
}
}

View File

@ -1447,76 +1447,6 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Equal(stamp, user.SecurityStamp);
}
[Fact]
public async Task CanEmailTwoFactorToken()
{
var manager = CreateManager();
var messageService = new TestMessageService<TUser> { Name = "Email" };
manager.RegisterMessageProvider(messageService);
const string factorId = "Email"; // default
var user = new TUser() { UserName = "EmailCodeTest", Email = "foo@foo.com" };
user.EmailConfirmed = true;
const string password = "password";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, password));
var stamp = user.SecurityStamp;
Assert.NotNull(stamp);
var token = await manager.GenerateTwoFactorTokenAsync(user, factorId);
Assert.NotNull(token);
Assert.Null(messageService.Message);
IdentityResultAssert.IsSuccess(await manager.NotifyTwoFactorTokenAsync(user, factorId, token));
Assert.NotNull(messageService.Message);
Assert.Equal("Your security code is: " + token, messageService.Message.Body);
Assert.True(await manager.VerifyTwoFactorTokenAsync(user, factorId, token));
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "VerifyTwoFactorTokenAsync", user.Id.ToString());
}
[Fact]
public async Task NotifyWithUnknownProviderFails()
{
var manager = CreateManager();
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
await
ExceptionAssert.ThrowsAsync<NotSupportedException>(
async () => await manager.NotifyTwoFactorTokenAsync(user, "Bogus", "token"),
"No IUserTokenProvider named 'Bogus' is registered.");
}
[Fact]
public async Task EmailTokenFactorWithFormatTest()
{
// CONSIDER: do we want to support multiple email token options?
const string factorId = "Email"; // default
const string subject = "Custom subject";
const string body = "Your code is {0}!";
var services = new ServiceCollection();
services.Configure<EmailTokenProviderOptions>(o =>
{
o.Name = factorId;
o.Subject = subject;
o.BodyFormat = body;
});
var manager = CreateManager(null, services);
var messageService = new TestMessageService<TUser> { Name = "Email" };
manager.RegisterMessageProvider(messageService);
var user = CreateTestUser();
user.Email = user.UserName + "@foo.com";
const string password = "password";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, password));
var stamp = user.SecurityStamp;
Assert.NotNull(stamp);
var token = await manager.GenerateTwoFactorTokenAsync(user, factorId);
Assert.NotNull(token);
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "GenerateTwoFactorTokenAsync", user.Id.ToString());
Assert.Null(messageService.Message);
IdentityResultAssert.IsSuccess(await manager.NotifyTwoFactorTokenAsync(user, factorId, token));
Assert.NotNull(messageService.Message);
Assert.Equal(subject, messageService.Message.Subject);
Assert.Equal(string.Format(body, token), messageService.Message.Body);
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "NotifyTwoFactorTokenAsync", user.Id.ToString());
Assert.True(await manager.VerifyTwoFactorTokenAsync(user, factorId, token));
}
[Fact]
public async Task EmailFactorFailsAfterSecurityStampChangeTest()
{
@ -1548,69 +1478,6 @@ namespace Microsoft.AspNet.Identity.Test
Assert.True(await manager.GetTwoFactorEnabledAsync(user));
}
[Fact]
public async Task CanSendMessage()
{
var manager = CreateManager();
var messageService = new TestMessageService<TUser>();
manager.RegisterMessageProvider(messageService);
var user = CreateTestUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
await manager.SendMessageAsync(messageService.Name, new IdentityMessage { Destination = "foo", Subject = "Hi", Body = "Body" });
Assert.NotNull(messageService.Message);
Assert.Equal("foo", messageService.Message.Destination);
Assert.Equal("Hi", messageService.Message.Subject);
Assert.Equal("Body", messageService.Message.Body);
}
[Fact]
public async Task CanSmsTwoFactorToken()
{
var manager = CreateManager();
var messageService = new TestMessageService<TUser> { Name = "SMS" };
manager.RegisterMessageProvider(messageService);
const string factorId = "Phone"; // default
var user = CreateTestUser();
user.PhoneNumber = "4251234567";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
var stamp = user.SecurityStamp;
Assert.NotNull(stamp);
var token = await manager.GenerateTwoFactorTokenAsync(user, factorId);
Assert.NotNull(token);
Assert.Null(messageService.Message);
IdentityResultAssert.IsSuccess(await manager.NotifyTwoFactorTokenAsync(user, factorId, token));
Assert.NotNull(messageService.Message);
Assert.Equal("Your security code is: " + token, messageService.Message.Body);
Assert.True(await manager.VerifyTwoFactorTokenAsync(user, factorId, token));
}
[Fact]
public async Task PhoneTokenFactorFormatTest()
{
const string factorId = "Phone"; // default
var services = new ServiceCollection();
services.Configure<PhoneNumberTokenProviderOptions>(o =>
{
o.Name = factorId;
o.MessageFormat = "Your code is: {0}";
});
var manager = CreateManager(null, services);
var messageService = new TestMessageService<TUser> { Name = "SMS" };
manager.RegisterMessageProvider(messageService);
var user = CreateTestUser();
user.PhoneNumber = "4251234567";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
var stamp = user.SecurityStamp;
Assert.NotNull(stamp);
var token = await manager.GenerateTwoFactorTokenAsync(user, factorId);
Assert.NotNull(token);
Assert.Null(messageService.Message);
IdentityResultAssert.IsSuccess(await manager.NotifyTwoFactorTokenAsync(user, factorId, token));
Assert.NotNull(messageService.Message);
Assert.Equal("Your code is: " + token, messageService.Message.Body);
Assert.True(await manager.VerifyTwoFactorTokenAsync(user, factorId, token));
}
[Fact]
public async Task GenerateTwoFactorWithUnknownFactorProviderWillThrow()
{