asp.net核心身份提取并保存外部登录令牌并将声明添加到本地身份

问题描述:

我是一个* noob,所以如果我这样做错了,请尽量轻松。asp.net核心身份提取并保存外部登录令牌并将声明添加到本地身份

我使用默认的核心身份模板(本地帐户)的asp.net核心。

我已经accertained如何索赔添加到用户主体时,他们在本地登录,像这样

[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中,而不管用户如何登录(本地或外部),以及如何在需要时将这些声明持久保存到数据库。

我打算做一些工作,如果我有一个用户登录使用说谷歌认证,我需要从谷歌保存access_token,因为我希望随后调用Google API。所以我需要能够将这个access_token包含在创建的用户主体中,并且我希望cookie可以在前端使用它。

这可能超出了这个问题的范围,但我也想当谷歌令牌到期,对于某些 - 如何使用刷新令牌并去获取新的令牌,或强制用户重新登录。

对此的任何帮助将超级赞赏,我真的很努力去理解这个没有发布这个问题到*。我阅读了很多有用信息的文章,但没有提供这个具体问题所要求的答案。所以非常感谢你提前。

欢呼

当您使用await _userManager.AddClaimAsync(user, new Claim("your-claim", "your-value"));实际更新标识的aspnetuserclaims表。

无论您何时登录(通过使用_signInManager.PasswordSignIn或_signInManager.ExternalLoginSignInAsync),都会读取该表中的声明并将其添加到每个请求成为主体的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控制。

这是为您完成的,当您使用_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); 

“Identity.Application” 是默认的cookie名称。您可以在启动的ConfigureServices方法改变它,例如MainCookie:

 services.Configure<IdentityOptions>(options => { 
      options.Cookies.ApplicationCookie.AuthenticationScheme = "MainCookie"; 
     }); 

你仍然需要以处理的AccountController的ExternalCallbackConfirmation行动。它将与上面的示例类似。