通过 openid 提供商在 ASP.NET Core 2.0 中授权
Authorization in ASP.NET Core 2.0 via openid provider
我在将声明从外部身份传递给本地身份时遇到问题。该应用程序基本上是添加了 openid 身份提供程序的 QuickBooksASPNetCore2 Demo。除了
之外,一切都可以正常工作
[Authorize(Role = "some_role")]
在测试 Razer 页面上。
这是执行登录逻辑的代码,
_signInManager.GetExternalLoginInfoAsync();
return 身份提供者的所有声明的主体(包括“http://schemas.microsoft.com/ws/2008/06/identity/claims/role”类型下的角色)。
dump of info var with claims
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Login");
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToPage("./Login");
}
// 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: true, bypassTwoFactor : true);
if (result.Succeeded)
{
_logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
return LocalRedirect(Url.GetLocalUrl(returnUrl));
}
if (result.IsLockedOut)
{
return RedirectToPage("./Lockout");
}
else
{
// If the user does not have an account, then ask the user to create an account.
ReturnUrl = returnUrl;
LoginProvider = info.LoginProvider;
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
{
Input = new InputModel
{
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
}
return Page();
}
}
但是当此方法退出时,Razor 页面上的 User.Claims 没有角色声明。它甚至获得了新的“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”声明(具有不同的 ID)。我在这里错过了什么吗?
因此,如果有人遇到此问题,您需要将声明从外部身份映射到本地应用程序身份。
这意味着替换行
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: true, bypassTwoFactor : true);
和
var user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
var claimsPrincipal = await this._signInManager.CreateUserPrincipalAsync(user);
((ClaimsIdentity)claimsPrincipal.Identity).AddClaims(info.Principal.Claims.Where(c => c.Type == ClaimTypes.Role));
await HttpContext.SignInAsync("Identity.Application", claimsPrincipal);
您在应用程序中需要的所有声明,您需要使用来自外部身份的 AddClaim(s) 方法手动映射。
我在将声明从外部身份传递给本地身份时遇到问题。该应用程序基本上是添加了 openid 身份提供程序的 QuickBooksASPNetCore2 Demo。除了
之外,一切都可以正常工作[Authorize(Role = "some_role")]
在测试 Razer 页面上。
这是执行登录逻辑的代码,
_signInManager.GetExternalLoginInfoAsync();
return 身份提供者的所有声明的主体(包括“http://schemas.microsoft.com/ws/2008/06/identity/claims/role”类型下的角色)。
dump of info var with claims
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Login");
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToPage("./Login");
}
// 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: true, bypassTwoFactor : true);
if (result.Succeeded)
{
_logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
return LocalRedirect(Url.GetLocalUrl(returnUrl));
}
if (result.IsLockedOut)
{
return RedirectToPage("./Lockout");
}
else
{
// If the user does not have an account, then ask the user to create an account.
ReturnUrl = returnUrl;
LoginProvider = info.LoginProvider;
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
{
Input = new InputModel
{
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
}
return Page();
}
}
但是当此方法退出时,Razor 页面上的 User.Claims 没有角色声明。它甚至获得了新的“http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”声明(具有不同的 ID)。我在这里错过了什么吗?
因此,如果有人遇到此问题,您需要将声明从外部身份映射到本地应用程序身份。
这意味着替换行
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: true, bypassTwoFactor : true);
和
var user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
var claimsPrincipal = await this._signInManager.CreateUserPrincipalAsync(user);
((ClaimsIdentity)claimsPrincipal.Identity).AddClaims(info.Principal.Claims.Where(c => c.Type == ClaimTypes.Role));
await HttpContext.SignInAsync("Identity.Application", claimsPrincipal);
您在应用程序中需要的所有声明,您需要使用来自外部身份的 AddClaim(s) 方法手动映射。