gpt4 book ai didi

c# - C# 中是否有任何 JSON Web token (JWT) 示例?

转载 作者:IT王子 更新时间:2023-10-29 03:36:05 24 4
gpt4 key购买 nike

我觉得我在这里吃了疯狂的药。对于任何给定的任务,网络上总会有数以百万计的库和示例。我正在尝试通过使用 JSON Web token (JWT) 来实现 Google“服务帐户”的身份验证,如 here 所述.

但是只有 PHP、Python 和 Java 的客户端库。即使在谷歌认证之外搜索JWT示例,关于JWT概念也只有蟋蟀和草稿。这真的很新而且可能是谷歌专有系统吗?

Java 示例是我能设法解释的最接近的示例,看起来非常密集和令人生畏。在 C# 中必须有一些我至少可以开始的东西。任何帮助都会很棒!

最佳答案

我找到了 Json Web Token 的基本实现,并使用 Google 风格对其进行了扩展。我还没有完全解决它,但它已经完成了 97%。这个项目失去了动力,所以希望这能帮助其他人获得良好的开端:

注意:我对基本实现所做的更改(不记得我是在哪里找到的)是:

  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;
}
}

然后是我的 google 特定 JWT 类:

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# - C# 中是否有任何 JSON Web token (JWT) 示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10055158/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com