在 ASP.net 身份中向 Asp.Net Web API 2 Bearer Token 添加声明?
Add Claims to Asp.Net Web API 2 Bearer Token in ASP.net Identity?
是否可以向不记名令牌添加声明以便将来访问这些声明?这是 Web API 发行的 Bearer Token。它包含在从 Twitter 应用程序授权过程重定向时显示的 URL 中。
我问的原因是我试图将 Twitter AccessToken 和 AccessTokenSecret 存储为附加声明。我这样做是为了在使用 Bearer Token 访问 GetUserInfo 方法时可以访问这些声明。据我所知,这是不可能的。
似乎我可能必须将这些存储在 SQL 中,并在访问 GetUserInfo 时使用 Twitter 用户名检索它们。当我访问GetUserInfo时,我得到了Twitter userName和userId,但是我无法获得AccessToken和AccessTokenSecret。我可以使用 public 重写 Task Authenticated(TwitterAuthenticatedContext context) 方法将 context.ScreenName、context.AccessToken 和 context.AccessTokenSecret 存储在 SQL 中。
我需要 AccessToken 和 AccessTokenSecret,因此我可以调用此 Twitter 端点来获取用户的电子邮件地址。
https://api.twitter.com/1.1/account/verify_credentials.json
在此过程的这个阶段,我的用户没有登录,也没有创建他们的本地帐户。我正在尝试从 Twitter 获取电子邮件地址以创建他们的本地帐户。
更新 1
这是一些代码。我像这样从 Startup.Auth 中的 TwitterAuthenticationOptions 中的 Provider 调用此方法。如您所见,我将声明添加到已验证的上下文中。
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);
}
}
非常感谢任何帮助。提前致谢!
您不能更改第三方制作的令牌。
它们使用私钥签名并在登录期间进行验证。
您可以将主机 IdentityServer 置于 Twiiter 身份提供程序和您的应用程序之间。 IdentityServer 是开源 OpenId 和 OAuth 2.0 服务器,允许您指定应如何处理令牌和声明。但这并不是一件简单的事情。一切都取决于你想为这个解决方案走多远。
我当然可以推荐它!
好的,我终于让它工作了。关键在于 ExternalLoginData 方法(见下文)。当应用程序从 Twitter、Facebook 等重定向回来时调用此方法...我假设这是 https://api.yourdomain.com/signin-twitter and https://api.yourdomain.com/signin-facebook 等...回调的一部分。根据我收集到的信息,return new ExternalLoginData 获取了 AccessToken 和 AccessTokenSecret。然后调用 GetClaims。如果 AccessToken 和 AccessTokenSecret 不为空,则将它们重新添加为声明。然后可以使用这行代码在 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,
};
}
}
然后我使用 public 静态 TwitterDto TwitterLogin 方法从 Twitter 获取电子邮件地址(参见下面的 link)。
希望这会对其他人有所帮助,因为根本没有记录。 :)
是否可以向不记名令牌添加声明以便将来访问这些声明?这是 Web API 发行的 Bearer Token。它包含在从 Twitter 应用程序授权过程重定向时显示的 URL 中。
我问的原因是我试图将 Twitter AccessToken 和 AccessTokenSecret 存储为附加声明。我这样做是为了在使用 Bearer Token 访问 GetUserInfo 方法时可以访问这些声明。据我所知,这是不可能的。
似乎我可能必须将这些存储在 SQL 中,并在访问 GetUserInfo 时使用 Twitter 用户名检索它们。当我访问GetUserInfo时,我得到了Twitter userName和userId,但是我无法获得AccessToken和AccessTokenSecret。我可以使用 public 重写 Task Authenticated(TwitterAuthenticatedContext context) 方法将 context.ScreenName、context.AccessToken 和 context.AccessTokenSecret 存储在 SQL 中。
我需要 AccessToken 和 AccessTokenSecret,因此我可以调用此 Twitter 端点来获取用户的电子邮件地址。
https://api.twitter.com/1.1/account/verify_credentials.json
在此过程的这个阶段,我的用户没有登录,也没有创建他们的本地帐户。我正在尝试从 Twitter 获取电子邮件地址以创建他们的本地帐户。
更新 1
这是一些代码。我像这样从 Startup.Auth 中的 TwitterAuthenticationOptions 中的 Provider 调用此方法。如您所见,我将声明添加到已验证的上下文中。
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);
}
}
非常感谢任何帮助。提前致谢!
您不能更改第三方制作的令牌。
它们使用私钥签名并在登录期间进行验证。
您可以将主机 IdentityServer 置于 Twiiter 身份提供程序和您的应用程序之间。 IdentityServer 是开源 OpenId 和 OAuth 2.0 服务器,允许您指定应如何处理令牌和声明。但这并不是一件简单的事情。一切都取决于你想为这个解决方案走多远。
我当然可以推荐它!
好的,我终于让它工作了。关键在于 ExternalLoginData 方法(见下文)。当应用程序从 Twitter、Facebook 等重定向回来时调用此方法...我假设这是 https://api.yourdomain.com/signin-twitter and https://api.yourdomain.com/signin-facebook 等...回调的一部分。根据我收集到的信息,return new ExternalLoginData 获取了 AccessToken 和 AccessTokenSecret。然后调用 GetClaims。如果 AccessToken 和 AccessTokenSecret 不为空,则将它们重新添加为声明。然后可以使用这行代码在 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,
};
}
}
然后我使用 public 静态 TwitterDto TwitterLogin 方法从 Twitter 获取电子邮件地址(参见下面的 link)。
希望这会对其他人有所帮助,因为根本没有记录。 :)