public async Task <IActionResult> RegisterUser(RegisterUserViewModel model) { if (ModelState.IsValid) { // create user + claims var userToCreate = new QuantusUser(); userToCreate.Id = Guid.NewGuid(); userToCreate.Password = model.Password; userToCreate.UserName = model.Username; userToCreate.IsActive = true; userToCreate.Claims.Add(new QuantusUserClaim() { UserId = userToCreate.Id, ClaimType = "country", ClaimValue = model.Country }); userToCreate.Claims.Add(new QuantusUserClaim() { UserId = userToCreate.Id, ClaimType = "address", ClaimValue = model.Address }); userToCreate.Claims.Add(new QuantusUserClaim() { UserId = userToCreate.Id, ClaimType = "given_name", ClaimValue = model.Firstname }); userToCreate.Claims.Add(new QuantusUserClaim() { UserId = userToCreate.Id, ClaimType = "family_name", ClaimValue = model.Lastname }); userToCreate.Claims.Add(new QuantusUserClaim() { UserId = userToCreate.Id, ClaimType = "email", ClaimValue = model.Email }); userToCreate.Claims.Add(new QuantusUserClaim() { UserId = userToCreate.Id, ClaimType = "subscriptionlevel", ClaimValue = "FreeUser" }); // if we're provisioning a user via external login, we must add the provider & // user id at the provider to this user's logins if (model.IsProvisioningFromExternal) { userToCreate.Logins.Add(new QuantusUserLogin() { LoginProvider = model.Provider, ProviderKey = model.ProviderUserId, UserId = userToCreate.Id }); } // add it through the repository _quantusUserRepository.AddUser(userToCreate); if (!_quantusUserRepository.Save()) { throw new Exception($"Creating a user failed."); } if (!model.IsProvisioningFromExternal) { // log the user in //await HttpContext.Authentication.SignInAsync(userToCreate.SubjectId, userToCreate.Username); await _httpContextAccssor.HttpContext.SignInAsync(userToCreate.Id.ToString(), userToCreate.UserName); } // continue with the flow if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl)) { return(Redirect(model.ReturnUrl)); } return(Redirect("~/")); } // ModelState invalid, return the view with the passed-in model // so changes can be made return(View(model)); }
public async Task <IActionResult> ExternalLoginCallback() { // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync( IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } // lookup our user and external provider info //var (user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); if (user == null) { // user wasn't found by provider, but maybe one exists with the same email address? if (provider == "Facebook") { // email claim from Facebook var email = claims.FirstOrDefault(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"); if (email != null) { var userByEmail = _quantusUserRepository.GetUserByEmail(email.Value); if (userByEmail != null) { // add Facebook as a provider for this user _quantusUserRepository.AddUserLogin(userByEmail.Id, provider, providerUserId); if (!_quantusUserRepository.Save()) { throw new Exception($"Adding a login for a user failed."); } // redirect to ExternalLoginCallback var continueWithUrlAfterAddingUserLogin = Url.Action("ExternalLoginCallback"); return(Redirect(continueWithUrlAfterAddingUserLogin)); } else { var registerModel = new RegisterUserViewModel() { Username = email.Value, Password = Guid.NewGuid().ToString(), Firstname = claims.FirstOrDefault(f => f.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname").Value, Lastname = claims.FirstOrDefault(f => f.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname").Value, Email = email.Value, Provider = provider, ProviderUserId = providerUserId, ReturnUrl = Url.Action("ExternalLoginCallback") }; // TODO: THIS MUST BE TRANSFERRED COVERTLY // redirect to ExternalLoginCallback var continueWithUrlAfterAddingUserLogin = Url.Action("RegisterUserProvisioningFromExternal", "UserRegistration", registerModel); return(Redirect(continueWithUrlAfterAddingUserLogin)); } } else { throw new ArgumentNullException($"Email from identity provider is null or could not be parsed"); } } else { //// this might be where you might initiate a custom workflow for user registration //// in this sample we don't show how that would be done, as our sample implementation //// simply auto-provisions new external user //user = AutoProvisionUser(provider, providerUserId, claims); //var returnUrlAfterRegistration = // Url.Action("ExternalLoginCallback"/*, new {returnUrl = "not need since this identity sever version!"}*/); // Not like in course! var continueWithUrl = Url.Action("RegisterUser", "UserRegistration", new { /*returnUrl = returnUrlAfterRegistration,*/ provider = provider, providerUserId = providerUserId }); // Not like in course! return(Redirect(continueWithUrl)); } } // this allows us to collect any additonal claims or properties // for the specific prtotocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. var additionalLocalClaims = new List <Claim>(); var localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps); ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), user.UserName)); await HttpContext.SignInAsync(user.Id.ToString(), user.UserName, provider, localSignInProps, additionalLocalClaims.ToArray()); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme); // validate return URL and redirect back to authorization endpoint or a local page var returnUrl = result.Properties.Items["returnUrl"]; if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl)) { return(Redirect(returnUrl)); } return(Redirect("~/")); }