简体   繁体   English

在ASP.net身份中向Asp.Net Web API 2承载令牌添加声明?

[英]Add Claims to Asp.Net Web API 2 Bearer Token in ASP.net Identity?

Is it possible to add claims to a Bearer Token in order to access those claims in the future? 是否可以将声明添加到承载令牌中,以便将来访问这些声明? This is the Bearer Token that is issued by the Web API. 这是Web API发行的Bearer令牌。 It is contained in the URL that is displayed upon redirect from the Twitter app authorization process. 它包含在从Twitter应用程序授权过程重定向后显示的URL中。

The reason I ask is that I'm trying to store the Twitter AccessToken and AccessTokenSecret as additional claims. 我问的原因是我正在尝试存储Twitter AccessToken和AccessTokenSecret作为其他声明。 I'm doing this so that I can access these claims when I access the GetUserInfo method using a Bearer Token. 我这样做是为了在使用承载令牌访问GetUserInfo方法时可以访问这些声明。 From what I can tell, this is not possible. 据我所知,这是不可能的。

It seems like I might have to store these in SQL and retrieve them using the Twitter userName when I access GetUserInfo. 似乎当我访问GetUserInfo时,可能必须将它们存储在SQL中并使用Twitter userName检索它们。 When I access GetUserInfo, I get the Twitter userName and userId, but I can't get the AccessToken and AccessTokenSecret. 当我访问GetUserInfo时,我获得了Twitter的userName和userId,但无法获得AccessToken和AccessTokenSecret。 I might be able to store the context.ScreenName, context.AccessToken and context.AccessTokenSecret in SQL using the public override Task Authenticated(TwitterAuthenticatedContext context) method. 我可以使用公共重写Task Authenticated(TwitterAuthenticatedContext context)方法在SQL中存储context.ScreenName,context.AccessToken和context.AccessTokenSecret。

I need the AccessToken and AccessTokenSecret, so I can call this Twitter endpoint to get the user's email address. 我需要AccessToken和AccessTokenSecret,因此我可以调用此Twitter端点来获取用户的电子邮件地址。

https://api.twitter.com/1.1/account/verify_credentials.json https://api.twitter.com/1.1/account/verify_credentials.json

At this stage in the process, my user is not logged in and their local account has not been created. 在此过程的此阶段,我的用户尚未登录,并且尚未创建其本地帐户。 I am attempting to get the email address from Twitter in order to create their local account. 我正在尝试从Twitter获取电子邮件地址,以创建其本地帐户。

UPDATE 1 更新1

Here is some code. 这是一些代码。 I'm calling this method from Provider in TwitterAuthenticationOptions in Startup.Auth like so. 我正在这样从Startup.Auth的TwitterAuthenticationOptions中的提供者调用此方法。 As you can see, I'm adding the claims to the context in Authenticated. 如您所见,我将声明添加到Authenticated中的上下文中。

Provider = new TwitterAuthProvider(), 

public class TwitterAuthProvider : TwitterAuthenticationProvider
{
    public string XmlSchemaString { get; private set; }

    public override Task Authenticated(TwitterAuthenticatedContext context)
    {
        context.Identity.AddClaim(new Claim("access_token", context.AccessToken, XmlSchemaString, "Twitter"));
        context.Identity.AddClaim(new Claim("access_token_secret", context.AccessTokenSecret, XmlSchemaString, "Twitter"));
        context.Identity.AddClaim(new Claim("user_name", context.ScreenName, XmlSchemaString, "Twitter"));
        context.Identity.AddClaim(new Claim("account_type", "Twitter", XmlSchemaString, "Twitter"));

        return Task.FromResult<object>(null);
    }

}

Any help is much appreciated. 任何帮助深表感谢。 Thanks in advance! 提前致谢!

You can't change tokens made by a third party. 您不能更改第三方制作的令牌。
They are signed with a private key and validated during login. 它们使用私钥签名,并在登录期间经过验证。

You could put host IdentityServer in between the Twiiter identity prodiver and your applications. 您可以将主机IdentityServer放在Twiiter身份专家和您的应用程序之间。 IdentityServer is open source OpenId and OAuth 2.0 server and allows you to dictate how tokens and claims should be handled. IdentityServer是开源的OpenId和OAuth 2.0服务器,可让您指示应如何处理令牌和声明。 But it is not a simple thing to start with. 但这并不是一件容易的事情。 All depends on how far you want to go for this solution. 一切都取决于您要为该解决方案走多远。

https://identityserver.io/ https://identityserver.io/

I can certainly recommend it! 我当然可以推荐它!

OK, I finally got this to work. 好的,我终于可以使用它了。 The key is in the ExternalLoginData method (see below). 密钥在ExternalLoginData方法中(请参见下文)。 This method gets called when the application redirects back from Twitter, Facebook etc... I assume this is part of the https://api.yourdomain.com/signin-twitter and https://api.yourdomain.com/signin-facebook etc... callbacks. 当应用程序从Twitter,Facebook等重定向回时,将调用此方法。我认为这是https://api.yourdomain.com/signin-twitterhttps://api.yourdomain.com/signin- Facebook等...回调。 Based on what I can gather, return new ExternalLoginData gets the AccessToken and AccessTokenSecret. 根据我的收集,返回新的ExternalLoginData获取AccessToken和AccessTokenSecret。 GetClaims is then called. 然后调用GetClaims。 If the AccessToken and AccessTokenSecret are not null, they get re-added as Claims. 如果AccessToken和AccessTokenSecret不为null,则将它们重新添加为Claims。 These claims can then be accessed in the GetUserInfo or RegisterExternal method using this line of code. 然后,可以使用此行代码在GetUserInfo或RegisterExternal方法中访问这些声明。

ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity). 

You can then get the exact values using this code. 然后,您可以使用此代码获取确切的值。

AccessToken = externalLogin != null ? externalLogin.AccessToken : null,
                    AccessTokenSecret = externalLogin != null ? externalLogin.AccessTokenSecret : null

Here is the new ExternalLoginData method. 这是新的ExternalLoginData方法。

private class ExternalLoginData
        {
            public string LoginProvider { get; set; }
            public string ProviderKey { get; set; }
            public string UserName { get; set; }
            public string AccessToken { get; set; }
            public string AccessTokenSecret { get; set; }


            public IList<Claim> GetClaims()
            {
                IList<Claim> claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));

                if (UserName != null)
                {
                    claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
                }

                if (AccessToken != null)
                {
                    claims.Add(new Claim("access_token", AccessToken, null, LoginProvider));
                }

                if (AccessTokenSecret != null)
                {
                    claims.Add(new Claim("access_token_secret", AccessTokenSecret, null, LoginProvider));
                }

                return claims;
            }

            public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
            {
                if (identity == null)
                {
                    return null;
                }

                Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);

                if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
                    || String.IsNullOrEmpty(providerKeyClaim.Value))
                {
                    return null;
                }

                if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
                {
                    return null;
                }

                return new ExternalLoginData
                {
                    LoginProvider = providerKeyClaim.Issuer,
                    ProviderKey = providerKeyClaim.Value,
                    UserName = identity.FindFirstValue(ClaimTypes.Name),
                    AccessToken = identity.Claims.FirstOrDefault(x => x.Type.Contains("access_token")).Value,
                    AccessTokenSecret = identity.Claims.FirstOrDefault(x => x.Type.Contains("access_token_secret")).Value,
                };
            }
        }

I'm then using the public static TwitterDto TwitterLogin method to get the email address from Twitter (see link below). 然后,我使用公共静态TwitterDto TwitterLogin方法从Twitter获取电子邮件地址(请参见下面的链接)。

https://stackoverflow.com/a/36356009/5360237 https://stackoverflow.com/a/36356009/5360237

Hopefully, this will help someone else since this is not documented at all. 希望这会对其他人有所帮助,因为这根本没有记录在案。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM