我是一个stackoverflow noob,所以如果我做错了,请放轻松。
我正在使用带有默认核心身份模板(本地帐户)的asp.net核心。
我已经接受了如何在本地登录时向用户主体添加声明
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model)
{
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var user = await _userManager.FindByNameAsync(model.Email);
await _userManager.AddClaimAsync(user, new Claim("your-claim", "your-value"));
我已经弄清楚如何从外部登录返回索赔但我无法弄清楚如何在ExternalLoginCallback函数中创建用户主体之前添加这些索引
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
return View(nameof(Login));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(Login));
}
else {
// extract claims from external token here
}
// assume add claims to user here before cookie gets created??
// 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);
if (result.Succeeded)
我假设_signInManager.ExternalLoginSignInAsync函数的工作方式类似于本地登录_signInManager.PasswordSignInAsync,因为一旦调用它,就会创建cookie。但我只是不确定。
基本上我希望实现的是理解如何将自定义声明添加到创建的cookie中,无论用户如何登录(本地或外部),以及如何在需要时将这些声明持久保存到数据库中。
我打算做一些工作,如果我使用google auth进行用户登录,我需要从google保存该access_token,因为我希望稍后使用它来调用Google API。所以我需要能够将这个access_token包含在创建的用户主体中,我希望cookie能够在前端使用它。
这可能超出了这个问题的范围,但我还想在谷歌令牌到期时,对于某些人 - 如何使用刷新令牌并获取新的令牌,或强制用户重新登录。
任何有关这方面的帮助都会非常感激,我真的很难理解这一点而不将此问题发布到stackoverflow。我已经阅读了很多有用信息的文章,但没有提供这个具体问题所要求的答案。非常感谢您提前。
欢呼声
答案 0 :(得分:8)
当您使用实际更新Identity的aspnetuserclaims表的await _userManager.AddClaimAsync(user, new Claim("your-claim", "your-value"));
时。
每当您登录时(通过使用_signInManager.PasswordSignIn或_signInManager.ExternalLoginSignInAsync),都会读取该表中的声明,并将其添加到每个请求都成为Principal的Cookie中。
因此,您可能不希望在每次登录时都从UserManager调用AddClaimAsync方法。
关于外部登录提供程序,您可以在此处访问声明(如果使用默认模板,则在ExternalCallback和ExternalCallbackConfirmation中):
var info = await _signInManager.GetExternalLoginInfoAsync();
声明属于info.Principal.Claims
。
默认情况下不包含访问令牌。如果是,它将在这里(连同类型和到期日期):
var accessToken = info.AuthenticationTokens.Single(f => f.Name == "access_token").Value;
var tokenType = info.AuthenticationTokens.Single(f => f.Name == "token_type").Value;
var expiryDate = info.AuthenticationTokens.Single(f => f.Name == "expires_at").Value;
要将访问令牌包含在AuthenticationTokens
集合中,在配置GoogleAuthentication中间件时,请将SaveTokens标志设置为true:
app.UseGoogleAuthentication(new GoogleOptions{
ClientId = "...",
ClientSecret = "...",
SaveTokens = true
现在,如果您想要控制cookie中的哪些声明,您必须接管&#34;创建索赔主体的过程。
使用_signInManager.PasswordSignIn/ExternalLoginSignInAsync
时,您就可以完成此操作。
因此,例如,对于ExternalLoginSignInAsync
替换:
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
使用:
var user = await this._userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
var claimsPrincipal = await this._signInManager.CreateUserPrincipalAsync(user);
((ClaimsIdentity)claimsPrincipal.Identity).AddClaim(new Claim("accessToken", info.AuthenticationTokens.Single(t => t.Name == "access_token").Value));
await HttpContext.Authentication.SignInAsync("Identity.Application", claimsPrincipal);
&#34; Identity.Application&#34;是默认的cookie名称。您可以在初创公司的ConfigureServices
方法中进行更改,例如更改为MainCookie:
services.Configure<IdentityOptions>(options => {
options.Cookies.ApplicationCookie.AuthenticationScheme = "MainCookie";
});
您仍需要处理AccountController中的ExternalCallbackConfirmation
操作。它将类似于上面的例子。