Add ChangeEmail APIs

This commit is contained in:
Hao Kung 2014-12-04 13:25:18 -08:00
parent 5658af6b61
commit 33d8645187
3 changed files with 118 additions and 1 deletions

View File

@ -29,6 +29,8 @@ namespace Microsoft.AspNet.Identity
public string PasswordResetTokenProvider { get; set; } = Resources.DefaultTokenProvider;
public string ChangeEmailTokenProvider { get; set; } = Resources.DefaultTokenProvider;
public static string ApplicationCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".Application";
public static string ExternalCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".External";
public static string TwoFactorUserIdCookieAuthenticationType { get; set; } = typeof(IdentityOptions).Namespace + ".TwoFactorUserId";

View File

@ -716,7 +716,7 @@ namespace Microsoft.AspNet.Identity
}
/// <summary>
/// GenerateAsync a new security stamp for a user, used for SignOutEverywhere functionality
/// Generate a new security stamp for a user, used for SignOutEverywhere functionality
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
@ -1337,6 +1337,52 @@ namespace Microsoft.AspNet.Identity
return await store.GetEmailConfirmedAsync(user, cancellationToken);
}
private static string GetChangeEmailPurpose(string newEmail)
{
return "ChangeEmail:" + newEmail;
}
/// <summary>
/// Generate a change email token for the user using the UserTokenProvider
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<string> GenerateChangeEmailTokenAsync(TUser user, string newEmail,
CancellationToken cancellationToken = default(CancellationToken))
{
ThrowIfDisposed();
return await GenerateUserTokenAsync(user, Options.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail), cancellationToken);
}
/// <summary>
/// Change a user's email using a change email token
/// </summary>
/// <param name="user"></param>
/// <param name="token"></param>
/// <param name="newPassword"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual async Task<IdentityResult> ChangeEmailAsync(TUser user, string newEmail, string token,
CancellationToken cancellationToken = default(CancellationToken))
{
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
// Make sure the token is valid and the stamp matches
if (!await VerifyUserTokenAsync(user, Options.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail), token, cancellationToken))
{
return IdentityResult.Failed(Resources.InvalidToken);
}
var store = GetEmailStore();
await store.SetEmailAsync(user, newEmail, cancellationToken);
await store.SetEmailConfirmedAsync(user, true, cancellationToken);
await UpdateSecurityStampInternal(user, cancellationToken);
return await UpdateAsync(user, cancellationToken);
}
// IUserPhoneNumberStore methods
internal IUserPhoneNumberStore<TUser> GetPhoneNumberStore()
{

View File

@ -1224,6 +1224,23 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Equal(stamp, user.SecurityStamp);
}
[Fact]
public async Task ChangePhoneNumberFailsWithWrongPhoneNumber()
{
var manager = CreateManager();
var user = CreateTestUser();
user.PhoneNumber = "123-456-7890";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
Assert.False(await manager.IsPhoneNumberConfirmedAsync(user));
var stamp = await manager.GetSecurityStampAsync(user);
var token1 = await manager.GenerateChangePhoneNumberTokenAsync(user, "111-111-1111");
IdentityResultAssert.IsFailure(await manager.ChangePhoneNumberAsync(user, "bogus", token1),
"Invalid token.");
Assert.False(await manager.IsPhoneNumberConfirmedAsync(user));
Assert.Equal(await manager.GetPhoneNumberAsync(user), "123-456-7890");
Assert.Equal(stamp, user.SecurityStamp);
}
[Fact]
public async Task CanVerifyPhoneNumber()
{
@ -1241,6 +1258,58 @@ namespace Microsoft.AspNet.Identity.Test
Assert.False(await manager.VerifyChangePhoneNumberTokenAsync(user, token1, num2));
}
[Fact]
public async Task CanChangeEmail()
{
var manager = CreateManager();
var user = CreateTestUser();
user.Email = user.UserName + "@diddly.bop";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
Assert.False(await manager.IsEmailConfirmedAsync(user));
var stamp = await manager.GetSecurityStampAsync(user);
string newEmail = user.UserName + "@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, user.SecurityStamp);
}
[Fact]
public async Task ChangeEmailFailsWithWrongToken()
{
var manager = CreateManager();
var user = CreateTestUser();
user.Email = user.UserName + "@diddly.bop";
string oldEmail = user.Email;
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
Assert.False(await manager.IsEmailConfirmedAsync(user));
var stamp = await manager.GetSecurityStampAsync(user);
IdentityResultAssert.IsFailure(await manager.ChangeEmailAsync(user, "whatevah@foo.barf", "bogus"),
"Invalid token.");
Assert.False(await manager.IsEmailConfirmedAsync(user));
Assert.Equal(await manager.GetEmailAsync(user), oldEmail);
Assert.Equal(stamp, user.SecurityStamp);
}
[Fact]
public async Task ChangeEmailFailsWithEmail()
{
var manager = CreateManager();
var user = CreateTestUser();
user.Email = user.UserName + "@diddly.bop";
string oldEmail = user.Email;
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
Assert.False(await manager.IsEmailConfirmedAsync(user));
var stamp = await manager.GetSecurityStampAsync(user);
var token1 = await manager.GenerateChangeEmailTokenAsync(user, "forgot@alrea.dy");
IdentityResultAssert.IsFailure(await manager.ChangeEmailAsync(user, "oops@foo.barf", token1),
"Invalid token.");
Assert.False(await manager.IsEmailConfirmedAsync(user));
Assert.Equal(await manager.GetEmailAsync(user), oldEmail);
Assert.Equal(stamp, user.SecurityStamp);
}
[Fact]
public async Task CanEmailTwoFactorToken()
{