gpt4 book ai didi

c# - Google OAuth2 服务帐户访问 token 请求提供 'Invalid Request' 响应

转载 作者:可可西里 更新时间:2023-11-01 08:21:00 27 4
gpt4 key购买 nike

我正在尝试通过服务器到服务器方法与我的应用启用的 BigQuery API 进行通信。

我已勾选此 Google guide 上的所有方框在 C# 中尽我所能构建我的 JWT。

我已经对所有必要的内容进行了 Base64Url 编码。

但是,我从 google 得到的唯一响应是 400 Bad Request

"error" : "invalid_request"

我已经从这些其他 SO 问题中确定了以下所有内容:

我在使用 Fiddler 时得到了相同的结果。错误消息令人沮丧地缺乏细节!我还能尝试什么?!这是我的代码:

class Program
{
static void Main(string[] args)
{
// certificate
var certificate = new X509Certificate2(@"<Path to my certificate>.p12", "notasecret");

// header
var header = new { typ = "JWT", alg = "RS256" };

// claimset
var times = GetExpiryAndIssueDate();
var claimset = new
{
iss = "<email address of the client id of my app>",
scope = "https://www.googleapis.com/auth/bigquery",
aud = "https://accounts.google.com/o/oauth2/token",
iat = times[0],
exp = times[1],
};

// encoded header
var headerSerialized = JsonConvert.SerializeObject(header);
var headerBytes = Encoding.UTF8.GetBytes(headerSerialized);
var headerEncoded = Base64UrlEncode(headerBytes);

// encoded claimset
var claimsetSerialized = JsonConvert.SerializeObject(claimset);
var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized);
var claimsetEncoded = Base64UrlEncode(claimsetBytes);

// input
var input = headerEncoded + "." + claimsetEncoded;
var inputBytes = Encoding.UTF8.GetBytes(input);

// signiture
var rsa = certificate.PrivateKey as RSACryptoServiceProvider;
var cspParam = new CspParameters
{
KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,
KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2
};
var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false };
var signatureBytes = aescsp.SignData(inputBytes, "SHA256");
var signatureEncoded = Base64UrlEncode(signatureBytes);

// jwt
var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded;

Console.WriteLine(jwt);

var client = new HttpClient();
var uri = "https://accounts.google.com/o/oauth2/token";
var post = new Dictionary<string, string>
{
{"assertion", jwt},
{"grant_type", "urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer"}
};
var content = new FormUrlEncodedContent(post);
var result = client.PostAsync(uri, content).Result;

Console.WriteLine(result);
Console.WriteLine(result.Content.ReadAsStringAsync().Result);
Console.ReadLine();
}

private static int[] GetExpiryAndIssueDate()
{
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;

return new[]{iat, exp};
}

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

最佳答案

看来我在上面评论中的猜测是正确的。我通过更改使您的代码正常工作:

“urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer”

到:

“urn:ietf:params:oauth:grant-type:jwt-bearer”

看起来你不小心对它进行了双重编码。

我现在收到的回复看起来像这样:

{
"access_token" : "1/_5pUwJZs9a545HSeXXXXXuNGITp1XtHhZXXxxyyaacqkbc",
"token_type" : "Bearer",
"expires_in" : 3600
}

编辑注意:请确保您的服务器上有正确的日期/时间/时区/夏令时配置。即使时钟关闭几秒钟也会导致 invalid_grant 错误。 http://www.time.gov将给出美国政府的官方时间,包括 UTC。

关于c# - Google OAuth2 服务帐户访问 token 请求提供 'Invalid Request' 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11939026/

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