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

时间:2019-02-27 17:15:49

标签: c# asp.net asp.net-web-api2 asp.net-identity twitter-oauth

是否可以将声明添加到承载令牌中,以便将来访问这些声明?这是Web API发行的Bearer令牌。它包含在从Twitter应用授权过程重定向后显示的URL中。

我问的原因是我正在尝试存储Twitter AccessToken和AccessTokenSecret作为其他声明。我这样做是为了在使用承载令牌访问GetUserInfo方法时可以访问这些声明。据我所知,这是不可能的。

当我访问GetUserInfo时,似乎可能必须将它们存储在SQL中并使用Twitter userName检索它们。当我访问GetUserInfo时,我获得了Twitter的userName和userId,但无法获得AccessToken和AccessTokenSecret。我也许可以使用公共重写Task Authenticated(TwitterAuthenticatedContext context)方法在SQL中存储context.ScreenName,context.AccessToken和context.AccessTokenSecret。

我需要AccessToken和AccessTokenSecret,因此我可以调用此Twitter端点来获取用户的电子邮件地址。

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

在此过程的此阶段,我的用户尚未登录,并且尚未创建其本地帐户。我正在尝试从Twitter获取电子邮件地址,以创建其本地帐户。

更新1

这是一些代码。我正在这样从Startup.Auth的TwitterAuthenticationOptions中的提供者调用此方法。如您所见,我正在将身份验证添加到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);
    }

}

非常感谢您的帮助。预先感谢!

2 个答案:

答案 0 :(得分:0)

您不能更改第三方制作的令牌。
它们用私钥签名并在登录期间经过验证。

您可以将主机IdentityServer放在Twiiter身份Prodiver和您的应用程序之间。 IdentityServer是开源的OpenId和OAuth 2.0服务器,可让您指示应如何处理令牌和声明。但这并不是一件容易的事情。一切都取决于您要采用这种解决方案的程度。

https://identityserver.io/

我当然可以推荐!

答案 1 :(得分:0)

好的,我终于可以使用它了。密钥在ExternalLoginData方法中(请参见下文)。当应用程序从Twitter,Facebook等重定向回时,将调用此方法。我认为这是https://api.yourdomain.com/signin-twitterhttps://api.yourdomain.com/signin-facebook等…回调的一部分。根据我的收集,返回新的ExternalLoginData获取AccessToken和AccessTokenSecret。然后调用GetClaims。如果AccessToken和AccessTokenSecret不为null,则将它们重新添加为Claims。然后,可以使用此行代码在GetUserInfo或RegisterExternal方法中访问这些声明。

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

然后您可以使用此代码获取确切的值。

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

这是新的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,
                };
            }
        }

然后,我使用公共静态TwitterDto TwitterLogin方法从Twitter获取电子邮件地址(请参见下面的链接)。

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

希望这对其他人有所帮助,因为这根本没有记录在案。 :)