使用System.IdentityModel.Tokens.Jwt解码和验证JWT令牌


100

我一直在使用JWT库来解码Json Web令牌,并想切换到Microsoft的官方JWT实现System.IdentityModel.Tokens.Jwt

该文档非常稀疏,因此我很难确定如何完成对JWT库所做的工作。在JWT库中,有一个Decode方法,它采用base64编码的JWT,并将其转换为JSON,然后可以反序列化。我想使用System.IdentityModel.Tokens.Jwt做类似的事情,但是经过大量的挖掘之后,仍然无法弄清楚如何做。

对于它的价值,我正在从cookie中读取JWT令牌,以与Google的身份框架一起使用。

任何帮助,将不胜感激。



下面是关于如何获取谷歌证书和验证令牌动手答案- stackoverflow.com/questions/29757140/...
rothschild86

Answers:


147

包中有一个名为的类JwtSecurityTokenHandler,它从System.IdentityModel.Tokens.SecurityTokenHandler。在WIF中,这是反序列化和序列化安全令牌的核心类。

该类具有一个ReadToken(String)将采用base64编码的JWT字符串并返回一个SecurityToken表示JWT的方法。

SecurityTokenHandler也有ValidateToken(SecurityToken)这需要你的方法SecurityToken,并创建一个ReadOnlyCollection<ClaimsIdentity>。通常对于JWT,它将包含一个ClaimsIdentity对象,该对象具有一组表示原始JWT属性的声明。

JwtSecurityTokenHandler为定义了一些附加的重载ValidateToken,特别是它有一个ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters)重载。该TokenValidationParameters参数允许您指定令牌签名证书(作为的列表X509SecurityTokens)。它还有一个重载,将JWT用作string而不是SecurityToken

执行此操作的代码相当复杂,但是可以在TokenValidationHandler位于以下位置的开发人员示例“ ADAL-REST的本机应用程序-通过浏览器对话框通过ACS进行身份验证” 的Global.asax.cx代码(类)中找到该代码。

http://code.msdn.microsoft.com/AAL-Native-App-to-REST-de57f2cc

另外,JwtSecurityToken该类还具有其他不在基SecurityToken类上的方法,例如,Claims无需通过ClaimsIdentity集合即可获取所包含的声明的属性。它还具有Payload返回一个JwtPayload对象的属性,该对象使您可以获取令牌的原始JSON。这取决于您的方案,哪种方法最合适。

SecurityTokenHandler该类的常规(即非JWT特定)文档位于

http://msdn.microsoft.com/zh-CN/library/system.identitymodel.tokens.securitytokenhandler.aspx

根据您的应用程序,可以像其他任何处理程序一样将JWT处理程序配置到WIF管道中。

共有3个样本在以下不同类型的应用中使用

http://code.msdn.microsoft.com/site/search?f%5B0%5D.Type=SearchText&f%5B0%5D.Value=aal&f%5B1%5D.Type=User&f%5B1%5D.Value=Azure% 20AD%20Developer%20Experience%20Team&f%5B1%5D.Text = Azure%20AD%20Developer%20Experience%20Team

可能,一个将满足您的需求或至少能够适应它们。


3
非常感谢您的回答。因此,一旦有了ClaimsIdentity,如何针对公共密钥进行验证?具体来说,我正在尝试根据其公钥(gstatic.com/authtoolkit/cert/gitkit_cert.pem)验证Google身份工具包JWT
w.brian 2013年

4
更新了我的答案-我无法为此提供全部信息,但我向您指出了适当的开发人员示例的方向。希望能帮助到你。
Mike Goodwin 2013年

4
@ w.brian-我正在尝试做同样的事情。我有一个可以解码的令牌和一个我想验证的公钥,但是即使查看这些示例,我仍在努力查看如何执行此操作。您是否有指向实际帮助您的代码的指针?谢谢。
Barguast,

25

我只是想知道为什么完全使用某些库进行JWT令牌解码和验证。

可以使用以下伪代码创建编码的JWT令牌

var headers = base64URLencode(myHeaders);
var claims = base64URLencode(myClaims);
var payload = header + "." + claims;

var signature = base64URLencode(HMACSHA256(payload, secret));

var encodedJWT = payload + "." + signature;

没有任何特定的库,这很容易做到。使用以下代码:

using System;
using System.Text;
using System.Security.Cryptography;

public class Program
{   
    // More info: https://stormpath.com/blog/jwt-the-right-way/
    public static void Main()
    {           
        var header = "{\"typ\":\"JWT\",\"alg\":\"HS256\"}";
        var claims = "{\"sub\":\"1047986\",\"email\":\"jon.doe@eexample.com\",\"given_name\":\"John\",\"family_name\":\"Doe\",\"primarysid\":\"b521a2af99bfdc65e04010ac1d046ff5\",\"iss\":\"http://example.com\",\"aud\":\"myapp\",\"exp\":1460555281,\"nbf\":1457963281}";

        var b64header = Convert.ToBase64String(Encoding.UTF8.GetBytes(header))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");
        var b64claims = Convert.ToBase64String(Encoding.UTF8.GetBytes(claims))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");

        var payload = b64header + "." + b64claims;
        Console.WriteLine("JWT without sig:    " + payload);

        byte[] key = Convert.FromBase64String("mPorwQB8kMDNQeeYO35KOrMMFn6rFVmbIohBphJPnp4=");
        byte[] message = Encoding.UTF8.GetBytes(payload);

        string sig = Convert.ToBase64String(HashHMAC(key, message))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");

        Console.WriteLine("JWT with signature: " + payload + "." + sig);        
    }

    private static byte[] HashHMAC(byte[] key, byte[] message)
    {
        var hash = new HMACSHA256(key);
        return hash.ComputeHash(message);
    }
}

令牌解码是上面代码的反向版本。要验证签名,您需要使用相同的签名并将签名部分与计算出的签名进行比较。

更新:对于那些如何努力进行base64 url​​safe编码/解码的人,请参阅另一个SO问题,以及Wiki和RFC。


2
好答案。:虽然因为你在这里展示基于HMAC签名,它可能是有意义的认识图书馆实现HMAC核查一些重要的安全漏洞作为Auth0网站这里详述auth0.com/blog/2015/03/31/...
Sudhanshu米什拉

2
我觉得这是最好的答案。OP请求提供有关JWT的具体信息,本文专门以一个清晰的示例进行介绍
。.– webworm

13
这个答案解释并演示了如何 连接的时候,问题是代码JWT很清楚地约编码。这可能是一个不错的答案,但这是对完全不同的问题的答案。
Deltics

2
@Deltics我认为甚至不需要计算机科学学位即可重写编码算法来解码令牌。如果您知道如何编码-您知道如何解码
-Regfor

31
“答案”的思想是解决一个问题,而不是通过期望某人解决某种反向意图难题来构成难题。床边,知道如何编码也并不一定意味着你还那么,知道如何解码,因为这也可能涉及到处理与第三方令牌和检索键来验证他们的签名,而不是简单地用一个密钥来签署自己。在任何情况下,没有一个答案并不是真正的定义回答这个问题是不是在“ ”的回答相比,一个,这是我是在回应观察。
Deltics,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.