public async Task <IActionResult> RegisterUser(RegisterUserViewModel model) { if (ModelState.IsValid) { // create user + claims var userToCreate = new Entities.User { Password = model.Password, Username = model.Username, IsActive = true }; userToCreate.Claims.Add(new Entities.UserClaim("country", model.Country)); userToCreate.Claims.Add(new Entities.UserClaim("address", model.Address)); userToCreate.Claims.Add(new Entities.UserClaim("given_name", model.Firstname)); userToCreate.Claims.Add(new Entities.UserClaim("family_name", model.Lastname)); userToCreate.Claims.Add(new Entities.UserClaim("email", model.Email)); userToCreate.Claims.Add(new Entities.UserClaim("subscriptionlevel", "PaidUser")); userToCreate.Claims.Add(new Entities.UserClaim(ClaimTypes.Role, "PaidUser")); // 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 Entities.UserLogin() { LoginProvider = model.Provider, ProviderKey = model.ProviderUserId }); } // add it through the repository _marvinUserRepository.AddUser(userToCreate); if (!_marvinUserRepository.Save()) { throw new Exception($"Creating a user failed."); } if (!model.IsProvisioningFromExternal) { AuthenticationProperties props = null; await HttpContext.SignInAsync(userToCreate.SubjectId, userToCreate.Username, props); } // continue with the flow if (_identityInteractionService.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> RegisterUser(RegisterUserViewModel model) { if (ModelState.IsValid) { // create user + claims var userToCreate = new Entities.User(); userToCreate.Password = model.Password; userToCreate.Username = model.Username; userToCreate.IsActive = true; userToCreate.Claims.Add(new Entities.UserClaim("country", model.Country)); userToCreate.Claims.Add(new Entities.UserClaim("address", model.Address)); userToCreate.Claims.Add(new Entities.UserClaim("given_name", model.Firstname)); userToCreate.Claims.Add(new Entities.UserClaim("family_name", model.Lastname)); userToCreate.Claims.Add(new Entities.UserClaim("email", model.Email)); userToCreate.Claims.Add(new Entities.UserClaim("subscriptionlevel", "FreeUser")); // add it through the repository _marvinUserRepository.AddUser(userToCreate); if (!_marvinUserRepository.Save()) { throw new Exception($"Creating a user failed."); } // log the user in //https://github.com/aspnet/Announcements/issues/232 //await HttpContext.Authentication.SignInAsync(userToCreate.SubjectId, userToCreate.Username); await HttpContext.SignInAsync(userToCreate.SubjectId, 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(string returnUrl) { // read external identity from the temporary cookie var info = await HttpContext.Authentication.GetAuthenticateInfoAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); var tempUser = info?.Principal; if (tempUser == null) { throw new Exception("External authentication error"); } // retrieve claims of the external user var claims = tempUser.Claims.ToList(); // try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier // depending on the external provider, some other claim type might be used var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject); if (userIdClaim == null) { userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier); } if (userIdClaim == null) { throw new Exception("Unknown userid"); } // remove the user id claim from the claims collection and move to the userId property // also set the name of the external authentication provider claims.Remove(userIdClaim); var provider = info.Properties.Items["scheme"]; var userId = userIdClaim.Value; // check if the external user is already provisioned var user = _marvinUserRepository.GetUserByProvider(provider, userId); 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 = _marvinUserRepository.GetUserByEmail(email.Value); if (userByEmail != null) { // add Facebook as a provider for this user _marvinUserRepository.AddUserLogin(userByEmail.SubjectId, provider, userId); if (!_marvinUserRepository.Save()) { throw new Exception($"Adding a login for a user failed."); } // redirect to ExternalLoginCallback var continueWithUrlAfterAddingUserLogin = Url.Action("ExternalLoginCallback", new { returnUrl = returnUrl }); return(Redirect(continueWithUrlAfterAddingUserLogin)); } } } var returnUrlAfterRegistration = Url.Action("ExternalLoginCallback", new { returnUrl = returnUrl }); var continueWithUrl = Url.Action("RegisterUser", "UserRegistration", new { returnUrl = returnUrlAfterRegistration, provider = provider, providerUserId = userId }); return(Redirect(continueWithUrl)); } var additionalClaims = new List <Claim>(); // if the external system sent a session id claim, copy it over var sid = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); if (sid != null) { additionalClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); } // if the external provider issued an id_token, we'll keep it for signout AuthenticationProperties props = null; var id_token = info.Properties.GetTokenValue("id_token"); if (id_token != null) { props = new AuthenticationProperties(); props.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = id_token } }); } // issue authentication cookie for user await _events.RaiseAsync(new UserLoginSuccessEvent(provider, userId, user.SubjectId, user.Username)); await HttpContext.Authentication.SignInAsync(user.SubjectId, user.Username, provider, props, additionalClaims.ToArray()); // delete temporary cookie used during external authentication await HttpContext.Authentication.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); // validate return URL and redirect back to authorization endpoint or a local page if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl)) { return(Redirect(returnUrl)); } return(Redirect("~/")); }