예제 #1
0
        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));
        }
예제 #2
0
        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("~/"));
        }