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

w.b*_*ian 90 .net wif jwt

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

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

为了它的价值,我正在从cookie中读取JWT令牌,以便与Google的身份框架一起使用.

任何帮助,将不胜感激.

Mik*_*win 135

在包中有一个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.

该代码做,这是相当复杂的,但可以在Global.asax.cx代码(可以找到TokenValidationHandler开发商样品中类)被称为"ADAL -原生应用休息服务-身份验证通过浏览器对话框ACS",位于

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

可替代地,JwtSecurityToken类具有额外的方法不属于在基SecurityToken类,如Claims那获取所含的权利要求书不经由去属性ClaimsIdentity集合.它还有一个Payload属性,该属性返回一个JwtPayload对象,使您可以获得令牌的原始JSON.这取决于您的场景哪种方法最合适.

SecurityTokenHandler课程的一般(即非JWT特定)文件是

http://msdn.microsoft.com/en-us/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 =天青%20AD%20Developer%20Experience%20Team

可能会满足您的需求,或至少适应它们.

  • 更新了我的答案 - 我无法完全适合这个,但我指出了适当的开发人员样本的方向.希望能帮助到你. (4认同)
  • @ w.brian - 我正在努力做同样的事情.我有一个可以解码的令牌,以及我要验证的公钥,但即使看这些样本,我也很难看到我是如何做到这一点的.你有什么指向实际帮助你的代码吗?谢谢. (4认同)
  • 我非常感谢你的回答.所以,一旦我有了ClaimsIdentity,我如何根据公钥验证它?具体来说,我正在尝试针对他们的公钥验证谷歌身份工具包JWT(https://www.gstatic.com/authtoolkit/cert/gitkit_cert.pem) (3认同)

Reg*_*for 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;
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

更新:对于那些如何努力如何做base64 url​​safe编码/解码请看另一个SO问题,以及维基和RFC

  • "回答"的想法是解决一个问题,而不是通过期待某人解决某种反向意图谜题来构成一个谜题.床边,知道如何编码*不一定意味着你也知道如何解码,因为这可能还涉及处理第三方令牌和检索密钥以验证他们的签名,而不是简单地使用密钥签署自己的.在任何情况下,根据定义**实际上回答问题的答案是*不是****************************************************************** (27认同)
  • 这个答案解释并演示了当问题非常明确地关于**de**编码时如何编写JWT代码.这可能是一个很好的答案,但它是一个完全不同的问题的答案*. (13认同)
  • 除非您真正知道自己在做什么,否则不要自己编写与安全相关的部分。总有一些事情你很容易做错。存在易受攻击的 jwt 库的事实证明,自己编写代码不是一个好主意,除非您真的认为自己比这些库的作者更了解 JWT。然而,这个答案对于获得 JWT 的理解仍然有用。 (3认同)
  • 很好的答案.虽然您在此处显示基于HMAC的签名,但是可以了解实施HMAC验证的库中的一些严重漏洞,详见Auth0网站:https://auth0.com/blog/2015/03/31/critical -vulnerabilities功能于JSON-Web的令牌库/ (2认同)
  • 我觉得这是最好的答案.OP请求有关JWT的信息,本文特别针对一个明确的例子进行了解决. (2认同)
  • @Deltics我认为即使是计算机科学学位也不需要重写编码算法来解码令牌.如果您了解如何编码 - 您了解如何解码 (2认同)
  • @Deltics在这种情况下(JWT,不透明令牌)解码可以很容易地按照编码示例完成.对于签名检查,您需要执行与示例相同的操作.让它倒转将是人们阅读它的功课.我认为这么简单的任务不需要任何库.所以这是一个替代答案.看看评级和你的投票我认为这个答案是有用的.无论如何,欢迎您发布更好的答案或使用第一个,反向代码并在此发布,甚至向管理员投诉. (2认同)