我觉得我在这里服用疯药.通常,对于任何给定的任务,总会有一百万个库和样本在网络上浮动.我正在尝试使用JSON Web令牌(JWT)通过Google服务帐户"实施身份验证,如此处.
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.
但是,只有PHP,Python和Java的客户端库.即使在Google身份验证之外搜索JWT示例,也只有关于JWT概念的和草稿.这真的很新,可能是Google专有系统吗?
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?
我可以设法解释的最接近的Java示例看起来非常密集且令人生畏.我至少可以从C#那里开始.任何帮助都会很棒!
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!
推荐答案感谢大家.我找到了Json Web令牌的基本实现,并用Google风格对其进行了扩展.我仍然没有完全解决这个问题,但是那是97%.这个项目失去了动力,因此希望这可以帮助其他人获得良好的开端:
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:
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","scope":"www.googleapis/auth/prediction","aud":"accounts.google/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; } }
然后是我的Google特定于JWT的类:
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 = "www.googleapis/auth/gan.readonly", aud = "accounts.google/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 Web令牌(JWT)示例?
发布评论