asp.net核心身份提取并保存外部登录令牌,并向本地身份添加声明 [英] asp.net core identity extract and save external login tokens and add claims to local identity

查看:146
本文介绍了asp.net核心身份提取并保存外部登录令牌,并向本地身份添加声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个stackoverflow菜鸟,所以如果我做错了,请放轻松.

I am a stackoverflow noob so please go easy if I am doing this wrong.

我正在将asp.net core和默认的核心标识模板(本地帐户)一起使用.

I am using asp.net core with the default core identity template (local accounts).

我已经了解了如何在用户本地登录时向用户主体添加声明

I have accertained how to add claims to user principal when they login locally like so

[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函数中创建用户主体之前添加这些声明

And I have figured out how to get claims returned from the external login but I cannot figure out how I would add these before the user principal gets created in the ExternalLoginCallback function

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.但我不确定.

I am assuming the the _signInManager.ExternalLoginSignInAsync function works similar to the local login _signInManager.PasswordSignInAsync in the sense that once it is called, the cookie will be created. But I am just not sure.

从本质上说,我希望了解如何将自定义声明添加到创建的cookie中,而不管用户如何登录(本地或外部),以及如何在需要时将这些声明持久化到数据库中.

Essentially what I am hoping to achieve, is understanding of how to add custom claims into the cookie that gets created regardless of how to user logins in (local or external), and how to persist these claims to the database if required.

我正计划做一些工作,如果我使用say google auth登录用户,则需要从Google保存该access_token,因为我希望以后使用它调用Google API.因此,我需要能够将这个access_token包含在创建的User Principal中,并且希望cookie对此也可以有一个要求,我也可以在前端使用它.

I am planning on doing some work where if I have a user login using say google auth, I need to save that access_token from google, because I wish to call into the Google APIs later with it. So I need to be able to include this access_token in with the User Principal that gets created, and I would hope the cookie would have a claim on it I could use at the front end as well.

这个问题可能超出范围,但是我也想在Google令牌过期时,以某种方式使用刷新令牌并获得新的令牌,或者强制用户重新登录.

This might be out of scope on this question but I would also like when the google token expires, for some-how it to use the refresh token and go get a new one, or force the user to relogin.

任何对此的帮助将不胜感激,我真的很努力地理解了这一点,而没有将这个问题发布到stackoverflow上.我已经阅读了许多文章,其中包含许多有用的信息,但没有提供此特定问题所要回答的答案.因此,非常感谢.

Any help on this would be super appreciated, I have really tried hard to understand this without posting this question to stackoverflow. I have read many articles with lots of useful info, but does not provide the answers this specific question is asking. So Thank you very much in advance.

欢呼

推荐答案

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

When you use await _userManager.AddClaimAsync(user, new Claim("your-claim", "your-value")); that actually updates the Identity's aspnetuserclaims table.

无论何时登录(通过使用_signInManager.PasswordSignIn或_signInManager.ExternalLoginSignInAsync),该表中的声明都会被读取并添加到cookie中,该cookie在每次请求时都成为Principal.

Whenever you sign in (by using _signInManager.PasswordSignIn or _signInManager.ExternalLoginSignInAsync) the claims from that table are read and added to the cookie that on every request becomes the Principal.

因此,您可能不想在每次登录时都从UserManager调用AddClaimAsync方法.

So you probably don't want to be calling the AddClaimAsync method from UserManager on every login.

关于外部登录提供程序,您可以在调用时访问声明(如果使用的是默认模板,则可以在ExternalCallback和ExternalCallbackConfirmation中):

Regarding external login providers, you have access to the claims when you call (in ExternalCallback and ExternalCallbackConfirmation if you are using the default templates) here:

var info = await _signInManager.GetExternalLoginInfoAsync();

声明在info.Principal.Claims中.

默认情况下不包括访问令牌.如果是,它将在这里(以及类型和有效期):

The access token is not included by default. When it is, it will be here (along with the type and expiry date):

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:

To have the access token be included in the AuthenticationTokens collection, when you are configuring the GoogleAuthentication middleware set the SaveTokens flag to true:

        app.UseGoogleAuthentication(new GoogleOptions{
            ClientId = "...",
            ClientSecret = "...",
            SaveTokens = true

现在,如果要控制cookie中的哪些索赔,则必须接管"创建索赔主体的过程.

Now, if you want to have control over which claims go in the cookie you have to "take over" the process of creating the claims principal.

当您使用_signInManager.PasswordSignIn/ExternalLoginSignInAsync时,将为您完成此操作.

This is done for you when you use _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名称.您可以在Startup的ConfigureServices方法中将其更改,例如更改为MainCookie:

"Identity.Application" is the default cookie name. You can change it in Startup's ConfigureServices method, for example to MainCookie:

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

您仍然需要在AccountController中处理ExternalCallbackConfirmation操作.它将与上面的示例相似.

You still need to handle the ExternalCallbackConfirmation action in the AccountController. It will be similar to the example above.

这篇关于asp.net核心身份提取并保存外部登录令牌,并向本地身份添加声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆