Я написал приложение Asp Net Core с поддоменами и аутентификацией OAuth. Теперь Oauth работает только на основном домене example.com, а не на поддоменах.
Я уже кое-что прочитал о двух вариантах.
«Зарегистрировать каждый субдомен независимо у Провайдера». Это на самом деле не вариант, потому что я использую субдомены с подстановочными знаками, так что это может привести к регистрации более 1 нового субдомена каждый день.
"Предоставить одну конечную точку обработки 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 или даже с локальной учетной записью.