首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用微软的IdentityModel验证JWT

用微软的IdentityModel验证JWT
EN

Stack Overflow用户
提问于 2017-03-22 23:16:39
回答 2查看 5.5K关注 0票数 3

我正在尝试验证以下测试JWT,选择的密钥是‘私有’,我可以在https://jwt.io上成功地验证它

代码语言:javascript
运行
复制
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyNzFjNmFkYjNhYTk1YTIxZWI3ZTljMTE2OGViNjI2YiIsImlhdCI6MTQ5MDE5NzQ2MCwibmJmIjoxNDkwMTk3NDYwLCJleHAiOjE0OTAyMDEwNjAsIklwIjoiNzkuMjMxLjczLjE1NCIsIk1lbWJlcklkIjoxfQ.P3m7RkXJ9TUiUFJ2bbtiyoL7OXaD7ITq_LsWMCRJj04

看起来微软已经改变了JwtSecurityTokenhandler()类,而且文档并不是最新的。我检查了一些使用new InMemorySymetricSecurityKey()的教程和gitpage,但是这个类已经不存在了。

Nuget软件包:Install System.IdentityModel.Tokens.Jwt (版本5.1.3)。

我创建了一个简单的控制台应用程序,并试图验证给定的JWT,但我不知道该如何指定TokenValidationParameters。

代码语言:javascript
运行
复制
static void Main(string[] args)
{
    var key = "private";
    var jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyNzFjNmFkYjNhYTk1YTIxZWI3ZTljMTE2OGViNjI2YiIsImlhdCI6MTQ5MDE5NzQ2MCwibmJmIjoxNDkwMTk3NDYwLCJleHAiOjE0OTAyMDEwNjAsIklwIjoiNzkuMjMxLjczLjE1NCIsIk1lbWJlcklkIjoxfQ.P3m7RkXJ9TUiUFJ2bbtiyoL7OXaD7ITq_LsWMCRJj04";

    var tokenHandler = new JwtSecurityTokenHandler();
    var securityToken = tokenHandler.ReadToken(jwt);
    var validationParameters = new TokenValidationParameters {IssuerSigningKey = new InMemorySymetricSecurityKey()};
    SecurityToken validated;
    tokenHandler.ValidateToken(jwt, validationParameters, out validated);

    Console.WriteLine(validated.ToString());
}
EN

回答 2

Stack Overflow用户

发布于 2017-03-23 01:06:54

参见下面的更新

这取决于谁签署了JWT令牌。通常,发出令牌的授权服务器使用其签名凭据的公钥发布元数据。

您的代码可以下载元数据并使用公钥验证令牌。例如,Azure发布它的签名密钥这里

您可以使用此代码验证Azure AD发出的JWT令牌。

代码语言:javascript
运行
复制
var jwtToken = "<JWT TOKEN>";
var url = "https://login.windows.net/common/federationmetadata/2007-06/federationmetadata.xml";
var serializer = new MetadataSerializer();
MetadataBase metadata = serializer.ReadMetadata(XmlReader.Create(url));

var entityDescriptor = (EntityDescriptor)metadata;
var securityTokens = new List<X509SecurityToken>();
var descriptor = entityDescriptor.RoleDescriptors.OfType<SecurityTokenServiceDescriptor>().First();

var x509DataClauses = descriptor.Keys.Where(key => key.KeyInfo != null &&
                                           (key.Use == KeyType.Signing || key.Use == KeyType.Unspecified))
                                     .Select(key => key.KeyInfo.OfType<X509RawDataKeyIdentifierClause>().First());

securityTokens.AddRange(x509DataClauses.Select(token => new X509SecurityToken(new X509Certificate2(token.GetX509RawData()))));

var validationParameters = new TokenValidationParameters
{
    IssuerSigningTokens = securityTokens,
    CertificateValidator = X509CertificateValidator.ChainTrust,
};
SecurityToken validatedToken;
ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(jwtToken, validationParameters, out validatedToken);

更新:--我误解了您的问题,错过了您指定的对称密钥的字面值。您应该能够使用这样的SymmetricSecurityKey

代码语言:javascript
运行
复制
HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(key));

var validationParameters = new TokenValidationParameters
{
    IssuerSigningKey = new SymmetricSecurityKey(hmac.Key);
};
票数 2
EN

Stack Overflow用户

发布于 2018-10-18 10:52:45

如果从身份提供程序获得元数据,则可以使用以下代码从元数据中获取密钥并验证令牌,

代码语言:javascript
运行
复制
static string _issuer = string.Empty;
static List<X509SecurityToken> _signingTokens = null;    
var stsMetadataAddress = "Your Metadata URL";
static string _audience = "your Audience URL"; //app id
GetTenantInformation(stsMetadataAddress, out issuer, out signingTokens);
Microsoft.IdentityModel.Tokens.SecurityKey key = new 
X509SecurityKey(signingTokens.FirstOrDefault().Certificate);
TokenValidationParameters validationParameters = new TokenValidationParameters
{
   ValidAudience = _audience,
   ValidIssuer = issuer,
   IssuerSigningKey = key
};

下面是从元数据中获取签名令牌和颁发者信息的方法,

代码语言:javascript
运行
复制
static void GetTenantInformation(string metadataAddress, out string issuer, out List<X509SecurityToken> signingTokens)
    {
        signingTokens = new List<X509SecurityToken>();

        // The issuer and signingTokens are cached for 24 hours. They are updated if any of the conditions in the if condition is true. 
        if (DateTime.UtcNow.Subtract(_stsMetadataRetrievalTime).TotalHours > 24
        || string.IsNullOrEmpty(_issuer)
        || _signingTokens == null)
        {
            MetadataSerializer serializer = new MetadataSerializer()
            {
                // turning off certificate validation for demo. Don't use this in production code.
                CertificateValidationMode = X509CertificateValidationMode.None
            };
            MetadataBase metadata = serializer.ReadMetadata(XmlReader.Create(metadataAddress));

            EntityDescriptor entityDescriptor = (EntityDescriptor)metadata;

            // get the issuer name
            if (!string.IsNullOrWhiteSpace(entityDescriptor.EntityId.Id))
            {
                _issuer = entityDescriptor.EntityId.Id;
            }

            // get the signing certs
            _signingTokens = ReadSigningCertsFromMetadata(entityDescriptor);

            _stsMetadataRetrievalTime = DateTime.UtcNow;
        }

        issuer = _issuer;
        signingTokens = _signingTokens;
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42964432

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档