public virtual async Task <UserLoginResult> TryLogin(LoginViewModel model) { var template = new LoginResultTemplate(); IUserContext userContext = null; LdapUser ldapUser = null; var isFakeLdapEmail = false; if (UserManager.Site.UseEmailForLogin && !string.IsNullOrWhiteSpace(model.UserName) && model.UserName.IndexOf("@") > -1) { template.User = await UserManager.FindByEmailAsync(model.UserName); } if (template.User == null) { template.User = await UserManager.FindByNameAsync(model.UserName); } if (template.User == null || string.IsNullOrWhiteSpace(template.User.PasswordHash)) //no password on cloudscribe user so could be ldap { if (LdapHelper.IsImplemented && !string.IsNullOrWhiteSpace(UserManager.Site.LdapServer) && !string.IsNullOrWhiteSpace(UserManager.Site.LdapDomain)) { ldapUser = await LdapHelper.TryLdapLogin(UserManager.Site as ILdapSettings, model.UserName, model.Password); } } if (ldapUser != null) //ldap auth success { if (template.User == null) { //ldap auth success but no siteuser exists so create one and sign in var cloudscribeUser = new SiteUser() { SiteId = UserManager.Site.Id, UserName = model.UserName, Email = ldapUser.Email, DisplayName = ldapUser.CommonName, FirstName = ldapUser.FirstName, LastName = ldapUser.LastName, LastLoginUtc = DateTime.UtcNow, AccountApproved = true }; if (string.IsNullOrWhiteSpace(cloudscribeUser.DisplayName)) { cloudscribeUser.DisplayName = model.UserName; } if (string.IsNullOrWhiteSpace(cloudscribeUser.Email)) { // identity doesn't allow create user with no email so fake it here then null it out below after sign in. // the cloudscribe site rules middleware will then force the user to provide an email cloudscribeUser.Email = model.UserName + "@fake-email.com"; isFakeLdapEmail = true; } var createdResult = await UserManager.CreateAsync(cloudscribeUser); if (createdResult.Succeeded) { template.User = cloudscribeUser; await SignInManager.SignInAsync(cloudscribeUser, model.RememberMe); template.SignInResult = SignInResult.Success; if (isFakeLdapEmail) { // clear the fake email, the user should then be forced to provide an email by site rules middleware cloudscribeUser.Email = null; cloudscribeUser.NormalizedEmail = null; await UserCommands.Update(cloudscribeUser); } } } else { //siteuser already created for ldap user so just sign in await SignInManager.SignInAsync(template.User, model.RememberMe); template.SignInResult = SignInResult.Success; } } if (template.User != null && ldapUser == null) //these rules don't apply for ldap users { await LoginRulesProcessor.ProcessAccountLoginRules(template); } if (template.User != null) { //this will get persisted if login succeeds template.User.BrowserKey = Guid.NewGuid().ToString(); userContext = new UserContext(template.User); } if (userContext != null && template.SignInResult == SignInResult.Failed && template.RejectReasons.Count == 0) { var persistent = false; if (UserManager.Site.AllowPersistentLogin) { persistent = model.RememberMe; } //template.SignInResult = await SignInManager.PasswordSignInAsync( // model.UserName, // model.Password, // persistent, // lockoutOnFailure: false); template.SignInResult = await SignInManager.PasswordSignInAsync( template.User, model.Password, persistent, lockoutOnFailure : false); if (template.SignInResult.Succeeded) { //update last login time template.User.LastLoginUtc = DateTime.UtcNow; if (string.IsNullOrEmpty(template.User.SecurityStamp)) { // if security stamp is empty then the securitystamp validation // fails when it checks after 30 minutes // users created via usermanager this gets populated but not // populated for the admin user created by seeding data // changes to the user such as password change also will populate it // but we can go ahead and check here and populate it if it is empty await UserManager.UpdateSecurityStampAsync(template.User); if (template.User.PasswordHash == "admin||0") { // initial admin user has not updated the password, need to hash it await UserManager.ChangeUserPassword(template.User, "admin", validatePassword : false); await SignInManager.SignOutAsync(); // security stamp needs to be there before authentication to avoid the problem template.SignInResult = await SignInManager.PasswordSignInAsync( model.UserName, model.Password, persistent, lockoutOnFailure : false); } } else { await UserManager.UpdateAsync(template.User); } } } return(new UserLoginResult( template.SignInResult, template.RejectReasons, userContext, template.IsNewUserRegistration, template.MustAcceptTerms, template.NeedsAccountApproval, template.NeedsEmailConfirmation, template.EmailConfirmationToken, template.NeedsPhoneConfirmation )); }