diff --git a/Identity.sln b/Identity.sln index 413d7e994a..c64740edda 100644 --- a/Identity.sln +++ b/Identity.sln @@ -27,6 +27,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Identity.T EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Aspnet.Identity.InMemory.Test.net45", "test\Microsoft.Aspnet.Identity.InMemory.Test\Microsoft.Aspnet.Identity.InMemory.Test.net45.csproj", "{9102E676-B509-4A78-AD66-A479C50FD1C3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Identity.Security.k10", "src\Microsoft.AspNet.Identity.Security\Microsoft.AspNet.Identity.Security.k10.csproj", "{DE98C383-A3D7-47EC-AE37-C7F707F16486}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Identity.Security.net45", "src\Microsoft.AspNet.Identity.Security\Microsoft.AspNet.Identity.Security.net45.csproj", "{BD765B85-9839-4901-B231-E49465596A75}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Identity.Security.Test.net45", "test\Microsoft.AspNet.Identity.Security.Test\Microsoft.AspNet.Identity.Security.Test.net45.csproj", "{30A2C4BB-86AB-4971-BC63-4761E8CE7D0F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,6 +71,18 @@ Global {9102E676-B509-4A78-AD66-A479C50FD1C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {9102E676-B509-4A78-AD66-A479C50FD1C3}.Release|Any CPU.ActiveCfg = Release|Any CPU {9102E676-B509-4A78-AD66-A479C50FD1C3}.Release|Any CPU.Build.0 = Release|Any CPU + {DE98C383-A3D7-47EC-AE37-C7F707F16486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE98C383-A3D7-47EC-AE37-C7F707F16486}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE98C383-A3D7-47EC-AE37-C7F707F16486}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE98C383-A3D7-47EC-AE37-C7F707F16486}.Release|Any CPU.Build.0 = Release|Any CPU + {BD765B85-9839-4901-B231-E49465596A75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD765B85-9839-4901-B231-E49465596A75}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD765B85-9839-4901-B231-E49465596A75}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD765B85-9839-4901-B231-E49465596A75}.Release|Any CPU.Build.0 = Release|Any CPU + {30A2C4BB-86AB-4971-BC63-4761E8CE7D0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30A2C4BB-86AB-4971-BC63-4761E8CE7D0F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30A2C4BB-86AB-4971-BC63-4761E8CE7D0F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30A2C4BB-86AB-4971-BC63-4761E8CE7D0F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -74,11 +92,14 @@ Global {77CEDA6C-A833-455D-8357-649BFD944724} = {0F647068-6602-4E24-B1DC-8ED91481A50A} {E00E23B0-79B8-41E1-9998-57FECA1F2535} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E} {9102E676-B509-4A78-AD66-A479C50FD1C3} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E} + {30A2C4BB-86AB-4971-BC63-4761E8CE7D0F} = {52D59F18-62D2-4D17-8CF2-BE192445AF8E} {B72401D7-47F6-4A98-89D5-CCBFEFC5B2B8} = {F6B0C0E9-C346-49D0-B583-95B6CE04BB1B} {E52361C9-1F0B-4229-86A0-E5C7C12A5429} = {F6B0C0E9-C346-49D0-B583-95B6CE04BB1B} {054B3FFA-7196-466F-9A8A-593FFE037A69} = {F6B0C0E9-C346-49D0-B583-95B6CE04BB1B} + {BD765B85-9839-4901-B231-E49465596A75} = {F6B0C0E9-C346-49D0-B583-95B6CE04BB1B} {6211450F-FFB8-431F-84E2-9A7620875260} = {77CEDA6C-A833-455D-8357-649BFD944724} {D32483A4-B617-480C-81E6-49CD596B9A34} = {77CEDA6C-A833-455D-8357-649BFD944724} {D2E7A146-C39F-4302-8EA3-BFA8C1082939} = {77CEDA6C-A833-455D-8357-649BFD944724} + {DE98C383-A3D7-47EC-AE37-C7F707F16486} = {77CEDA6C-A833-455D-8357-649BFD944724} EndGlobalSection EndGlobal diff --git a/src/Microsoft.AspNet.Identity.InMemory/InMemoryRoleStore.cs b/src/Microsoft.AspNet.Identity.InMemory/InMemoryRoleStore.cs index 93cb6e53b3..ac8c06d279 100644 --- a/src/Microsoft.AspNet.Identity.InMemory/InMemoryRoleStore.cs +++ b/src/Microsoft.AspNet.Identity.InMemory/InMemoryRoleStore.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity.InMemory @@ -9,13 +10,13 @@ namespace Microsoft.AspNet.Identity.InMemory { private readonly Dictionary _roles = new Dictionary(); - public Task Create(InMemoryRole role) + public Task Create(InMemoryRole role, CancellationToken cancellationToken = default(CancellationToken)) { _roles[role.Id] = role; return Task.FromResult(0); } - public Task Delete(InMemoryRole role) + public Task Delete(InMemoryRole role, CancellationToken cancellationToken = default(CancellationToken)) { if (role == null || !_roles.ContainsKey(role.Id)) { @@ -25,13 +26,13 @@ namespace Microsoft.AspNet.Identity.InMemory return Task.FromResult(0); } - public Task Update(InMemoryRole role) + public Task Update(InMemoryRole role, CancellationToken cancellationToken = default(CancellationToken)) { _roles[role.Id] = role; return Task.FromResult(0); } - public Task FindById(string roleId) + public Task FindById(string roleId, CancellationToken cancellationToken = default(CancellationToken)) { if (_roles.ContainsKey(roleId)) { @@ -40,7 +41,7 @@ namespace Microsoft.AspNet.Identity.InMemory return Task.FromResult(null); } - public Task FindByName(string roleName) + public Task FindByName(string roleName, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult( diff --git a/src/Microsoft.AspNet.Identity.InMemory/InMemoryUserStore.cs b/src/Microsoft.AspNet.Identity.InMemory/InMemoryUserStore.cs index 456d12041c..b1c0782385 100644 --- a/src/Microsoft.AspNet.Identity.InMemory/InMemoryUserStore.cs +++ b/src/Microsoft.AspNet.Identity.InMemory/InMemoryUserStore.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity.InMemory @@ -29,99 +30,99 @@ namespace Microsoft.AspNet.Identity.InMemory get { return _users.Values.AsQueryable(); } } - public Task> GetClaims(TUser user) + public Task> GetClaims(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.Claims); } - public Task AddClaim(TUser user, Claim claim) + public Task AddClaim(TUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) { user.Claims.Add(claim); return Task.FromResult(0); } - public Task RemoveClaim(TUser user, Claim claim) + public Task RemoveClaim(TUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) { user.Claims.Remove(claim); return Task.FromResult(0); } - public Task SetEmail(TUser user, string email) + public Task SetEmail(TUser user, string email, CancellationToken cancellationToken = default(CancellationToken)) { user.Email = email; return Task.FromResult(0); } - public Task GetEmail(TUser user) + public Task GetEmail(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.Email); } - public Task GetEmailConfirmed(TUser user) + public Task GetEmailConfirmed(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.EmailConfirmed); } - public Task SetEmailConfirmed(TUser user, bool confirmed) + public Task SetEmailConfirmed(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)) { user.EmailConfirmed = confirmed; return Task.FromResult(0); } - public Task FindByEmail(string email) + public Task FindByEmail(string email, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult( Users.FirstOrDefault(u => String.Equals(u.Email, email, StringComparison.OrdinalIgnoreCase))); } - public Task GetLockoutEndDate(TUser user) + public Task GetLockoutEndDate(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.LockoutEnd); } - public Task SetLockoutEndDate(TUser user, DateTimeOffset lockoutEnd) + public Task SetLockoutEndDate(TUser user, DateTimeOffset lockoutEnd, CancellationToken cancellationToken = default(CancellationToken)) { user.LockoutEnd = lockoutEnd; return Task.FromResult(0); } - public Task IncrementAccessFailedCount(TUser user) + public Task IncrementAccessFailedCount(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { user.AccessFailedCount++; return Task.FromResult(user.AccessFailedCount); } - public Task ResetAccessFailedCount(TUser user) + public Task ResetAccessFailedCount(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { user.AccessFailedCount = 0; return Task.FromResult(0); } - public Task GetAccessFailedCount(TUser user) + public Task GetAccessFailedCount(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.AccessFailedCount); } - public Task GetLockoutEnabled(TUser user) + public Task GetLockoutEnabled(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.LockoutEnabled); } - public Task SetLockoutEnabled(TUser user, bool enabled) + public Task SetLockoutEnabled(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) { user.LockoutEnabled = enabled; return Task.FromResult(0); } - public Task AddLogin(TUser user, UserLoginInfo login) + public Task AddLogin(TUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { user.Logins.Add(login); _logins[login] = user; return Task.FromResult(0); } - public Task RemoveLogin(TUser user, UserLoginInfo login) + public Task RemoveLogin(TUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { var logs = user.Logins.Where(l => l.ProviderKey == login.ProviderKey && l.LoginProvider == login.LoginProvider) @@ -134,12 +135,12 @@ namespace Microsoft.AspNet.Identity.InMemory return Task.FromResult(0); } - public Task> GetLogins(TUser user) + public Task> GetLogins(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.Logins); } - public Task Find(UserLoginInfo login) + public Task Find(UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { if (_logins.ContainsKey(login)) { @@ -148,19 +149,19 @@ namespace Microsoft.AspNet.Identity.InMemory return Task.FromResult(null); } - public Task Create(TUser user) + public Task Create(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { _users[user.Id] = user; return Task.FromResult(0); } - public Task Update(TUser user) + public Task Update(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { _users[user.Id] = user; return Task.FromResult(0); } - public Task FindById(string userId) + public Task FindById(string userId, CancellationToken cancellationToken = default(CancellationToken)) { if (_users.ContainsKey(userId)) { @@ -173,14 +174,14 @@ namespace Microsoft.AspNet.Identity.InMemory { } - public Task FindByName(string userName) + public Task FindByName(string userName, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult( Users.FirstOrDefault(u => String.Equals(u.UserName, userName, StringComparison.OrdinalIgnoreCase))); } - public Task Delete(TUser user) + public Task Delete(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { if (user == null || !_users.ContainsKey(user.Id)) { @@ -190,84 +191,84 @@ namespace Microsoft.AspNet.Identity.InMemory return Task.FromResult(0); } - public Task SetPasswordHash(TUser user, string passwordHash) + public Task SetPasswordHash(TUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken)) { user.PasswordHash = passwordHash; return Task.FromResult(0); } - public Task GetPasswordHash(TUser user) + public Task GetPasswordHash(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.PasswordHash); } - public Task HasPassword(TUser user) + public Task HasPassword(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.PasswordHash != null); } - public Task SetPhoneNumber(TUser user, string phoneNumber) + public Task SetPhoneNumber(TUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken)) { user.PhoneNumber = phoneNumber; return Task.FromResult(0); } - public Task GetPhoneNumber(TUser user) + public Task GetPhoneNumber(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.PhoneNumber); } - public Task GetPhoneNumberConfirmed(TUser user) + public Task GetPhoneNumberConfirmed(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.PhoneNumberConfirmed); } - public Task SetPhoneNumberConfirmed(TUser user, bool confirmed) + public Task SetPhoneNumberConfirmed(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)) { user.PhoneNumberConfirmed = confirmed; return Task.FromResult(0); } - public Task AddToRole(TUser user, string role) + public Task AddToRole(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken)) { user.Roles.Add(role); return Task.FromResult(0); } - public Task RemoveFromRole(TUser user, string role) + public Task RemoveFromRole(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken)) { user.Roles.Remove(role); return Task.FromResult(0); } - public Task> GetRoles(TUser user) + public Task> GetRoles(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.Roles); } - public Task IsInRole(TUser user, string role) + public Task IsInRole(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.Roles.Contains(role)); } - public Task SetSecurityStamp(TUser user, string stamp) + public Task SetSecurityStamp(TUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken)) { user.SecurityStamp = stamp; return Task.FromResult(0); } - public Task GetSecurityStamp(TUser user) + public Task GetSecurityStamp(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.SecurityStamp); } - public Task SetTwoFactorEnabled(TUser user, bool enabled) + public Task SetTwoFactorEnabled(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) { user.TwoFactorEnabled = enabled; return Task.FromResult(0); } - public Task GetTwoFactorEnabled(TUser user) + public Task GetTwoFactorEnabled(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(user.TwoFactorEnabled); } diff --git a/src/Microsoft.AspNet.Identity.Security/SignInManager.cs b/src/Microsoft.AspNet.Identity.Security/SignInManager.cs new file mode 100644 index 0000000000..721cb98ce1 --- /dev/null +++ b/src/Microsoft.AspNet.Identity.Security/SignInManager.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNet.Abstractions; +using Microsoft.AspNet.Abstractions.Security; + +namespace Microsoft.AspNet.Identity.Security +{ + public class SignInManager + where TUser : class, IUser + where TKey : IEquatable + { + private string _authType; + public string AuthenticationType + { + get { return _authType ?? "Microsoft.AspNet.Identity"; } + set { _authType = value; } + } + + public UserManager UserManager { get; set; } + public HttpContext Context { get; set; } + + + public virtual async Task CreateUserIdentity(TUser user) + { + if (UserManager == null) + { + return null; + } + return await UserManager.CreateIdentity(user, AuthenticationType); + } + + public virtual async Task SignIn(TUser user, bool isPersistent, bool rememberBrowser) + { + if (Context == null) + { + return; + } + + // TODO: all the two factor logic/external/rememberBrowser + var userIdentity = await CreateUserIdentity(user); + Context.Response.SignIn(userIdentity, new AuthenticationProperties { IsPersistent = isPersistent }); + } + + //public virtual async Task SendTwoFactorCode(string provider) + //{ + // var userId = await GetVerifiedUserId(); + // if (userId == null) + // { + // return false; + // } + + // var token = await UserManager.GenerateTwoFactorToken(userId, provider); + // // See IdentityConfig.cs to plug in Email/SMS services to actually send the code + // await UserManager.NotifyTwoFactorToken(userId, provider, token); + // return true; + //} + + //public Task GetVerifiedUserId() + //{ + // //var result = await AuthenticationManager.Authenticate(DefaultAuthenticationTypes.TwoFactorCookie); + // //if (result != null && result.Identity != null && !String.IsNullOrEmpty(result.Identity.GetUserId())) + // //{ + // // return result.Identity.GetUserId(); + // //} + // return Task.FromResult(default(TKey)); + //} + + //public async Task HasBeenVerified() + //{ + // return await GetVerifiedUserId() != null; + //} + + //public virtual async Task TwoFactorSignIn(string provider, string code, bool isPersistent, bool rememberBrowser) + //{ + // var userId = await GetVerifiedUserId(); + // if (userId == null) + // { + // return SignInStatus.Failure; + // } + // var user = await UserManager.FindById(userId); + // if (user == null) + // { + // return SignInStatus.Failure; + // } + // if (await UserManager.IsLockedOut(user.Id)) + // { + // return SignInStatus.LockedOut; + // } + // if (await UserManager.VerifyTwoFactorToken(user.Id, provider, code)) + // { + // // When token is verified correctly, clear the access failed count used for lockout + // await UserManager.ResetAccessFailedCount(user.Id); + // await SignIn(user, isPersistent, rememberBrowser); + // return SignInStatus.Success; + // } + // // If the token is incorrect, record the failure which also may cause the user to be locked out + // await UserManager.AccessFailed(user.Id); + // return SignInStatus.Failure; + //} + + //public async Task ExternalSignIn(ExternalLoginInfo loginInfo, bool isPersistent) + //{ + // var user = await UserManager.Find(loginInfo.Login); + // if (user == null) + // { + // return SignInStatus.Failure; + // } + // if (await UserManager.IsLockedOut(user.Id)) + // { + // return SignInStatus.LockedOut; + // } + // return await SignInOrTwoFactor(user, isPersistent); + //} + + //private async Task SignInOrTwoFactor(TUser user, bool isPersistent) + //{ + // if (await UserManager.GetTwoFactorEnabled(user.Id)) + // //&& !await AuthenticationManager.TwoFactorBrowserRemembered(user.Id)) + // { + // //var identity = new ClaimsIdentity(DefaultAuthenticationTypes.TwoFactorCookie); + // //identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id)); + // //AuthenticationManager.SignIn(identity); + // return SignInStatus.RequiresTwoFactorAuthentication; + // } + // await SignIn(user, isPersistent, false); + // return SignInStatus.Success; + //} + + public virtual async Task PasswordSignIn(string userName, string password, bool isPersistent, bool shouldLockout) + { + if (UserManager == null) + { + return SignInStatus.Failure; + } + var user = await UserManager.FindByName(userName); + if (user == null) + { + return SignInStatus.Failure; + } + if (await UserManager.IsLockedOut(user.Id)) + { + return SignInStatus.LockedOut; + } + if (await UserManager.CheckPassword(user, password)) + { + await SignIn(user, isPersistent, false); + return SignInStatus.Success; + //TODO: return await SignInOrTwoFactor(user, isPersistent); + } + if (shouldLockout) + { + // If lockout is requested, increment access failed count which might lock out the user + await UserManager.AccessFailed(user.Id); + if (await UserManager.IsLockedOut(user.Id)) + { + return SignInStatus.LockedOut; + } + } + return SignInStatus.Failure; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity.Security/SignInStatus.cs b/src/Microsoft.AspNet.Identity.Security/SignInStatus.cs new file mode 100644 index 0000000000..b92fc3c31c --- /dev/null +++ b/src/Microsoft.AspNet.Identity.Security/SignInStatus.cs @@ -0,0 +1,11 @@ +namespace Microsoft.AspNet.Identity.Security +{ + public enum SignInStatus + { + Success, + LockedOut, + RequiresTwoFactorAuthentication, + Failure + } + +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity.Security/project.json b/src/Microsoft.AspNet.Identity.Security/project.json new file mode 100644 index 0000000000..89ff45ece3 --- /dev/null +++ b/src/Microsoft.AspNet.Identity.Security/project.json @@ -0,0 +1,31 @@ +{ + "version": "0.1-alpha-*", + "dependencies": { + "Microsoft.AspNet.DependencyInjection" : "0.1-alpha-*", + "System.Security.Claims" : "0.1-alpha-*", + "Microsoft.AspNet.Abstractions" : "0.1-alpha-*", + "Microsoft.AspNet.Identity" : "0.1-alpha-*", + "Microsoft.AspNet.Security.DataProtection" : "0.1-alpha-*" + }, + "configurations": { + "net45": {}, + "k10": { + "dependencies": { + "System.Collections": "4.0.0.0", + "System.ComponentModel": "4.0.0.0", + "System.Diagnostics.Debug": "4.0.10.0", + "System.Diagnostics.Tools": "4.0.0.0", + "System.Globalization": "4.0.10.0", + "System.Linq": "4.0.0.0", + "System.Linq.Expressions": "4.0.0.0", + "System.Reflection": "4.0.10.0", + "System.Resources.ResourceManager": "4.0.0.0", + "System.Runtime": "4.0.20.0", + "System.Runtime.Extensions": "4.0.10.0", + "System.Security.Principal": "4.0.0.0", + "System.Text.Encoding": "4.0.20.0", + "System.Threading.Tasks": "4.0.10.0" + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/ClaimsIdentityFactory.cs b/src/Microsoft.AspNet.Identity/ClaimsIdentityFactory.cs index 5bf9164a1c..fe2dd0a4ad 100644 --- a/src/Microsoft.AspNet.Identity/ClaimsIdentityFactory.cs +++ b/src/Microsoft.AspNet.Identity/ClaimsIdentityFactory.cs @@ -1,5 +1,7 @@ using System; +using System.Globalization; using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -57,7 +59,7 @@ namespace Microsoft.AspNet.Identity /// /// public virtual async Task Create(UserManager manager, TUser user, - string authenticationType) + string authenticationType, CancellationToken cancellationToken = default(CancellationToken)) { if (manager == null) { @@ -68,15 +70,15 @@ namespace Microsoft.AspNet.Identity throw new ArgumentNullException("user"); } var id = new ClaimsIdentity(authenticationType, UserNameClaimType, RoleClaimType); - id.AddClaim(new Claim(UserIdClaimType, ConvertIdToString(user.Id), ClaimValueTypes.String)); + id.AddClaim(new Claim(UserIdClaimType, Convert.ToString(user.Id, CultureInfo.InvariantCulture), ClaimValueTypes.String)); id.AddClaim(new Claim(UserNameClaimType, user.UserName, ClaimValueTypes.String)); if (manager.SupportsUserSecurityStamp) { - id.AddClaim(new Claim(SecurityStampClaimType, await manager.GetSecurityStamp(user.Id))); + id.AddClaim(new Claim(SecurityStampClaimType, await manager.GetSecurityStamp(user.Id, cancellationToken))); } if (manager.SupportsUserRole) { - var roles = await manager.GetRoles(user.Id); + var roles = await manager.GetRoles(user.Id, cancellationToken); foreach (var roleName in roles) { id.AddClaim(new Claim(RoleClaimType, roleName, ClaimValueTypes.String)); @@ -84,23 +86,9 @@ namespace Microsoft.AspNet.Identity } if (manager.SupportsUserClaim) { - id.AddClaims(await manager.GetClaims(user.Id)); + id.AddClaims(await manager.GetClaims(user.Id, cancellationToken)); } return id; } - - /// - /// Convert the key to a string, by default just calls .ToString() - /// - /// - /// - public virtual string ConvertIdToString(TKey key) - { - if (key == null || key.Equals(default(TKey))) - { - return null; - } - return key.ToString(); - } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IClaimsIdentityFactory.cs b/src/Microsoft.AspNet.Identity/IClaimsIdentityFactory.cs index 57985e2258..1a029c9b59 100644 --- a/src/Microsoft.AspNet.Identity/IClaimsIdentityFactory.cs +++ b/src/Microsoft.AspNet.Identity/IClaimsIdentityFactory.cs @@ -1,5 +1,6 @@ using System; using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -19,7 +20,8 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task Create(UserManager manager, TUser user, string authenticationType); + Task Create(UserManager manager, TUser user, string authenticationType, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IIdentityMessageService.cs b/src/Microsoft.AspNet.Identity/IIdentityMessageService.cs index 43c89d2ec5..884ba15444 100644 --- a/src/Microsoft.AspNet.Identity/IIdentityMessageService.cs +++ b/src/Microsoft.AspNet.Identity/IIdentityMessageService.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.AspNet.Identity { @@ -11,7 +12,8 @@ namespace Microsoft.AspNet.Identity /// This method should send the message /// /// + /// /// - Task Send(IdentityMessage message); + Task Send(IdentityMessage message, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IPasswordValidator.cs b/src/Microsoft.AspNet.Identity/IPasswordValidator.cs index 4cf7720165..0b4cd3fa23 100644 --- a/src/Microsoft.AspNet.Identity/IPasswordValidator.cs +++ b/src/Microsoft.AspNet.Identity/IPasswordValidator.cs @@ -1,3 +1,4 @@ +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -11,6 +12,6 @@ namespace Microsoft.AspNet.Identity /// Validate the item /// /// - Task Validate(string password); + Task Validate(string password, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IRoleStore.cs b/src/Microsoft.AspNet.Identity/IRoleStore.cs index 8286b56b46..7205a9deff 100644 --- a/src/Microsoft.AspNet.Identity/IRoleStore.cs +++ b/src/Microsoft.AspNet.Identity/IRoleStore.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -14,35 +15,40 @@ namespace Microsoft.AspNet.Identity /// Insert a new role /// /// + /// /// - Task Create(TRole role); + Task Create(TRole role, CancellationToken cancellationToken = default(CancellationToken)); /// /// Update a role /// /// + /// /// - Task Update(TRole role); + Task Update(TRole role, CancellationToken cancellationToken = default(CancellationToken)); /// /// Delete a role /// /// + /// /// - Task Delete(TRole role); + Task Delete(TRole role, CancellationToken cancellationToken = default(CancellationToken)); /// /// Finds a role by id /// /// + /// /// - Task FindById(TKey roleId); + Task FindById(TKey roleId, CancellationToken cancellationToken = default(CancellationToken)); /// /// Find a role by name /// /// + /// /// - Task FindByName(string roleName); + Task FindByName(string roleName, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IRoleValidator.cs b/src/Microsoft.AspNet.Identity/IRoleValidator.cs index 2d72a2994d..b41c6f6305 100644 --- a/src/Microsoft.AspNet.Identity/IRoleValidator.cs +++ b/src/Microsoft.AspNet.Identity/IRoleValidator.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -17,7 +18,8 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task Validate(RoleManager manager, TRole role); + Task Validate(RoleManager manager, TRole role, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserClaimStore.cs b/src/Microsoft.AspNet.Identity/IUserClaimStore.cs index 165875c940..f2e50e2959 100644 --- a/src/Microsoft.AspNet.Identity/IUserClaimStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserClaimStore.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -15,23 +16,26 @@ namespace Microsoft.AspNet.Identity /// Returns the claims for the user with the issuer set /// /// + /// /// - Task> GetClaims(TUser user); + Task> GetClaims(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Add a new user claim /// /// /// + /// /// - Task AddClaim(TUser user, Claim claim); + Task AddClaim(TUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken)); /// /// Remove a user claim /// /// /// + /// /// - Task RemoveClaim(TUser user, Claim claim); + Task RemoveClaim(TUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserEmailStore.cs b/src/Microsoft.AspNet.Identity/IUserEmailStore.cs index 8a631f79cb..bd18f09d25 100644 --- a/src/Microsoft.AspNet.Identity/IUserEmailStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserEmailStore.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.AspNet.Identity { @@ -14,36 +15,41 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task SetEmail(TUser user, string email); + Task SetEmail(TUser user, string email, CancellationToken cancellationToken = default(CancellationToken)); /// /// Get the user email /// /// + /// /// - Task GetEmail(TUser user); + Task GetEmail(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns true if the user email is confirmed /// /// + /// /// - Task GetEmailConfirmed(TUser user); + Task GetEmailConfirmed(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Sets whether the user email is confirmed /// /// /// + /// /// - Task SetEmailConfirmed(TUser user, bool confirmed); + Task SetEmailConfirmed(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns the user associated with this email /// /// + /// /// - Task FindByEmail(string email); + Task FindByEmail(string email, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserLockoutStore.cs b/src/Microsoft.AspNet.Identity/IUserLockoutStore.cs index 813fcc12c0..b40e6f07dc 100644 --- a/src/Microsoft.AspNet.Identity/IUserLockoutStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserLockoutStore.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -15,52 +16,59 @@ namespace Microsoft.AspNet.Identity /// not locked out. /// /// + /// /// - Task GetLockoutEndDate(TUser user); + Task GetLockoutEndDate(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Locks a user out until the specified end date (set to a past date, to unlock a user) /// /// /// + /// /// - Task SetLockoutEndDate(TUser user, DateTimeOffset lockoutEnd); + Task SetLockoutEndDate(TUser user, DateTimeOffset lockoutEnd, CancellationToken cancellationToken = default(CancellationToken)); /// /// Used to record when an attempt to access the user has failed /// /// + /// /// - Task IncrementAccessFailedCount(TUser user); + Task IncrementAccessFailedCount(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Used to reset the account access count, typically after the account is successfully accessed /// /// + /// /// - Task ResetAccessFailedCount(TUser user); + Task ResetAccessFailedCount(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns the current number of failed access attempts. This number usually will be reset whenever the password is /// verified or the account is locked out. /// /// + /// /// - Task GetAccessFailedCount(TUser user); + Task GetAccessFailedCount(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns whether the user can be locked out. /// /// + /// /// - Task GetLockoutEnabled(TUser user); + Task GetLockoutEnabled(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Sets whether the user can be locked out. /// /// /// + /// /// - Task SetLockoutEnabled(TUser user, bool enabled); + Task SetLockoutEnabled(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserLoginStore.cs b/src/Microsoft.AspNet.Identity/IUserLoginStore.cs index 1bb4c1b0f8..a5f19f5b80 100644 --- a/src/Microsoft.AspNet.Identity/IUserLoginStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserLoginStore.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -15,28 +16,33 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task AddLogin(TUser user, UserLoginInfo login); + Task AddLogin(TUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)); /// /// Removes the user login with the specified combination if it exists, returns true if found and removed /// /// /// + /// /// - Task RemoveLogin(TUser user, UserLoginInfo login); + Task RemoveLogin(TUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns the linked accounts for this user /// /// + /// /// - Task> GetLogins(TUser user); + Task> GetLogins(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns the user associated with this login /// + /// + /// /// - Task Find(UserLoginInfo login); + Task Find(UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserPasswordStore.cs b/src/Microsoft.AspNet.Identity/IUserPasswordStore.cs index ce4bccb8cc..2c4c343815 100644 --- a/src/Microsoft.AspNet.Identity/IUserPasswordStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserPasswordStore.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.AspNet.Identity { @@ -14,21 +15,24 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task SetPasswordHash(TUser user, string passwordHash); + Task SetPasswordHash(TUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken)); /// /// Get the user password hash /// /// + /// /// - Task GetPasswordHash(TUser user); + Task GetPasswordHash(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns true if a user has a password set /// /// + /// /// - Task HasPassword(TUser user); + Task HasPassword(TUser user, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserPhoneNumberStore.cs b/src/Microsoft.AspNet.Identity/IUserPhoneNumberStore.cs index c46e681cde..f342f00be5 100644 --- a/src/Microsoft.AspNet.Identity/IUserPhoneNumberStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserPhoneNumberStore.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.AspNet.Identity { @@ -14,29 +15,33 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task SetPhoneNumber(TUser user, string phoneNumber); + Task SetPhoneNumber(TUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken)); /// /// Get the user phoneNumber /// /// + /// /// - Task GetPhoneNumber(TUser user); + Task GetPhoneNumber(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns true if the user phone number is confirmed /// /// + /// /// - Task GetPhoneNumberConfirmed(TUser user); + Task GetPhoneNumberConfirmed(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Sets whether the user phone number is confirmed /// /// /// + /// /// - Task SetPhoneNumberConfirmed(TUser user, bool confirmed); + Task SetPhoneNumberConfirmed(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserRoleStore.cs b/src/Microsoft.AspNet.Identity/IUserRoleStore.cs index f2a356f121..180c74c287 100644 --- a/src/Microsoft.AspNet.Identity/IUserRoleStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserRoleStore.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -15,30 +16,34 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task AddToRole(TUser user, string roleName); + Task AddToRole(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken)); /// /// Removes the role for the user /// /// /// + /// /// - Task RemoveFromRole(TUser user, string roleName); + Task RemoveFromRole(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns the roles for this user /// /// + /// /// - Task> GetRoles(TUser user); + Task> GetRoles(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns true if a user is in a role /// /// /// + /// /// - Task IsInRole(TUser user, string roleName); + Task IsInRole(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserSecurityStampStore.cs b/src/Microsoft.AspNet.Identity/IUserSecurityStampStore.cs index 5dbdd38f81..db79cf58d2 100644 --- a/src/Microsoft.AspNet.Identity/IUserSecurityStampStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserSecurityStampStore.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.AspNet.Identity { @@ -14,14 +15,16 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task SetSecurityStamp(TUser user, string stamp); + Task SetSecurityStamp(TUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken)); /// /// Get the user security stamp /// /// + /// /// - Task GetSecurityStamp(TUser user); + Task GetSecurityStamp(TUser user, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserStore.cs b/src/Microsoft.AspNet.Identity/IUserStore.cs index 1adc85665b..e6b857411f 100644 --- a/src/Microsoft.AspNet.Identity/IUserStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserStore.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -14,35 +15,40 @@ namespace Microsoft.AspNet.Identity /// Insert a new user /// /// + /// /// - Task Create(TUser user); + Task Create(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Update a user /// /// + /// /// - Task Update(TUser user); + Task Update(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Delete a user /// /// + /// /// - Task Delete(TUser user); + Task Delete(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Finds a user /// /// + /// /// - Task FindById(TKey userId); + Task FindById(TKey userId, CancellationToken cancellationToken = default(CancellationToken)); /// /// Find a user by name /// /// + /// /// - Task FindByName(string userName); + Task FindByName(string userName, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserTokenProvider.cs b/src/Microsoft.AspNet.Identity/IUserTokenProvider.cs index 0a665c2342..1595237e53 100644 --- a/src/Microsoft.AspNet.Identity/IUserTokenProvider.cs +++ b/src/Microsoft.AspNet.Identity/IUserTokenProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -14,8 +15,9 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task Generate(string purpose, UserManager manager, TUser user); + Task Generate(string purpose, UserManager manager, TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Validate and unprotect a token, returns null if invalid @@ -24,8 +26,9 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task Validate(string purpose, string token, UserManager manager, TUser user); + Task Validate(string purpose, string token, UserManager manager, TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Notifies the user that a token has been generated, i.e. via email or sms, or can no-op @@ -33,15 +36,17 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task Notify(string token, UserManager manager, TUser user); + Task Notify(string token, UserManager manager, TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns true if provider can be used for this user, i.e. could require a user to have an email /// /// /// + /// /// - Task IsValidProviderForUser(UserManager manager, TUser user); + Task IsValidProviderForUser(UserManager manager, TUser user, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserTwoFactorStore.cs b/src/Microsoft.AspNet.Identity/IUserTwoFactorStore.cs index 0ab772403c..f7384eb90d 100644 --- a/src/Microsoft.AspNet.Identity/IUserTwoFactorStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserTwoFactorStore.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace Microsoft.AspNet.Identity { @@ -14,14 +15,16 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task SetTwoFactorEnabled(TUser user, bool enabled); + Task SetTwoFactorEnabled(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns whether two factor is enabled for the user /// /// + /// /// - Task GetTwoFactorEnabled(TUser user); + Task GetTwoFactorEnabled(TUser user, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IUserValidator.cs b/src/Microsoft.AspNet.Identity/IUserValidator.cs index df04301913..3d72915f62 100644 --- a/src/Microsoft.AspNet.Identity/IUserValidator.cs +++ b/src/Microsoft.AspNet.Identity/IUserValidator.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -17,7 +18,8 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - Task Validate(UserManager manager, TUser user); + Task Validate(UserManager manager, TUser user, CancellationToken cancellationToken = default(CancellationToken)); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/PasswordValidator.cs b/src/Microsoft.AspNet.Identity/PasswordValidator.cs index d242b9e16f..8668991f46 100644 --- a/src/Microsoft.AspNet.Identity/PasswordValidator.cs +++ b/src/Microsoft.AspNet.Identity/PasswordValidator.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -40,8 +41,9 @@ namespace Microsoft.AspNet.Identity /// Ensures that the string is of the required length and meets the configured requirements /// /// + /// /// - public virtual Task Validate(string item) + public virtual Task Validate(string item, CancellationToken cancellationToken = default(CancellationToken)) { if (item == null) { diff --git a/src/Microsoft.AspNet.Identity/RoleManager.cs b/src/Microsoft.AspNet.Identity/RoleManager.cs index 5f6f1067b2..535e574ba6 100644 --- a/src/Microsoft.AspNet.Identity/RoleManager.cs +++ b/src/Microsoft.AspNet.Identity/RoleManager.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -92,17 +93,18 @@ namespace Microsoft.AspNet.Identity GC.SuppressFinalize(this); } - private async Task ValidateRoleInternal(TRole role) + private async Task ValidateRoleInternal(TRole role, CancellationToken cancellationToken) { - return (RoleValidator == null) ? IdentityResult.Success : await RoleValidator.Validate(this, role); + return (RoleValidator == null) ? IdentityResult.Success : await RoleValidator.Validate(this, role, cancellationToken); } /// /// Create a role /// /// + /// /// - public virtual async Task Create(TRole role) + public virtual async Task Create(TRole role, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (role == null) @@ -110,12 +112,12 @@ namespace Microsoft.AspNet.Identity throw new ArgumentNullException("role"); } - var result = await ValidateRoleInternal(role); + var result = await ValidateRoleInternal(role, cancellationToken); if (!result.Succeeded) { return result; } - await Store.Create(role); + await Store.Create(role, cancellationToken); return IdentityResult.Success; } @@ -123,8 +125,9 @@ namespace Microsoft.AspNet.Identity /// Update an existing role /// /// + /// /// - public virtual async Task Update(TRole role) + public virtual async Task Update(TRole role, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (role == null) @@ -132,12 +135,12 @@ namespace Microsoft.AspNet.Identity throw new ArgumentNullException("role"); } - var result = await ValidateRoleInternal(role); + var result = await ValidateRoleInternal(role, cancellationToken); if (!result.Succeeded) { return result; } - await Store.Update(role); + await Store.Update(role, cancellationToken); return IdentityResult.Success; } @@ -145,8 +148,9 @@ namespace Microsoft.AspNet.Identity /// Delete a role /// /// + /// /// - public virtual async Task Delete(TRole role) + public virtual async Task Delete(TRole role, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (role == null) @@ -154,7 +158,7 @@ namespace Microsoft.AspNet.Identity throw new ArgumentNullException("role"); } - await Store.Delete(role); + await Store.Delete(role, cancellationToken); return IdentityResult.Success; } @@ -162,8 +166,9 @@ namespace Microsoft.AspNet.Identity /// Returns true if the role exists /// /// + /// /// - public virtual async Task RoleExists(string roleName) + public virtual async Task RoleExists(string roleName, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (roleName == null) @@ -171,26 +176,28 @@ namespace Microsoft.AspNet.Identity throw new ArgumentNullException("roleName"); } - return await FindByName(roleName) != null; + return await FindByName(roleName, cancellationToken) != null; } /// /// Find a role by id /// /// + /// /// - public virtual async Task FindById(TKey roleId) + public virtual async Task FindById(TKey roleId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - return await Store.FindById(roleId); + return await Store.FindById(roleId, cancellationToken); } /// /// Find a role by name /// /// + /// /// - public virtual async Task FindByName(string roleName) + public virtual async Task FindByName(string roleName, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (roleName == null) @@ -198,7 +205,7 @@ namespace Microsoft.AspNet.Identity throw new ArgumentNullException("roleName"); } - return await Store.FindByName(roleName); + return await Store.FindByName(roleName, cancellationToken); } private void ThrowIfDisposed() diff --git a/src/Microsoft.AspNet.Identity/RoleValidator.cs b/src/Microsoft.AspNet.Identity/RoleValidator.cs index 3cf92c4da9..dcd649272a 100644 --- a/src/Microsoft.AspNet.Identity/RoleValidator.cs +++ b/src/Microsoft.AspNet.Identity/RoleValidator.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity @@ -19,8 +20,9 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task Validate(RoleManager manager, TRole role) + public virtual async Task Validate(RoleManager manager, TRole role, CancellationToken cancellationToken = default(CancellationToken)) { if (manager == null) { diff --git a/src/Microsoft.AspNet.Identity/UserManager.cs b/src/Microsoft.AspNet.Identity/UserManager.cs index 051522ca78..3863816ad6 100644 --- a/src/Microsoft.AspNet.Identity/UserManager.cs +++ b/src/Microsoft.AspNet.Identity/UserManager.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Security.Claims; using System.Text; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.DependencyInjection; @@ -26,6 +27,8 @@ namespace Microsoft.AspNet.Identity private bool _disposed; private IPasswordHasher _passwordHasher; + public UserManager() { } + /// /// Constructor which takes a service provider to find the default interfaces to hook up /// @@ -309,43 +312,45 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual Task CreateIdentity(TUser user, string authenticationType) + public virtual Task CreateIdentity(TUser user, string authenticationType, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (user == null) { throw new ArgumentNullException("user"); } - return ClaimsIdentityFactory.Create(this, user, authenticationType); + return ClaimsIdentityFactory.Create(this, user, authenticationType, cancellationToken); } - private async Task ValidateUserInternal(TUser user) + private async Task ValidateUserInternal(TUser user, CancellationToken cancellationToken) { return (UserValidator == null) ? IdentityResult.Success - : await UserValidator.Validate(this, user); + : await UserValidator.Validate(this, user, cancellationToken); } /// /// Create a user with no password /// /// + /// /// - public virtual async Task Create(TUser user) + public virtual async Task Create(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - await UpdateSecurityStampInternal(user); - var result = await ValidateUserInternal(user); + await UpdateSecurityStampInternal(user, cancellationToken); + var result = await ValidateUserInternal(user, cancellationToken); if (!result.Succeeded) { return result; } if (UserLockoutEnabledByDefault && SupportsUserLockout) { - await GetUserLockoutStore().SetLockoutEnabled(user, true); + await GetUserLockoutStore().SetLockoutEnabled(user, true, cancellationToken); } - await Store.Create(user); + await Store.Create(user, cancellationToken); return IdentityResult.Success; } @@ -353,20 +358,21 @@ namespace Microsoft.AspNet.Identity /// Update a user /// /// + /// /// - public virtual async Task Update(TUser user) + public virtual async Task Update(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (user == null) { throw new ArgumentNullException("user"); } - var result = await ValidateUserInternal(user); + var result = await ValidateUserInternal(user, cancellationToken); if (!result.Succeeded) { return result; } - await Store.Update(user); + await Store.Update(user, cancellationToken); return IdentityResult.Success; } @@ -374,15 +380,16 @@ namespace Microsoft.AspNet.Identity /// Delete a user /// /// + /// /// - public virtual async Task Delete(TUser user) + public virtual async Task Delete(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (user == null) { throw new ArgumentNullException("user"); } - await Store.Delete(user); + await Store.Delete(user, cancellationToken); return IdentityResult.Success; } @@ -390,26 +397,28 @@ namespace Microsoft.AspNet.Identity /// Find a user by id /// /// + /// /// - public virtual Task FindById(TKey userId) + public virtual Task FindById(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - return Store.FindById(userId); + return Store.FindById(userId, cancellationToken); } /// /// Find a user by name /// /// + /// /// - public virtual Task FindByName(string userName) + public virtual Task FindByName(string userName, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (userName == null) { throw new ArgumentNullException("userName"); } - return Store.FindByName(userName); + return Store.FindByName(userName, cancellationToken); } // IUserPasswordStore methods @@ -429,7 +438,7 @@ namespace Microsoft.AspNet.Identity /// /// /// - public virtual async Task Create(TUser user, string password) + public virtual async Task Create(TUser user, string password, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var passwordStore = GetPasswordStore(); @@ -441,12 +450,12 @@ namespace Microsoft.AspNet.Identity { throw new ArgumentNullException("password"); } - var result = await UpdatePasswordInternal(passwordStore, user, password); + var result = await UpdatePasswordInternal(passwordStore, user, password, cancellationToken); if (!result.Succeeded) { return result; } - return await Create(user); + return await Create(user, cancellationToken); } /// @@ -454,16 +463,17 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task Find(string userName, string password) + public virtual async Task Find(string userName, string password, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - var user = await FindByName(userName); + var user = await FindByName(userName, cancellationToken); if (user == null) { return null; } - return await CheckPassword(user, password) ? user : null; + return await CheckPassword(user, password, cancellationToken) ? user : null; } /// @@ -471,8 +481,9 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task CheckPassword(TUser user, string password) + public virtual async Task CheckPassword(TUser user, string password, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var passwordStore = GetPasswordStore(); @@ -480,25 +491,26 @@ namespace Microsoft.AspNet.Identity { return false; } - return await VerifyPassword(passwordStore, user, password); + return await VerifyPassword(passwordStore, user, password, cancellationToken); } /// /// Returns true if the user has a password /// /// + /// /// - public virtual async Task HasPassword(TKey userId) + public virtual async Task HasPassword(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var passwordStore = GetPasswordStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await passwordStore.HasPassword(user); + return await passwordStore.HasPassword(user, cancellationToken); } /// @@ -506,28 +518,29 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task AddPassword(TKey userId, string password) + public virtual async Task AddPassword(TKey userId, string password, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var passwordStore = GetPasswordStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - var hash = await passwordStore.GetPasswordHash(user); + var hash = await passwordStore.GetPasswordHash(user, cancellationToken); if (hash != null) { return new IdentityResult(Resources.UserAlreadyHasPassword); } - var result = await UpdatePasswordInternal(passwordStore, user, password); + var result = await UpdatePasswordInternal(passwordStore, user, password, cancellationToken); if (!result.Succeeded) { return result; } - return await Update(user); + return await Update(user, cancellationToken); } /// @@ -536,26 +549,27 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// public virtual async Task ChangePassword(TKey userId, string currentPassword, - string newPassword) + string newPassword, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var passwordStore = GetPasswordStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - if (await VerifyPassword(passwordStore, user, currentPassword)) + if (await VerifyPassword(passwordStore, user, currentPassword, cancellationToken)) { - var result = await UpdatePasswordInternal(passwordStore, user, newPassword); + var result = await UpdatePasswordInternal(passwordStore, user, newPassword, cancellationToken); if (!result.Succeeded) { return result; } - return await Update(user); + return await Update(user, cancellationToken); } return IdentityResult.Failed(Resources.PasswordMismatch); } @@ -564,36 +578,37 @@ namespace Microsoft.AspNet.Identity /// Remove a user's password /// /// + /// /// - public virtual async Task RemovePassword(TKey userId) + public virtual async Task RemovePassword(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var passwordStore = GetPasswordStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await passwordStore.SetPasswordHash(user, null); - await UpdateSecurityStampInternal(user); - return await Update(user); + await passwordStore.SetPasswordHash(user, null, cancellationToken); + await UpdateSecurityStampInternal(user, cancellationToken); + return await Update(user, cancellationToken); } internal async Task UpdatePasswordInternal(IUserPasswordStore passwordStore, - TUser user, string newPassword) + TUser user, string newPassword, CancellationToken cancellationToken) { if (PasswordValidator != null) { - var result = await PasswordValidator.Validate(newPassword); + var result = await PasswordValidator.Validate(newPassword, cancellationToken); if (!result.Succeeded) { return result; } } await - passwordStore.SetPasswordHash(user, PasswordHasher.HashPassword(newPassword)); - await UpdateSecurityStampInternal(user); + passwordStore.SetPasswordHash(user, PasswordHasher.HashPassword(newPassword), cancellationToken); + await UpdateSecurityStampInternal(user, cancellationToken); return IdentityResult.Success; } @@ -603,11 +618,12 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// protected virtual async Task VerifyPassword(IUserPasswordStore store, TUser user, - string password) + string password, CancellationToken cancellationToken = default(CancellationToken)) { - var hash = await store.GetPasswordHash(user); + var hash = await store.GetPasswordHash(user, cancellationToken); return PasswordHasher.VerifyHashedPassword(hash, password) != PasswordVerificationResult.Failed; } @@ -626,48 +642,51 @@ namespace Microsoft.AspNet.Identity /// Returns the current security stamp for a user /// /// + /// /// - public virtual async Task GetSecurityStamp(TKey userId) + public virtual async Task GetSecurityStamp(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var securityStore = GetSecurityStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await securityStore.GetSecurityStamp(user); + return await securityStore.GetSecurityStamp(user, cancellationToken); } /// /// Generate a new security stamp for a user, used for SignOutEverywhere functionality /// /// + /// /// - public virtual async Task UpdateSecurityStamp(TKey userId) + public virtual async Task UpdateSecurityStamp(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var securityStore = GetSecurityStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await securityStore.SetSecurityStamp(user, NewSecurityStamp()); - return await Update(user); + await UpdateSecurityStampInternal(user, cancellationToken); + return await Update(user, cancellationToken); } /// /// Generate a password reset token for the user using the UserTokenProvider /// /// + /// /// - public virtual async Task GeneratePasswordResetToken(TKey userId) + public virtual async Task GeneratePasswordResetToken(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - return await GenerateUserToken("ResetPassword", userId); + return await GenerateUserToken("ResetPassword", userId, cancellationToken); } /// @@ -676,36 +695,37 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task ResetPassword(TKey userId, string token, string newPassword) + public virtual async Task ResetPassword(TKey userId, string token, string newPassword, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } // Make sure the token is valid and the stamp matches - if (!await VerifyUserToken(userId, "ResetPassword", token)) + if (!await VerifyUserToken(userId, "ResetPassword", token, cancellationToken)) { return IdentityResult.Failed(Resources.InvalidToken); } var passwordStore = GetPasswordStore(); - var result = await UpdatePasswordInternal(passwordStore, user, newPassword); + var result = await UpdatePasswordInternal(passwordStore, user, newPassword, cancellationToken); if (!result.Succeeded) { return result; } - return await Update(user); + return await Update(user, cancellationToken); } // Update the security stamp if the store supports it - internal async Task UpdateSecurityStampInternal(TUser user) + internal async Task UpdateSecurityStampInternal(TUser user, CancellationToken cancellationToken) { if (SupportsUserSecurityStamp) { - await GetSecurityStore().SetSecurityStamp(user, NewSecurityStamp()); + await GetSecurityStore().SetSecurityStamp(user, NewSecurityStamp(), cancellationToken); } } @@ -729,10 +749,10 @@ namespace Microsoft.AspNet.Identity /// Returns the user associated with this login /// /// - public virtual Task Find(UserLoginInfo login) + public virtual Task Find(UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - return GetLoginStore().Find(login); + return GetLoginStore().Find(login, cancellationToken); } /// @@ -740,8 +760,9 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task RemoveLogin(TKey userId, UserLoginInfo login) + public virtual async Task RemoveLogin(TKey userId, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var loginStore = GetLoginStore(); @@ -749,15 +770,15 @@ namespace Microsoft.AspNet.Identity { throw new ArgumentNullException("login"); } - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await loginStore.RemoveLogin(user, login); - await UpdateSecurityStampInternal(user); - return await Update(user); + await loginStore.RemoveLogin(user, login, cancellationToken); + await UpdateSecurityStampInternal(user, cancellationToken); + return await Update(user, cancellationToken); } /// @@ -765,8 +786,9 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task AddLogin(TKey userId, UserLoginInfo login) + public virtual async Task AddLogin(TKey userId, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var loginStore = GetLoginStore(); @@ -774,37 +796,38 @@ namespace Microsoft.AspNet.Identity { throw new ArgumentNullException("login"); } - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - var existingUser = await Find(login); + var existingUser = await Find(login, cancellationToken); if (existingUser != null) { return IdentityResult.Failed(Resources.ExternalLoginExists); } - await loginStore.AddLogin(user, login); - return await Update(user); + await loginStore.AddLogin(user, login, cancellationToken); + return await Update(user, cancellationToken); } /// /// Gets the logins for a user. /// /// + /// /// - public virtual async Task> GetLogins(TKey userId) + public virtual async Task> GetLogins(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var loginStore = GetLoginStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await loginStore.GetLogins(user); + return await loginStore.GetLogins(user, cancellationToken); } // IUserClaimStore methods @@ -823,8 +846,9 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task AddClaim(TKey userId, Claim claim) + public virtual async Task AddClaim(TKey userId, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var claimStore = GetClaimStore(); @@ -832,14 +856,14 @@ namespace Microsoft.AspNet.Identity { throw new ArgumentNullException("claim"); } - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await claimStore.AddClaim(user, claim); - return await Update(user); + await claimStore.AddClaim(user, claim, cancellationToken); + return await Update(user, cancellationToken); } /// @@ -847,37 +871,39 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task RemoveClaim(TKey userId, Claim claim) + public virtual async Task RemoveClaim(TKey userId, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var claimStore = GetClaimStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await claimStore.RemoveClaim(user, claim); - return await Update(user); + await claimStore.RemoveClaim(user, claim, cancellationToken); + return await Update(user, cancellationToken); } /// /// Get a users's claims /// /// + /// /// - public virtual async Task> GetClaims(TKey userId) + public virtual async Task> GetClaims(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var claimStore = GetClaimStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await claimStore.GetClaims(user); + return await claimStore.GetClaims(user, cancellationToken); } private IUserRoleStore GetUserRoleStore() @@ -895,24 +921,25 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task AddToRole(TKey userId, string role) + public virtual async Task AddToRole(TKey userId, string role, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var userRoleStore = GetUserRoleStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - var userRoles = await userRoleStore.GetRoles(user); + var userRoles = await userRoleStore.GetRoles(user, cancellationToken); if (userRoles.Contains(role)) { return new IdentityResult(Resources.UserAlreadyInRole); } - await userRoleStore.AddToRole(user, role); - return await Update(user); + await userRoleStore.AddToRole(user, role, cancellationToken); + return await Update(user, cancellationToken); } /// @@ -920,41 +947,43 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task RemoveFromRole(TKey userId, string role) + public virtual async Task RemoveFromRole(TKey userId, string role, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var userRoleStore = GetUserRoleStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - if (!await userRoleStore.IsInRole(user, role)) + if (!await userRoleStore.IsInRole(user, role, cancellationToken)) { return new IdentityResult(Resources.UserNotInRole); } - await userRoleStore.RemoveFromRole(user, role); - return await Update(user); + await userRoleStore.RemoveFromRole(user, role, cancellationToken); + return await Update(user, cancellationToken); } /// /// Returns the roles for the user /// /// + /// /// - public virtual async Task> GetRoles(TKey userId) + public virtual async Task> GetRoles(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var userRoleStore = GetUserRoleStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await userRoleStore.GetRoles(user); + return await userRoleStore.GetRoles(user, cancellationToken); } /// @@ -962,12 +991,13 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task IsInRole(TKey userId, string role) + public virtual async Task IsInRole(TKey userId, string role, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var userRoleStore = GetUserRoleStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, @@ -992,17 +1022,17 @@ namespace Microsoft.AspNet.Identity /// /// /// - public virtual async Task GetEmail(TKey userId) + public virtual async Task GetEmail(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetEmailStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await store.GetEmail(user); + return await store.GetEmail(user, cancellationToken); } /// @@ -1011,20 +1041,20 @@ namespace Microsoft.AspNet.Identity /// /// /// - public virtual async Task SetEmail(TKey userId, string email) + public virtual async Task SetEmail(TKey userId, string email, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetEmailStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await store.SetEmail(user, email); - await store.SetEmailConfirmed(user, false); - await UpdateSecurityStampInternal(user); - return await Update(user); + await store.SetEmail(user, email, cancellationToken); + await store.SetEmailConfirmed(user, false, cancellationToken); + await UpdateSecurityStampInternal(user, cancellationToken); + return await Update(user, cancellationToken); } /// @@ -1032,7 +1062,7 @@ namespace Microsoft.AspNet.Identity /// /// /// - public virtual Task FindByEmail(string email) + public virtual Task FindByEmail(string email, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetEmailStore(); @@ -1040,7 +1070,7 @@ namespace Microsoft.AspNet.Identity { throw new ArgumentNullException("email"); } - return store.FindByEmail(email); + return store.FindByEmail(email, cancellationToken); } /// @@ -1048,10 +1078,10 @@ namespace Microsoft.AspNet.Identity /// /// /// - public virtual Task GenerateEmailConfirmationToken(TKey userId) + public virtual Task GenerateEmailConfirmationToken(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - return GenerateUserToken("Confirmation", userId); + return GenerateUserToken("Confirmation", userId, cancellationToken); } /// @@ -1059,41 +1089,43 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task ConfirmEmail(TKey userId, string token) + public virtual async Task ConfirmEmail(TKey userId, string token, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetEmailStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - if (!await VerifyUserToken(userId, "Confirmation", token)) + if (!await VerifyUserToken(userId, "Confirmation", token, cancellationToken)) { return IdentityResult.Failed(Resources.InvalidToken); } - await store.SetEmailConfirmed(user, true); - return await Update(user); + await store.SetEmailConfirmed(user, true, cancellationToken); + return await Update(user, cancellationToken); } /// /// Returns true if the user's email has been confirmed /// /// + /// /// - public virtual async Task IsEmailConfirmed(TKey userId) + public virtual async Task IsEmailConfirmed(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetEmailStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await store.GetEmailConfirmed(user); + return await store.GetEmailConfirmed(user, cancellationToken); } // IUserPhoneNumberStore methods @@ -1111,18 +1143,19 @@ namespace Microsoft.AspNet.Identity /// Get a user's phoneNumber /// /// + /// /// - public virtual async Task GetPhoneNumber(TKey userId) + public virtual async Task GetPhoneNumber(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetPhoneNumberStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await store.GetPhoneNumber(user); + return await store.GetPhoneNumber(user, cancellationToken); } /// @@ -1130,21 +1163,22 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task SetPhoneNumber(TKey userId, string phoneNumber) + public virtual async Task SetPhoneNumber(TKey userId, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetPhoneNumberStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await store.SetPhoneNumber(user, phoneNumber); - await store.SetPhoneNumberConfirmed(user, false); - await UpdateSecurityStampInternal(user); - return await Update(user); + await store.SetPhoneNumber(user, phoneNumber, cancellationToken); + await store.SetPhoneNumberConfirmed(user, false, cancellationToken); + await UpdateSecurityStampInternal(user, cancellationToken); + return await Update(user, cancellationToken); } /// @@ -1153,12 +1187,13 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task ChangePhoneNumber(TKey userId, string phoneNumber, string token) + public virtual async Task ChangePhoneNumber(TKey userId, string phoneNumber, string token, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetPhoneNumberStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, @@ -1168,28 +1203,29 @@ namespace Microsoft.AspNet.Identity { return IdentityResult.Failed(Resources.InvalidToken); } - await store.SetPhoneNumber(user, phoneNumber); - await store.SetPhoneNumberConfirmed(user, true); - await UpdateSecurityStampInternal(user); - return await Update(user); + await store.SetPhoneNumber(user, phoneNumber, cancellationToken); + await store.SetPhoneNumberConfirmed(user, true, cancellationToken); + await UpdateSecurityStampInternal(user, cancellationToken); + return await Update(user, cancellationToken); } /// /// Returns true if the user's phone number has been confirmed /// /// + /// /// - public virtual async Task IsPhoneNumberConfirmed(TKey userId) + public virtual async Task IsPhoneNumberConfirmed(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetPhoneNumberStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await store.GetPhoneNumberConfirmed(user); + return await store.GetPhoneNumberConfirmed(user, cancellationToken); } // Two factor APIS @@ -1243,22 +1279,23 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task VerifyUserToken(TKey userId, string purpose, string token) + public virtual async Task VerifyUserToken(TKey userId, string purpose, string token, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (UserTokenProvider == null) { throw new NotSupportedException(Resources.NoTokenProvider); } - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } // Make sure the token is valid - return await UserTokenProvider.Validate(purpose, token, this, user); + return await UserTokenProvider.Validate(purpose, token, this, user, cancellationToken); } /// @@ -1266,21 +1303,22 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task GenerateUserToken(string purpose, TKey userId) + public virtual async Task GenerateUserToken(string purpose, TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (UserTokenProvider == null) { throw new NotSupportedException(Resources.NoTokenProvider); } - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await UserTokenProvider.Generate(purpose, this, user); + return await UserTokenProvider.Generate(purpose, this, user, cancellationToken); } /// @@ -1306,11 +1344,12 @@ namespace Microsoft.AspNet.Identity /// Returns a list of valid two factor providers for a user /// /// + /// /// - public virtual async Task> GetValidTwoFactorProviders(TKey userId) + public virtual async Task> GetValidTwoFactorProviders(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, @@ -1319,7 +1358,7 @@ namespace Microsoft.AspNet.Identity var results = new List(); foreach (var f in TwoFactorProviders) { - if (await f.Value.IsValidProviderForUser(this, user)) + if (await f.Value.IsValidProviderForUser(this, user, cancellationToken)) { results.Add(f.Key); } @@ -1333,11 +1372,12 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task VerifyTwoFactorToken(TKey userId, string twoFactorProvider, string token) + public virtual async Task VerifyTwoFactorToken(TKey userId, string twoFactorProvider, string token, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, @@ -1350,7 +1390,7 @@ namespace Microsoft.AspNet.Identity } // Make sure the token is valid var provider = _factors[twoFactorProvider]; - return await provider.Validate(twoFactorProvider, token, this, user); + return await provider.Validate(twoFactorProvider, token, this, user, cancellationToken); } /// @@ -1358,11 +1398,12 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task GenerateTwoFactorToken(TKey userId, string twoFactorProvider) + public virtual async Task GenerateTwoFactorToken(TKey userId, string twoFactorProvider, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, @@ -1373,7 +1414,7 @@ namespace Microsoft.AspNet.Identity throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Resources.NoTwoFactorProvider, twoFactorProvider)); } - return await _factors[twoFactorProvider].Generate(twoFactorProvider, this, user); + return await _factors[twoFactorProvider].Generate(twoFactorProvider, this, user, cancellationToken); } /// @@ -1382,12 +1423,13 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// public virtual async Task NotifyTwoFactorToken(TKey userId, string twoFactorProvider, - string token) + string token, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, @@ -1398,7 +1440,7 @@ namespace Microsoft.AspNet.Identity throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Resources.NoTwoFactorProvider, twoFactorProvider)); } - await _factors[twoFactorProvider].Notify(token, this, user); + await _factors[twoFactorProvider].Notify(token, this, user, cancellationToken); return IdentityResult.Success; } @@ -1417,18 +1459,19 @@ namespace Microsoft.AspNet.Identity /// Get a user's two factor provider /// /// + /// /// - public virtual async Task GetTwoFactorEnabled(TKey userId) + public virtual async Task GetTwoFactorEnabled(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserTwoFactorStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await store.GetTwoFactorEnabled(user); + return await store.GetTwoFactorEnabled(user, cancellationToken); } /// @@ -1436,20 +1479,21 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task SetTwoFactorEnabled(TKey userId, bool enabled) + public virtual async Task SetTwoFactorEnabled(TKey userId, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserTwoFactorStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await store.SetTwoFactorEnabled(user, enabled); - await UpdateSecurityStampInternal(user); - return await Update(user); + await store.SetTwoFactorEnabled(user, enabled, cancellationToken); + await UpdateSecurityStampInternal(user, cancellationToken); + return await Update(user, cancellationToken); } // SMS/Email methods @@ -1460,19 +1504,20 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task SendEmail(TKey userId, string subject, string body) + public virtual async Task SendEmail(TKey userId, string subject, string body, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (EmailService != null) { var msg = new IdentityMessage { - Destination = await GetEmail(userId), + Destination = await GetEmail(userId, cancellationToken), Subject = subject, Body = body, }; - await EmailService.Send(msg); + await EmailService.Send(msg, cancellationToken); } } @@ -1481,18 +1526,19 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task SendSms(TKey userId, string message) + public virtual async Task SendSms(TKey userId, string message, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); if (SmsService != null) { var msg = new IdentityMessage { - Destination = await GetPhoneNumber(userId), + Destination = await GetPhoneNumber(userId, cancellationToken), Body = message }; - await SmsService.Send(msg); + await SmsService.Send(msg, cancellationToken); } } @@ -1511,22 +1557,23 @@ namespace Microsoft.AspNet.Identity /// Returns true if the user is locked out /// /// + /// /// - public virtual async Task IsLockedOut(TKey userId) + public virtual async Task IsLockedOut(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserLockoutStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - if (!await store.GetLockoutEnabled(user)) + if (!await store.GetLockoutEnabled(user, cancellationToken)) { return false; } - var lockoutTime = await store.GetLockoutEndDate(user).ConfigureAwait((false)); + var lockoutTime = await store.GetLockoutEndDate(user, cancellationToken).ConfigureAwait((false)); return lockoutTime >= DateTimeOffset.UtcNow; } @@ -1536,18 +1583,18 @@ namespace Microsoft.AspNet.Identity /// /// /// - public virtual async Task SetLockoutEnabled(TKey userId, bool enabled) + public virtual async Task SetLockoutEnabled(TKey userId, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserLockoutStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - await store.SetLockoutEnabled(user, enabled); - return await Update(user); + await store.SetLockoutEnabled(user, enabled, cancellationToken); + return await Update(user, cancellationToken); } /// @@ -1555,29 +1602,30 @@ namespace Microsoft.AspNet.Identity /// /// /// - public virtual async Task GetLockoutEnabled(TKey userId) + public virtual async Task GetLockoutEnabled(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserLockoutStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await store.GetLockoutEnabled(user); + return await store.GetLockoutEnabled(user, cancellationToken); } /// /// Returns the user lockout end date /// /// + /// /// - public virtual async Task GetLockoutEndDate(TKey userId) + public virtual async Task GetLockoutEndDate(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserLockoutStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, @@ -1591,23 +1639,24 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task SetLockoutEndDate(TKey userId, DateTimeOffset lockoutEnd) + public virtual async Task SetLockoutEndDate(TKey userId, DateTimeOffset lockoutEnd, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserLockoutStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - if (!await store.GetLockoutEnabled(user).ConfigureAwait((false))) + if (!await store.GetLockoutEnabled(user, cancellationToken).ConfigureAwait((false))) { return IdentityResult.Failed(Resources.LockoutNotEnabled); } - await store.SetLockoutEndDate(user, lockoutEnd); - return await Update(user); + await store.SetLockoutEndDate(user, lockoutEnd, cancellationToken); + return await Update(user, cancellationToken); } /// @@ -1616,47 +1665,48 @@ namespace Microsoft.AspNet.Identity /// and the AccessFailedCount will be reset to 0. /// /// + /// /// - public virtual async Task AccessFailed(TKey userId) + public virtual async Task AccessFailed(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserLockoutStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } // If this puts the user over the threshold for lockout, lock them out and reset the access failed count - var count = await store.IncrementAccessFailedCount(user); + var count = await store.IncrementAccessFailedCount(user, cancellationToken); if (count < MaxFailedAccessAttemptsBeforeLockout) { - return await Update(user); + return await Update(user, cancellationToken); } await - store.SetLockoutEndDate(user, DateTimeOffset.UtcNow.Add(DefaultAccountLockoutTimeSpan)) - ; - await store.ResetAccessFailedCount(user); - return await Update(user); + store.SetLockoutEndDate(user, DateTimeOffset.UtcNow.Add(DefaultAccountLockoutTimeSpan), cancellationToken); + await store.ResetAccessFailedCount(user, cancellationToken); + return await Update(user, cancellationToken); } /// /// Resets the access failed count for the user to 0 /// /// + /// /// - public virtual async Task ResetAccessFailedCount(TKey userId) + public virtual async Task ResetAccessFailedCount(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserLockoutStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } await store.ResetAccessFailedCount(user); - return await Update(user); + return await Update(user, cancellationToken); } /// @@ -1664,17 +1714,17 @@ namespace Microsoft.AspNet.Identity /// /// /// - public virtual async Task GetAccessFailedCount(TKey userId) + public virtual async Task GetAccessFailedCount(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfDisposed(); var store = GetUserLockoutStore(); - var user = await FindById(userId); + var user = await FindById(userId, cancellationToken); if (user == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound, userId)); } - return await store.GetAccessFailedCount(user); + return await store.GetAccessFailedCount(user, cancellationToken); } private void ThrowIfDisposed() diff --git a/src/Microsoft.AspNet.Identity/UserValidator.cs b/src/Microsoft.AspNet.Identity/UserValidator.cs index 4fa83082d2..78a1abc05e 100644 --- a/src/Microsoft.AspNet.Identity/UserValidator.cs +++ b/src/Microsoft.AspNet.Identity/UserValidator.cs @@ -1,3 +1,4 @@ +using System.Threading; #if NET45 using System.Net.Mail; #endif @@ -41,8 +42,9 @@ namespace Microsoft.AspNet.Identity /// /// /// + /// /// - public virtual async Task Validate(UserManager manager, TUser user) + public virtual async Task Validate(UserManager manager, TUser user, CancellationToken cancellationToken = default(CancellationToken)) { if (manager == null) { diff --git a/src/Microsoft.AspNet.Identity/project.json b/src/Microsoft.AspNet.Identity/project.json index d05403206d..fe3b27e4c9 100644 --- a/src/Microsoft.AspNet.Identity/project.json +++ b/src/Microsoft.AspNet.Identity/project.json @@ -3,6 +3,7 @@ "dependencies": { "Microsoft.AspNet.DependencyInjection" : "0.1-alpha-*", "System.Security.Claims" : "0.1-alpha-*", + "Microsoft.AspNet.HttpFeature" : "0.1-alpha-*", "Microsoft.AspNet.Security.DataProtection" : "0.1-alpha-*" }, "configurations": { diff --git a/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryStoreTest.cs b/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryStoreTest.cs index 026ab5c56f..95dac2ba94 100644 --- a/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryStoreTest.cs +++ b/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryStoreTest.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.Testing; using Xunit; @@ -388,23 +389,23 @@ namespace Microsoft.AspNet.Identity.InMemory.Test private class StaticTokenProvider : IUserTokenProvider { public Task Generate(string purpose, UserManager manager, - InMemoryUser user) + InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(MakeToken(purpose, user)); } public Task Validate(string purpose, string token, UserManager manager, - InMemoryUser user) + InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(token == MakeToken(purpose, user)); } - public Task Notify(string token, UserManager manager, InMemoryUser user) + public Task Notify(string token, UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task IsValidProviderForUser(UserManager manager, InMemoryUser user) + public Task IsValidProviderForUser(UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(true); } @@ -719,17 +720,17 @@ namespace Microsoft.AspNet.Identity.InMemory.Test { public const string ErrorMessage = "I'm Bad."; - public Task Validate(string password) + public Task Validate(string password, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(IdentityResult.Failed(ErrorMessage)); } - public Task Validate(RoleManager manager, InMemoryRole role) + public Task Validate(RoleManager manager, InMemoryRole role, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(IdentityResult.Failed(ErrorMessage)); } - public Task Validate(UserManager manager, InMemoryUser user) + public Task Validate(UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(IdentityResult.Failed(ErrorMessage)); } @@ -1092,23 +1093,23 @@ namespace Microsoft.AspNet.Identity.InMemory.Test private class EmailTokenProvider : IUserTokenProvider { - public Task Generate(string purpose, UserManager manager, InMemoryUser user) + public Task Generate(string purpose, UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(MakeToken(purpose)); } public Task Validate(string purpose, string token, UserManager manager, - InMemoryUser user) + InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(token == MakeToken(purpose)); } - public Task Notify(string token, UserManager manager, InMemoryUser user) + public Task Notify(string token, UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return manager.SendEmail(user.Id, token, token); } - public async Task IsValidProviderForUser(UserManager manager, InMemoryUser user) + public async Task IsValidProviderForUser(UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return !string.IsNullOrEmpty(await manager.GetEmail(user.Id)); } @@ -1121,23 +1122,23 @@ namespace Microsoft.AspNet.Identity.InMemory.Test private class SmsTokenProvider : IUserTokenProvider { - public Task Generate(string purpose, UserManager manager, InMemoryUser user) + public Task Generate(string purpose, UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(MakeToken(purpose)); } public Task Validate(string purpose, string token, UserManager manager, - InMemoryUser user) + InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(token == MakeToken(purpose)); } - public Task Notify(string token, UserManager manager, InMemoryUser user) + public Task Notify(string token, UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return manager.SendSms(user.Id, token); } - public async Task IsValidProviderForUser(UserManager manager, InMemoryUser user) + public async Task IsValidProviderForUser(UserManager manager, InMemoryUser user, CancellationToken cancellationToken = default(CancellationToken)) { return !string.IsNullOrEmpty(await manager.GetPhoneNumber(user.Id)); } @@ -1419,7 +1420,7 @@ namespace Microsoft.AspNet.Identity.InMemory.Test { public IdentityMessage Message { get; set; } - public Task Send(IdentityMessage message) + public Task Send(IdentityMessage message, CancellationToken cancellationToken = default(CancellationToken)) { Message = message; return Task.FromResult(0); diff --git a/test/Microsoft.AspNet.Identity.Security.Test/SignInManagerTest.cs b/test/Microsoft.AspNet.Identity.Security.Test/SignInManagerTest.cs new file mode 100644 index 0000000000..3271322a36 --- /dev/null +++ b/test/Microsoft.AspNet.Identity.Security.Test/SignInManagerTest.cs @@ -0,0 +1,173 @@ +using System.Threading; +using Microsoft.AspNet.Abstractions; +using Microsoft.AspNet.Abstractions.Security; +using Moq; +using System.Security.Claims; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.AspNet.Identity.Security.Test +{ + public class SignInManagerTest + { + +#if NET45 + //TODO: Mock fails in K (this works fine in net45) + [Fact] + public async Task EnsureClaimsIdentityFactoryCreateIdentityCalled() + { + // Setup + var store = new Mock>(); + var user = new TestUser { UserName = "Foo" }; + var userManager = new UserManager(store.Object); + var identityFactory = new Mock>(); + const string authType = "Test"; + var testIdentity = new ClaimsIdentity(authType); + identityFactory.Setup(s => s.Create(userManager, user, authType, CancellationToken.None)).ReturnsAsync(testIdentity).Verifiable(); + userManager.ClaimsIdentityFactory = identityFactory.Object; + var context = new Mock(); + var response = new Mock(); + context.Setup(c => c.Response).Returns(response.Object).Verifiable(); + response.Setup(r => r.SignIn(testIdentity, It.IsAny())).Verifiable(); + var helper = new SignInManager { UserManager = userManager, AuthenticationType = authType, Context = context.Object }; + + // Act + await helper.SignIn(user, false, false); + + // Assert + identityFactory.VerifyAll(); + } + + [Fact] + public async Task PasswordSignInReturnsLockedOutWhenLockedOut() + { + // Setup + var user = new TestUser { UserName = "Foo" }; + var manager = new Mock>(); + manager.Setup(m => m.IsLockedOut(user.Id, CancellationToken.None)).ReturnsAsync(true).Verifiable(); + manager.Setup(m => m.FindByName(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable(); + var helper = new SignInManager { UserManager = manager.Object }; + + // Act + var result = await helper.PasswordSignIn(user.UserName, "bogus", false, false); + + // Assert + Assert.Equal(SignInStatus.LockedOut, result); + manager.VerifyAll(); + } + + [Fact] + public async Task CanPasswordSignIn() + { + // Setup + var user = new TestUser { UserName = "Foo" }; + var manager = new Mock>(); + manager.Setup(m => m.IsLockedOut(user.Id, CancellationToken.None)).ReturnsAsync(false).Verifiable(); + manager.Setup(m => m.FindByName(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable(); + manager.Setup(m => m.CheckPassword(user, "password", CancellationToken.None)).ReturnsAsync(true).Verifiable(); + manager.Setup(m => m.CreateIdentity(user, "Microsoft.AspNet.Identity", CancellationToken.None)).ReturnsAsync(new ClaimsIdentity("Microsoft.AspNet.Identity")).Verifiable(); + var context = new Mock(); + var response = new Mock(); + context.Setup(c => c.Response).Returns(response.Object).Verifiable(); + response.Setup(r => r.SignIn(It.IsAny(), It.IsAny())).Verifiable(); + var helper = new SignInManager { UserManager = manager.Object, Context = context.Object }; + + // Act + var result = await helper.PasswordSignIn(user.UserName, "password", false, false); + + // Assert + Assert.Equal(SignInStatus.Success, result); + manager.VerifyAll(); + } + + [Fact] + public async Task PasswordSignInFailsWithWrongPassword() + { + // Setup + var user = new TestUser { UserName = "Foo" }; + var manager = new Mock>(); + manager.Setup(m => m.IsLockedOut(user.Id, CancellationToken.None)).ReturnsAsync(false).Verifiable(); + manager.Setup(m => m.FindByName(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable(); + manager.Setup(m => m.CheckPassword(user, "bogus", CancellationToken.None)).ReturnsAsync(false).Verifiable(); + var helper = new SignInManager { UserManager = manager.Object }; + + // Act + var result = await helper.PasswordSignIn(user.UserName, "bogus", false, false); + + // Assert + Assert.Equal(SignInStatus.Failure, result); + manager.VerifyAll(); + } + + + [Fact] + public async Task PasswordSignInFailsWithUnknownUser() + { + // Setup + var manager = new Mock>(); + manager.Setup(m => m.FindByName("bogus", CancellationToken.None)).ReturnsAsync(null).Verifiable(); + var helper = new SignInManager { UserManager = manager.Object }; + + // Act + var result = await helper.PasswordSignIn("bogus", "bogus", false, false); + + // Assert + Assert.Equal(SignInStatus.Failure, result); + manager.VerifyAll(); + } + + [Fact] + public async Task PasswordSignInFailsWithNoUserManager() + { + // Setup + var helper = new SignInManager(); + + // Act + var result = await helper.PasswordSignIn("bogus", "bogus", false, false); + + // Assert + Assert.Equal(SignInStatus.Failure, result); + } + + [Fact] + public async Task CreateUserIdentityReturnsNullNoUserManager() + { + // Setup + var user = new TestUser(); + var helper = new SignInManager(); + + // Act + var result = await helper.CreateUserIdentity(user); + + // Assert + Assert.Null(result); + } + + + [Fact] + public async Task PasswordSignInFailsWithWrongPasswordCanAccessFailedAndLockout() + { + // Setup + var user = new TestUser { UserName = "Foo" }; + var manager = new Mock>(); + var lockedout = false; + manager.Setup(m => m.AccessFailed(user.Id, CancellationToken.None)).Returns(() => + { + lockedout = true; + return Task.FromResult(IdentityResult.Success); + }).Verifiable(); + manager.Setup(m => m.IsLockedOut(user.Id, CancellationToken.None)).Returns(() => Task.FromResult(lockedout)); + manager.Setup(m => m.FindByName(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable(); + manager.Setup(m => m.CheckPassword(user, "bogus", CancellationToken.None)).ReturnsAsync(false).Verifiable(); + var helper = new SignInManager { UserManager = manager.Object }; + + // Act + var result = await helper.PasswordSignIn(user.UserName, "bogus", false, true); + + // Assert + Assert.Equal(SignInStatus.LockedOut, result); + manager.VerifyAll(); + } +#endif + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.Security.Test/TestUser.cs b/test/Microsoft.AspNet.Identity.Security.Test/TestUser.cs new file mode 100644 index 0000000000..aa9ab7607f --- /dev/null +++ b/test/Microsoft.AspNet.Identity.Security.Test/TestUser.cs @@ -0,0 +1,12 @@ +namespace Microsoft.AspNet.Identity.Security.Test +{ + public class TestUser : TestUser + { + } + + public class TestUser : IUser + { + public TKey Id { get; private set; } + public string UserName { get; set; } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.Security.Test/project.json b/test/Microsoft.AspNet.Identity.Security.Test/project.json new file mode 100644 index 0000000000..23dc6b1d43 --- /dev/null +++ b/test/Microsoft.AspNet.Identity.Security.Test/project.json @@ -0,0 +1,48 @@ +{ + "version": "0.1-alpha-*", + "dependencies": { + "Microsoft.AspNet.Abstractions" : "0.1-alpha-*", + "Microsoft.AspNet.ConfigurationModel" : "0.1-alpha-*", + "Microsoft.AspNet.DependencyInjection" : "0.1-alpha-*", + "Microsoft.AspNet.Identity" : "0.1-alpha-*", + "Microsoft.AspNet.Identity.Security" : "0.1-alpha-*", + "Microsoft.AspNet.Testing" : "0.1-alpha-*", + "System.Security.Claims" : "0.1-alpha-*", + "Xunit.KRunner": "0.1-alpha-*", + "xunit.abstractions": "2.0.0-aspnet-*", + "xunit.assert": "2.0.0-aspnet-*", + "xunit.core": "2.0.0-aspnet-*", + "xunit.execution": "2.0.0-aspnet-*" + }, + "configurations": { + "net45": { + "dependencies": { + "Moq" : "4.2.1312.1622", + "System.Runtime": "", + "System.Collections": "" + } + }, + "k10": { + "dependencies": { + "System.Collections": "4.0.0.0", + "System.Collections.Concurrent": "4.0.0.0", + "System.ComponentModel": "4.0.0.0", + "System.Console": "4.0.0.0", + "System.Diagnostics.Debug": "4.0.10.0", + "System.Globalization": "4.0.10.0", + "System.Linq": "4.0.0.0", + "System.Linq.Expressions": "4.0.0.0", + "System.Reflection": "4.0.10.0", + "System.Reflection.Extensions": "4.0.0.0", + "System.Resources.ResourceManager": "4.0.0.0", + "System.Runtime": "4.0.20.0", + "System.Runtime.Extensions": "4.0.10.0", + "System.Threading": "4.0.0.0", + "System.Threading.Tasks": "4.0.10.0" + } + } + }, + "commands": { + "test": "Xunit.KRunner" + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.Test/ClaimsIdentityFactoryTest.cs b/test/Microsoft.AspNet.Identity.Test/ClaimsIdentityFactoryTest.cs index e84fae5d76..49722d323a 100644 --- a/test/Microsoft.AspNet.Identity.Test/ClaimsIdentityFactoryTest.cs +++ b/test/Microsoft.AspNet.Identity.Test/ClaimsIdentityFactoryTest.cs @@ -1,5 +1,9 @@ using System; +using System.Linq; +using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; +using Moq; using Xunit; namespace Microsoft.AspNet.Identity.Test @@ -19,29 +23,49 @@ namespace Microsoft.AspNet.Identity.Test async () => await factory.Create(manager, new TestUser(), null)); } - [Fact] - public void ConvertIdToStringWithDefaultStringReturnsNull() + #if NET45 + //TODO: Mock fails in K (this works fine in net45) + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public async Task EnsureClaimsIdentityHasExpectedClaims(bool supportRoles, bool supportClaims) { + // Setup + var userManager = new Mock>(); + var user = new TestUser { UserName = "Foo" }; + userManager.Setup(m => m.SupportsUserRole).Returns(supportRoles); + userManager.Setup(m => m.SupportsUserClaim).Returns(supportClaims); + var roleClaims = new[] { "Admin", "Local" }; + userManager.Setup(m => m.GetRoles(user.Id, CancellationToken.None)).ReturnsAsync(roleClaims); + var userClaims = new[] { new Claim("Whatever", "Value"), new Claim("Whatever2", "Value2") }; + userManager.Setup(m => m.GetClaims(user.Id, CancellationToken.None)).ReturnsAsync(userClaims); + + const string authType = "Microsoft.AspNet.Identity"; var factory = new ClaimsIdentityFactory(); - Assert.Null(factory.ConvertIdToString(default(string))); - } - [Fact] - public void ConvertIdToStringWithDefaultIntReturnsNull() - { - var factory = new ClaimsIdentityFactory, int>(); - Assert.Null(factory.ConvertIdToString(default(int))); - } + // Act + var identity = await factory.Create(userManager.Object, user, authType); - [Fact] - public void ConvertIdToStringWithDefaultGuidReturnsNull() - { - var factory = new ClaimsIdentityFactory, Guid>(); - Assert.Null(factory.ConvertIdToString(default(Guid))); + // Assert + Assert.NotNull(identity); + Assert.Equal(authType, identity.AuthenticationType); + var claims = identity.Claims; + Assert.NotNull(claims); + Assert.True( + claims.Any(c => c.Type == factory.UserNameClaimType && c.Value == user.UserName)); + Assert.True(claims.Any(c => c.Type == factory.UserIdClaimType && c.Value == user.Id)); + Assert.Equal(supportRoles, claims.Any(c => c.Type == factory.RoleClaimType && c.Value == "Admin")); + Assert.Equal(supportRoles, claims.Any(c => c.Type == factory.RoleClaimType && c.Value == "Local")); + foreach (var cl in userClaims) + { + Assert.Equal(supportClaims, claims.Any(c => c.Type == cl.Type && c.Value == cl.Value)); + } } +#endif - // TODO: Need Mock (test in InMemory for now) - //[Fact] + //[Fact] //public async Task ClaimsIdentityTest() //{ // var db = UnitTestHelper.CreateDefaultDb(); diff --git a/test/Microsoft.AspNet.Identity.Test/NoopRoleStore.cs b/test/Microsoft.AspNet.Identity.Test/NoopRoleStore.cs index 8ae6538e06..f1173efa41 100644 --- a/test/Microsoft.AspNet.Identity.Test/NoopRoleStore.cs +++ b/test/Microsoft.AspNet.Identity.Test/NoopRoleStore.cs @@ -1,25 +1,26 @@ +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity.Test { public class NoopRoleStore : IRoleStore { - public Task Create(TestRole user) + public Task Create(TestRole user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task Update(TestRole user) + public Task Update(TestRole user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task FindById(string roleId) + public Task FindById(string roleId, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } - public Task FindByName(string userName) + public Task FindByName(string userName, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } @@ -28,7 +29,7 @@ namespace Microsoft.AspNet.Identity.Test { } - public Task Delete(TestRole user) + public Task Delete(TestRole user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } diff --git a/test/Microsoft.AspNet.Identity.Test/NoopUserStore.cs b/test/Microsoft.AspNet.Identity.Test/NoopUserStore.cs index 134f2c64b1..014144e9ae 100644 --- a/test/Microsoft.AspNet.Identity.Test/NoopUserStore.cs +++ b/test/Microsoft.AspNet.Identity.Test/NoopUserStore.cs @@ -1,25 +1,26 @@ +using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity.Test { public class NoopUserStore : IUserStore { - public Task Create(TestUser user) + public Task Create(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task Update(TestUser user) + public Task Update(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task FindById(string userId) + public Task FindById(string userId, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } - public Task FindByName(string userName) + public Task FindByName(string userName, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } @@ -28,7 +29,7 @@ namespace Microsoft.AspNet.Identity.Test { } - public Task Delete(TestUser user) + public Task Delete(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } diff --git a/test/Microsoft.AspNet.Identity.Test/RoleManagerTest.cs b/test/Microsoft.AspNet.Identity.Test/RoleManagerTest.cs index 9fc3507758..3c50147c7c 100644 --- a/test/Microsoft.AspNet.Identity.Test/RoleManagerTest.cs +++ b/test/Microsoft.AspNet.Identity.Test/RoleManagerTest.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Xunit; @@ -57,27 +58,27 @@ namespace Microsoft.AspNet.Identity.Test private class NotImplementedStore : IRoleStore { - public Task Create(TestRole role) + public Task Create(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task Update(TestRole role) + public Task Update(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task Delete(TestRole role) + public Task Delete(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task FindById(string roleId) + public Task FindById(string roleId, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task FindByName(string roleName) + public Task FindByName(string roleName, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } diff --git a/test/Microsoft.AspNet.Identity.Test/TestUser.cs b/test/Microsoft.AspNet.Identity.Test/TestUser.cs index b8455e4cdf..cf4d975f0d 100644 --- a/test/Microsoft.AspNet.Identity.Test/TestUser.cs +++ b/test/Microsoft.AspNet.Identity.Test/TestUser.cs @@ -1,12 +1,18 @@ +using System; + namespace Microsoft.AspNet.Identity.Test { public class TestUser : TestUser { + public TestUser() + { + Id = Guid.NewGuid().ToString(); + } } public class TestUser : IUser { - public TKey Id { get; private set; } + public TKey Id { get; set; } public string UserName { get; set; } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs b/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs index 461ae2b5f0..42f0dc546d 100644 --- a/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs +++ b/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs @@ -2,8 +2,10 @@ using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.Testing; +using Moq; using Xunit; namespace Microsoft.AspNet.Identity.Test @@ -27,23 +29,100 @@ namespace Microsoft.AspNet.Identity.Test Assert.NotNull(manager.StorePublic); } +#if NET45 //TODO: Mock fails in K (this works fine in net45) - //[Fact] - //public async Task CreateTest() - //{ - // // Setup - // var store = new Mock>(); - // var user = new TestUser(); - // store.Setup(s => s.Create(user)).Verifiable(); - // var userManager = new UserManager(store.Object); + [Fact] + public async Task CreateCallsStore() + { + // Setup + var store = new Mock>(); + var user = new TestUser { UserName = "Foo" }; + store.Setup(s => s.Create(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable(); + var validator = new Mock>(); + var userManager = new UserManager(store.Object); + validator.Setup(v => v.Validate(userManager, user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable(); + userManager.UserValidator = validator.Object; - // // Act - // var result = await userManager.Create(user); + // Act + var result = await userManager.Create(user); - // // Assert - // Assert.True(result.Succeeded); - // store.VerifyAll(); - //} + // Assert + Assert.True(result.Succeeded); + store.VerifyAll(); + } + + [Fact] + public async Task DeleteCallsStore() + { + // Setup + var store = new Mock>(); + var user = new TestUser { UserName = "Foo" }; + store.Setup(s => s.Delete(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable(); + var userManager = new UserManager(store.Object); + + // Act + var result = await userManager.Delete(user); + + // Assert + Assert.True(result.Succeeded); + store.VerifyAll(); + } + + [Fact] + public async Task UpdateCallsStore() + { + // Setup + var store = new Mock>(); + var user = new TestUser { UserName = "Foo" }; + store.Setup(s => s.Update(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable(); + var validator = new Mock>(); + var userManager = new UserManager(store.Object); + validator.Setup(v => v.Validate(userManager, user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable(); + userManager.UserValidator = validator.Object; + + // Act + var result = await userManager.Update(user); + + // Assert + Assert.True(result.Succeeded); + store.VerifyAll(); + } + + [Fact] + public async Task FindByIdCallsStore() + { + // Setup + var store = new Mock>(); + var user = new TestUser { UserName = "Foo" }; + store.Setup(s => s.FindById(user.Id, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable(); + var userManager = new UserManager(store.Object); + + // Act + var result = await userManager.FindById(user.Id); + + // Assert + Assert.Equal(user, result); + store.VerifyAll(); + } + + [Fact] + public async Task FindByNameCallsStore() + { + // Setup + var store = new Mock>(); + var user = new TestUser {UserName="Foo"}; + store.Setup(s => s.FindByName(user.UserName, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable(); + var userManager = new UserManager(store.Object); + + // Act + var result = await userManager.FindByName(user.UserName); + + // Assert + Assert.Equal(user, result); + store.VerifyAll(); + } + +#endif [Fact] public async Task CheckPasswordWithNullUserReturnsFalse() @@ -372,7 +451,7 @@ namespace Microsoft.AspNet.Identity.Test { public const string ErrorMessage = "I'm Bad."; - public Task Validate(string password) + public Task Validate(string password, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(IdentityResult.Failed(ErrorMessage)); } @@ -389,97 +468,97 @@ namespace Microsoft.AspNet.Identity.Test IUserRoleStore, IUserSecurityStampStore { - public Task> GetClaims(TestUser user) + public Task> GetClaims(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult>(new List()); } - public Task AddClaim(TestUser user, Claim claim) + public Task AddClaim(TestUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task RemoveClaim(TestUser user, Claim claim) + public Task RemoveClaim(TestUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task SetEmail(TestUser user, string email) + public Task SetEmail(TestUser user, string email, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task GetEmail(TestUser user) + public Task GetEmail(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(""); } - public Task GetEmailConfirmed(TestUser user) + public Task GetEmailConfirmed(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(false); } - public Task SetEmailConfirmed(TestUser user, bool confirmed) + public Task SetEmailConfirmed(TestUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task FindByEmail(string email) + public Task FindByEmail(string email, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } - public Task GetLockoutEndDate(TestUser user) + public Task GetLockoutEndDate(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(DateTimeOffset.MinValue); } - public Task SetLockoutEndDate(TestUser user, DateTimeOffset lockoutEnd) + public Task SetLockoutEndDate(TestUser user, DateTimeOffset lockoutEnd, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task IncrementAccessFailedCount(TestUser user) + public Task IncrementAccessFailedCount(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task ResetAccessFailedCount(TestUser user) + public Task ResetAccessFailedCount(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task GetAccessFailedCount(TestUser user) + public Task GetAccessFailedCount(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task GetLockoutEnabled(TestUser user) + public Task GetLockoutEnabled(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(false); } - public Task SetLockoutEnabled(TestUser user, bool enabled) + public Task SetLockoutEnabled(TestUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task AddLogin(TestUser user, UserLoginInfo login) + public Task AddLogin(TestUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task RemoveLogin(TestUser user, UserLoginInfo login) + public Task RemoveLogin(TestUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task> GetLogins(TestUser user) + public Task> GetLogins(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult>(new List()); } - public Task Find(UserLoginInfo login) + public Task Find(UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } @@ -488,102 +567,102 @@ namespace Microsoft.AspNet.Identity.Test { } - public Task Create(TestUser user) + public Task Create(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task Update(TestUser user) + public Task Update(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task Delete(TestUser user) + public Task Delete(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task FindById(string userId) + public Task FindById(string userId, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } - public Task FindByName(string userName) + public Task FindByName(string userName, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } - public Task SetPasswordHash(TestUser user, string passwordHash) + public Task SetPasswordHash(TestUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task GetPasswordHash(TestUser user) + public Task GetPasswordHash(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(null); } - public Task HasPassword(TestUser user) + public Task HasPassword(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(false); } - public Task SetPhoneNumber(TestUser user, string phoneNumber) + public Task SetPhoneNumber(TestUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task GetPhoneNumber(TestUser user) + public Task GetPhoneNumber(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(""); } - public Task GetPhoneNumberConfirmed(TestUser user) + public Task GetPhoneNumberConfirmed(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(false); } - public Task SetPhoneNumberConfirmed(TestUser user, bool confirmed) + public Task SetPhoneNumberConfirmed(TestUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task AddToRole(TestUser user, string roleName) + public Task AddToRole(TestUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task RemoveFromRole(TestUser user, string roleName) + public Task RemoveFromRole(TestUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task> GetRoles(TestUser user) + public Task> GetRoles(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult>(new List()); } - public Task IsInRole(TestUser user, string roleName) + public Task IsInRole(TestUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(false); } - public Task SetSecurityStamp(TestUser user, string stamp) + public Task SetSecurityStamp(TestUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task GetSecurityStamp(TestUser user) + public Task GetSecurityStamp(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(""); } - public Task SetTwoFactorEnabled(TestUser user, bool enabled) + public Task SetTwoFactorEnabled(TestUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task GetTwoFactorEnabled(TestUser user) + public Task GetTwoFactorEnabled(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(false); } @@ -591,23 +670,23 @@ namespace Microsoft.AspNet.Identity.Test private class NoOpTokenProvider : IUserTokenProvider { - public Task Generate(string purpose, UserManager manager, TestUser user) + public Task Generate(string purpose, UserManager manager, TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult("Test"); } public Task Validate(string purpose, string token, UserManager manager, - TestUser user) + TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(true); } - public Task Notify(string token, UserManager manager, TestUser user) + public Task Notify(string token, UserManager manager, TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(0); } - public Task IsValidProviderForUser(UserManager manager, TestUser user) + public Task IsValidProviderForUser(UserManager manager, TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(true); } @@ -622,97 +701,97 @@ namespace Microsoft.AspNet.Identity.Test IUserLockoutStore, IUserTwoFactorStore { - public Task> GetClaims(TestUser user) + public Task> GetClaims(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task AddClaim(TestUser user, Claim claim) + public Task AddClaim(TestUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task RemoveClaim(TestUser user, Claim claim) + public Task RemoveClaim(TestUser user, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task SetEmail(TestUser user, string email) + public Task SetEmail(TestUser user, string email, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetEmail(TestUser user) + public Task GetEmail(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetEmailConfirmed(TestUser user) + public Task GetEmailConfirmed(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task SetEmailConfirmed(TestUser user, bool confirmed) + public Task SetEmailConfirmed(TestUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task FindByEmail(string email) + public Task FindByEmail(string email, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetLockoutEndDate(TestUser user) + public Task GetLockoutEndDate(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task SetLockoutEndDate(TestUser user, DateTimeOffset lockoutEnd) + public Task SetLockoutEndDate(TestUser user, DateTimeOffset lockoutEnd, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task IncrementAccessFailedCount(TestUser user) + public Task IncrementAccessFailedCount(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task ResetAccessFailedCount(TestUser user) + public Task ResetAccessFailedCount(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetAccessFailedCount(TestUser user) + public Task GetAccessFailedCount(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetLockoutEnabled(TestUser user) + public Task GetLockoutEnabled(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task SetLockoutEnabled(TestUser user, bool enabled) + public Task SetLockoutEnabled(TestUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task AddLogin(TestUser user, UserLoginInfo login) + public Task AddLogin(TestUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task RemoveLogin(TestUser user, UserLoginInfo login) + public Task RemoveLogin(TestUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task> GetLogins(TestUser user) + public Task> GetLogins(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task Find(UserLoginInfo login) + public Task Find(UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } @@ -722,72 +801,72 @@ namespace Microsoft.AspNet.Identity.Test throw new NotImplementedException(); } - public Task Create(TestUser user) + public Task Create(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task Update(TestUser user) + public Task Update(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task Delete(TestUser user) + public Task Delete(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task FindById(string userId) + public Task FindById(string userId, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task FindByName(string userName) + public Task FindByName(string userName, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task SetPasswordHash(TestUser user, string passwordHash) + public Task SetPasswordHash(TestUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetPasswordHash(TestUser user) + public Task GetPasswordHash(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task HasPassword(TestUser user) + public Task HasPassword(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task SetPhoneNumber(TestUser user, string phoneNumber) + public Task SetPhoneNumber(TestUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetPhoneNumber(TestUser user) + public Task GetPhoneNumber(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetPhoneNumberConfirmed(TestUser user) + public Task GetPhoneNumberConfirmed(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task SetPhoneNumberConfirmed(TestUser user, bool confirmed) + public Task SetPhoneNumberConfirmed(TestUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task SetTwoFactorEnabled(TestUser user, bool enabled) + public Task SetTwoFactorEnabled(TestUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task GetTwoFactorEnabled(TestUser user) + public Task GetTwoFactorEnabled(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } diff --git a/test/Microsoft.AspNet.Identity.Test/packages.config b/test/Microsoft.AspNet.Identity.Test/packages.config new file mode 100644 index 0000000000..a8ecd228e5 --- /dev/null +++ b/test/Microsoft.AspNet.Identity.Test/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file