Как войти в систему с внешними провайдерами на поддоменах? - PullRequest
0 голосов
/ 03 июня 2019

Я написал приложение Asp Net Core с поддоменами и аутентификацией OAuth. Теперь Oauth работает только на основном домене example.com, а не на поддоменах.

Я уже кое-что прочитал о двух вариантах.

  1. «Зарегистрировать каждый субдомен независимо у Провайдера». Это на самом деле не вариант, потому что я использую субдомены с подстановочными знаками, так что это может привести к регистрации более 1 нового субдомена каждый день.

  2. "Предоставить одну конечную точку обработки OAuth2 для всех поддоменов". Я пытался создать одну конечную точку, но не могу заставить ее работать, потому что вызов начинается с субдомена, и я не могу перенаправить его в основной домен.

Вот 2 наиболее важных метода из моего класса ExternalLogin.cshtml.cs.

public IActionResult OnPost(string provider, string returnUrl = null)
        {
            // Request a redirect to the external login provider.
            var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
            var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
            return new ChallengeResult(provider, properties);
        }

        public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");
            if (remoteError != null)
            {
                ErrorMessage = $"Error from external provider: {remoteError}";
                return RedirectToPage("./Login", new {ReturnUrl = returnUrl });
            }
            var info = await _signInManager.GetExternalLoginInfoAsync();
            if (info == null)
            {
                ErrorMessage = "Error loading external login information.";
                return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
            }

            // Sign in the user with this external login provider if the user already has a login.
            var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor : true);
            if (result.Succeeded)
            {
                _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
                return LocalRedirect(returnUrl);
            }
            if (result.IsLockedOut)
            {
                return RedirectToPage("./Lockout");
            }
            else
            {
                // If the user does not have an account, create an account.
                var email = info.Principal.FindFirst(ClaimTypes.Email).Value;
                var firstName =
                    info.Principal.FindFirst(ClaimTypes.GivenName).Value[0].ToString().ToUpper() +
                    info.Principal.FindFirst(ClaimTypes.GivenName).Value.Substring(1).ToLower();

                var lastName =
                    info.Principal.FindFirst(ClaimTypes.Surname).Value[0].ToString().ToUpper() +
                    info.Principal.FindFirst(ClaimTypes.Surname).Value.Substring(1).ToLower();

                if (email == null)
                {
                    LoginProvider = info.LoginProvider;
                    ErrorMessage = "No email registered on your " + LoginProvider + "account";
                    return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
                }

                // Ask firstname and last name if the user does not have an firstname or lastname
                if (firstName == String.Empty | lastName == String.Empty)
                {
                    ReturnUrl = returnUrl;
                    LoginProvider = info.LoginProvider;
                    if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Name))
                    {
                        Input = new InputModel
                        {
                            FirstName = info.Principal.FindFirst(ClaimTypes.Name).ToString().Split(" ")[1][0].ToString().ToUpper() + info.Principal.FindFirst(ClaimTypes.Name).ToString().Split(" ")[1].Substring(1).ToLower(),
                            LastName = info.Principal.FindFirst(ClaimTypes.Name).ToString().Split(" ")[2][0].ToString().ToUpper() + info.Principal.FindFirst(ClaimTypes.Name).ToString().Split(" ")[2].Substring(1).ToLower() 
                        };
                    }
                    return Page();
                }

                // If the user does not have an account, then create an account.
                returnUrl = returnUrl ?? Url.Content("~/");

                // Get the information about the user from the external login provider
                var loginInfo = await _signInManager.GetExternalLoginInfoAsync();
                if (loginInfo == null)
                {
                    ErrorMessage = "Error loading external login information during confirmation.";
                    return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
                }

                if (ModelState.IsValid)
                {
                    var userName =  firstName + "_" + lastName;
                    var countUser = _userManager.Users.Where(c => c.UserName.Contains(userName)).Count();

                    if (countUser > 0)
                    {
                        userName = userName + countUser;
                    }    

                    var user = new User { UserName = userName , Email = email, FirstName = firstName, LastName = lastName, EmailConfirmed = true};
                    var createUserResult = await _userManager.CreateAsync(user);
                    if (createUserResult.Succeeded)
                    {
                        await _userManager.AddClaimAsync(user, new Claim("User", "User"));
                        createUserResult = await _userManager.AddLoginAsync(user, info);
                        if (createUserResult.Succeeded)
                        {
                            await _signInManager.SignInAsync(user, isPersistent: false);
                            _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
                            return LocalRedirect(returnUrl);
                        }
                    }
                    foreach (var error in createUserResult.Errors)
                    {
//                        ModelState.AddModelError(string.Empty, error.Description);
                        ErrorMessage = error.Description;
                    }
                }

                LoginProvider = info.LoginProvider;
                ReturnUrl = returnUrl;
                return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
            }
        }

Я хотел бы аутентифицировать пользователя на 1 поддомене, а не на 1 учетной записи для всех доменов. Таким образом, должна быть возможность войти на subdomain1.example.com с Facebook и на subdomain2.exaple.com с Google или даже с локальной учетной записью.

...