有没有在C#中JSON网络令牌(JWT)的例子吗? [英] Is there a JSON Web Token (JWT) example in C#?

查看:3793
本文介绍了有没有在C#中JSON网络令牌(JWT)的例子吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得我在这里疯狂服用药片。通常总是有一百万图书馆和漂浮在网络上任何给定的任务样本。我试图通过使用JSON网络令牌(JWT)的这里描述来实现与谷歌服务帐户验证:<一href=\"https://developers.google.com/accounts/docs/OAuth2ServiceAccount#libraries\">https://developers.google.com/accounts/docs/OAuth2ServiceAccount#libraries

但是,现在在PHP,Python和和Java只有客户端库。即使搜索谷歌的认证以外的智威汤逊的例子,只有在智威汤逊概念蟋蟀和草稿。这真的是很新,可能是谷歌专有系统?

Java示例这是我能设法间preT最接近看起来pretty密集和恐吓。我们有了在C#那里的东西,我至少可以下手。任何帮助,这将是巨大的!


解决方案

谢谢大家。我发现了一个JSON网络令牌的基本实现,并与谷歌的味道就可以了扩大。我还没有得到它完全制定,但它的存在97%。这个项目失去了它的蒸汽,所以希望这会帮助别人得到了一个好头启动:

请注意:
我对基实现所做的更改(不记得在那里我找到了,)分别是:


  

      
  1. 改变HS256 - > RS256

  2.   
  3. 交换了智威汤逊和在头ALG顺序。不知道谁听错了,谷歌或规范,但谷歌采取的方式是根据自己的文档下方。

  4.   

 公开枚举JwtHashAlgorithm
{
    RS256,
    HS384,
    HS512
}公共类JsonWebToken
{
    私有静态字典&LT; JwtHashAlgorithm,Func键&LT;字节[],字节[],字节[]&GT;&GT; HashAlgorithms;    静态JsonWebToken()
    {
        HashAlgorithms =新词典&LT; JwtHashAlgorithm,Func键&LT;字节[],字节[],字节[]&GT;&GT;
            {
                {JwtHashAlgorithm.RS256,(键,值)=&GT; {使用(VAR SHA =新HMACSHA256(键)){返回sha.ComputeHash(值); }}},
                {JwtHashAlgorithm.HS384,(键,值)=&GT; {使用(VAR SHA =新HMACSHA384(键)){返回sha.ComputeHash(值); }}},
                {JwtHashAlgorithm.HS512,(键,值)=&GT; {使用(VAR SHA =新HMACSHA512(键)){返回sha.ComputeHash(值); }}}
            };
    }    公共静态字符串连接code(对象的有效载荷,串键,JwtHashAlgorithm算法)
    {
        返回恩code(有效载荷,Encoding.UTF8.GetBytes(键),算法);
    }    公共静态字符串连接code(对象的有效载荷,字节[] keyBytes,JwtHashAlgorithm算法)
    {
        VAR段=新的List&LT;串GT;();
        VAR头= {新ALG = algorithm.ToString(),典型值=智威汤逊};        字节[] = headerBytes Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(头,Formatting.None));
        字节[] = payloadBytes Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(有效载荷,Formatting.None));
        //字节[] = payloadBytes Encoding.UTF8.GetBytes(@\"{\"iss\":\"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com\",\"scope\":\"https://www.googleapis.com/auth/$p$pdiction\",\"aud\":\"https://accounts.google.com/o/oauth2/token\",\"exp\":1328554385,\"iat\":1328550785}\");        segments.Add(Base64UrlEn code(headerBytes));
        segments.Add(Base64UrlEn code(payloadBytes));        变种stringToSign =的string.join(,segments.ToArray()。);        VAR bytesToSign = Encoding.UTF8.GetBytes(stringToSign);        字节[] =签名HashAlgorithms [算法(keyBytes,bytesToSign);
        segments.Add(Base64UrlEn code(签字));        返回的string.join(,segments.ToArray()。);
    }    公共静态字符串德code(字符串标记,字符串键)
    {
        返回德code(令牌,钥匙,真正的);
    }    公共静态字符串德code(字符串标记,串键,布尔确认)
    {
        变种份= token.Split('。');
        VAR头=零件[0];
        VAR有效载荷=部件[1];
        字节[] =密码Base64UrlDe code(部件[2]);        VAR headerJson = Encoding.UTF8.GetString(Base64UrlDe code(头));
        VAR headerData = JObject.Parse(headerJson);
        VAR payloadJson = Encoding.UTF8.GetString(Base64UrlDe code(负载));
        VAR payloadData = JObject.Parse(payloadJson);        如果(验证)
        {
            变种bytesToSign = Encoding.UTF8.GetBytes(string.Concat(标题,有效载荷)。);
            VAR keyBytes = Encoding.UTF8.GetBytes(键);
            VAR算法=(字符串)headerData [ALG];            变种签名= ​​HashAlgorithms [GetHashAlgorithm(算法)](keyBytes,bytesToSign);
            VAR德codedCrypto = Convert.ToBase64String(加密);
            VAR德codedSignature = Convert.ToBase64String(签字);            如果(德codedCrypto!=去codedSignature)
            {
                抛出新ApplicationException的(的String.Format(无效的签名预期{0}有{1},德codedCrypto,德codedSignature));
            }
        }        返回payloadData.ToString();
    }    私有静态JwtHashAlgorithm GetHashAlgorithm(字符串变换算法)
    {
        开关(算法)
        {
            案RS256:返回JwtHashAlgorithm.RS256;
            案HS384:返回JwtHashAlgorithm.HS384;
            案HS512:返回JwtHashAlgorithm.HS512;
            默认:抛出新的InvalidOperationException异常(不支持算法。);
        }
    }    //从智威汤逊规范
    私人静态字符串Base64UrlEn code(字节[]输入)
    {
        无功输出= Convert.ToBase64String(输入);
        输出= output.Split('=')[0]; //删除任何尾随'=的
        输出= output.Replace(+, - ); //编码字符第62
        输出= output.Replace('/','_'); //编码字符第63
        返回输出;
    }    //从智威汤逊规范
    私人静态的byte [] Base64UrlDe code(字符串输入)
    {
        无功输出=输入;
        输出= output.Replace(' - ','+'); //编码字符第62
        输出= output.Replace('_','/'); //编码字符第63
        开关(output.Length%4)//垫尾随'=的
        {
            情况下0:打破; //在这种情况下没有键盘字符
            案例2:输出+ ===;打破; //两个垫字符
            案例3:输出+ ==;打破; //一垫字符
            默认:抛出新的System.Exception(非法base64url串!);
        }
        变种转化= Convert.FromBase64String(输出); //标准的base64德codeR
        返回转换;
    }
}

然后我的谷歌具体的智威汤逊类:

 公共类GoogleJsonWebToken
{
    公共静态字符串连接code(字符串email,字符串certificateFilePath)
    {
        VAR utc0 =新日期时间(1970,1,1,0,0,0,0,DateTimeKind.Utc);
        VAR issueTime = DateTime.Now;        VAR IAT =(int)的issueTime.Subtract(utc0).TotalSeconds;
        VAR EXP =(int)的issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds; //过期时间长达1个小时,但让玩家在安全方面        无功负载=新
        {
            ISS =电子邮件,
            范围=htt​​ps://www.googleapis.com/auth/gan.readonly
            AUD =htt​​ps://accounts.google.com/o/oauth2/token
            EXP = EXP,
            IAT IAT =
        };        VAR证书=新X509Certificate2(certificateFilePathnotasecret);        VAR privateKey = certificate.Export(X509ContentType.Cert);        返回JsonWebToken.En code(有效载荷,privateKey,JwtHashAlgorithm.RS256);
    }
}

I feel like I'm taking crazy pills here. Usually there's always a million library and samples floating around the web for any given task. I'm trying to implement authentication with a Google "Service Account" by use of JSON Web Tokens (JWT) as described here: https://developers.google.com/accounts/docs/OAuth2ServiceAccount#libraries

However there is only client libraries in PHP, Python, and Java. Even searching for JWT examples outside of Google's authentication, there is only crickets and drafts on the JWT concept. Is this really so new and possibly a Google proprietary system?

The java sample which is the closest I could manage to interpret looks pretty intensive and intimidating. There's got to be something out there in C# that I could at least start with. Any help with this would be great!

解决方案

Thanks everyone. I found a base implementation of a Json Web Token and expanded on it with the Google flavor. I still haven't gotten it completely worked out but it's 97% there. This project lost it's steam, so hopefully this will help someone else get a good head-start:

Note: Changes I made to the base implementation (Can't remember where I found it,) are:

  1. Changed HS256 -> RS256
  2. Swapped the JWT and alg order in the header. Not sure who got it wrong, Google or the spec, but google takes it the way It is below according to their docs.

public enum JwtHashAlgorithm
{
    RS256,
    HS384,
    HS512
}

public class JsonWebToken
{
    private static Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>> HashAlgorithms;

    static JsonWebToken()
    {
        HashAlgorithms = new Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>>
            {
                { JwtHashAlgorithm.RS256, (key, value) => { using (var sha = new HMACSHA256(key)) { return sha.ComputeHash(value); } } },
                { JwtHashAlgorithm.HS384, (key, value) => { using (var sha = new HMACSHA384(key)) { return sha.ComputeHash(value); } } },
                { JwtHashAlgorithm.HS512, (key, value) => { using (var sha = new HMACSHA512(key)) { return sha.ComputeHash(value); } } }
            };
    }

    public static string Encode(object payload, string key, JwtHashAlgorithm algorithm)
    {
        return Encode(payload, Encoding.UTF8.GetBytes(key), algorithm);
    }

    public static string Encode(object payload, byte[] keyBytes, JwtHashAlgorithm algorithm)
    {
        var segments = new List<string>();
        var header = new { alg = algorithm.ToString(), typ = "JWT" };

        byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
        byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));
        //byte[] payloadBytes = Encoding.UTF8.GetBytes(@"{"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com","scope":"https://www.googleapis.com/auth/prediction","aud":"https://accounts.google.com/o/oauth2/token","exp":1328554385,"iat":1328550785}");

        segments.Add(Base64UrlEncode(headerBytes));
        segments.Add(Base64UrlEncode(payloadBytes));

        var stringToSign = string.Join(".", segments.ToArray());

        var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);

        byte[] signature = HashAlgorithms[algorithm](keyBytes, bytesToSign);
        segments.Add(Base64UrlEncode(signature));

        return string.Join(".", segments.ToArray());
    }

    public static string Decode(string token, string key)
    {
        return Decode(token, key, true);
    }

    public static string Decode(string token, string key, bool verify)
    {
        var parts = token.Split('.');
        var header = parts[0];
        var payload = parts[1];
        byte[] crypto = Base64UrlDecode(parts[2]);

        var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
        var headerData = JObject.Parse(headerJson);
        var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
        var payloadData = JObject.Parse(payloadJson);

        if (verify)
        {
            var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(header, ".", payload));
            var keyBytes = Encoding.UTF8.GetBytes(key);
            var algorithm = (string)headerData["alg"];

            var signature = HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes, bytesToSign);
            var decodedCrypto = Convert.ToBase64String(crypto);
            var decodedSignature = Convert.ToBase64String(signature);

            if (decodedCrypto != decodedSignature)
            {
                throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature));
            }
        }

        return payloadData.ToString();
    }

    private static JwtHashAlgorithm GetHashAlgorithm(string algorithm)
    {
        switch (algorithm)
        {
            case "RS256": return JwtHashAlgorithm.RS256;
            case "HS384": return JwtHashAlgorithm.HS384;
            case "HS512": return JwtHashAlgorithm.HS512;
            default: throw new InvalidOperationException("Algorithm not supported.");
        }
    }

    // from JWT spec
    private static string Base64UrlEncode(byte[] input)
    {
        var output = Convert.ToBase64String(input);
        output = output.Split('=')[0]; // Remove any trailing '='s
        output = output.Replace('+', '-'); // 62nd char of encoding
        output = output.Replace('/', '_'); // 63rd char of encoding
        return output;
    }

    // from JWT spec
    private static byte[] Base64UrlDecode(string input)
    {
        var output = input;
        output = output.Replace('-', '+'); // 62nd char of encoding
        output = output.Replace('_', '/'); // 63rd char of encoding
        switch (output.Length % 4) // Pad with trailing '='s
        {
            case 0: break; // No pad chars in this case
            case 2: output += "=="; break; // Two pad chars
            case 3: output += "="; break; // One pad char
            default: throw new System.Exception("Illegal base64url string!");
        }
        var converted = Convert.FromBase64String(output); // Standard base64 decoder
        return converted;
    }
}

And then my google specific JWT class:

public class GoogleJsonWebToken
{
    public static string Encode(string email, string certificateFilePath)
    {
        var utc0 = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);
        var issueTime = DateTime.Now;

        var iat = (int)issueTime.Subtract(utc0).TotalSeconds;
        var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds; // Expiration time is up to 1 hour, but lets play on safe side

        var payload = new
        {
            iss = email,
            scope = "https://www.googleapis.com/auth/gan.readonly",
            aud = "https://accounts.google.com/o/oauth2/token",
            exp = exp,
            iat = iat
        };

        var certificate = new X509Certificate2(certificateFilePath, "notasecret");

        var privateKey = certificate.Export(X509ContentType.Cert);

        return JsonWebToken.Encode(payload, privateKey, JwtHashAlgorithm.RS256);
    }
}

这篇关于有没有在C#中JSON网络令牌(JWT)的例子吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆