private async Task <bool> VerifyMembership(ExternalLoginCode codeRow, ExternalLoginInfo info, ExternalVerifyViewModel model) { if (codeRow == null) { AddErrors(IdentityResult.Failed(new IdentityError { Code = "NoMembershipCode", Description = "Invalid or unknown code." })); return(false); } if (string.Compare(codeRow.Code, model.Code, true) != 0) { AddErrors(IdentityResult.Failed(new IdentityError { Code = "MembershipCodeInvalid", Description = "Invalid or unknown code." })); return(false); } if (codeRow.ExpiresUtc < DateTime.UtcNow) { AddErrors(IdentityResult.Failed(new IdentityError { Code = "MembershipCodeExpired", Description = "Code is expired." })); return(false); } var member = await remoteMembers.GetMember(codeRow.MemberId); if (member == null) { AddErrors(IdentityResult.Failed(new IdentityError { Code = "MembershipCodeInvalid", Description = "Invalid or unknown code." })); return(false); } IdentityResult result; var user = await users.FindByMemberId(member.Id); if (user == null) { string nameSpacer = (string.IsNullOrEmpty(member.LastName) || string.IsNullOrEmpty(member.FirstName)) ? string.Empty : " "; user = new ApplicationUser { UserName = $"@{member.Id}-{info.LoginProvider}", Email = member.PrimaryEmail, MemberId = member.Id, PhoneNumber = member.PrimaryPhone, FirstName = member.FirstName, LastName = member.LastName, Created = DateTimeOffset.UtcNow }; result = await users.CreateAsync(user); if (!result.Succeeded) { AddErrors(result); return(false); } logger.LogInformation($"User created for {member.FirstName} {member.LastName}. Will link to {info.ProviderDisplayName} login."); } info.ProviderDisplayName += " - " + (info.Principal.FindFirstValue(ClaimTypes.Email) ?? "unknown"); result = await users.AddLoginAsync(user, info); if (!result.Succeeded) { AddErrors(result); return(false); } await signin.SignInAsync(user, isPersistent : false); logger.LogInformation($"Associated {info.ProviderDisplayName} login with account {user.Id} ({user.UserName} {user.Email})"); return(true); }
public async Task <IActionResult> ExternalLoginConfirmation(ExternalLoginViewModel model, string returnUrl = null) { ViewData["ReturnUrl"] = returnUrl; if (ModelState.IsValid) { // Get the information about the user from the external login provider var info = await signin.GetExternalLoginInfoAsync(); if (info == null) { throw new ApplicationException("Error loading external login information during confirmation."); } ViewData["LoginProvider"] = info.LoginProvider; IdentityResult result; List <RemoteMember> members = new List <RemoteMember>(); bool foundPhone = false; if (!string.IsNullOrWhiteSpace(model.Phone)) { members = await remoteMembers.FindByPhone(model.Phone); } if (members.Count == 1) { foundPhone = true; } else if (!string.IsNullOrWhiteSpace(model.Email)) { members = await remoteMembers.FindByEmail(model.Email); } if (members.Count != 1) { result = IdentityResult.Failed(new IdentityError { Code = "NotMemberEmail", Description = "Unable to find member." }); } else { var codeRow = await db.ExternalLoginCodes.FindAsync(info.ProviderKey); if (codeRow == null) { codeRow = new ExternalLoginCode { LoginSubject = info.ProviderKey }; db.ExternalLoginCodes.Add(codeRow); } codeRow.MemberId = members[0].Id; codeRow.ExpiresUtc = DateTime.UtcNow.AddMinutes(10); codeRow.Code = new Random().Next(1000000).ToString("000000"); await db.SaveChangesAsync(); if (foundPhone) { await messaging.SendText(model.Phone, "Your verification code: " + codeRow.Code); } else { await messaging.SendEmail(model.Email, "Verification Code", "Your verificaton code: " + codeRow.Code); } return(View("ExternalVerify")); } AddErrors(result); } return(View(nameof(ExternalLogin), model)); }