問題描述
我正在嘗試通過服務(wù)器到服務(wù)器方法與我的應(yīng)用啟用的 BigQuery API 進(jìn)行通信.
I'm trying to communicate with my app's enabled BigQuery API via the server to server method.
我已勾選此 Google 指南上的所有方框,以構(gòu)建我的 JWT盡我所能在 C# 中.
I've ticked all the boxes on this Google guide for constructing my JWT as best I can in C#.
我已經(jīng)對所有必要的東西都進(jìn)行了 Base64Url 編碼.
And I've Base64Url encoded everything that was necessary.
但是,我從 google 得到的唯一響應(yīng)是 400 Bad Request
However, the only response I get from google is a 400 Bad Request
"error" : "invalid_request"
我已經(jīng)從這些其他 SO 問題中確定了以下所有內(nèi)容:
I've made sure of all of the following from these other SO questions:
- 簽名正確加密使用 RSA 和 SHA256
- 我正在使用 POST 并使用 application/x-www-form-urlencoded 內(nèi)容類型
- 轉(zhuǎn)義了聲明集中的所有反斜杠
- 在 POST 數(shù)據(jù)中嘗試了各種 grant_type 和斷言值
當(dāng)我使用 Fiddler 時,我得到了相同的結(jié)果.該錯誤消息令人沮喪地缺乏詳細(xì)信息!我還能嘗試什么?!這是我的代碼:
I get the same result when I use Fiddler. The error message is frustratingly lacking in detail! What else can I try?! Here's my code:
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;
}
}
推薦答案
看來我在上面評論中的猜測是正確的.我通過更改使您的代碼正常工作:
Looks like my guess in the comment above was correct. I got your code working by changing:
"urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer"
到:
"urn:ietf:params:oauth:grant-type:jwt-bearer"
看起來你不小心對它進(jìn)行了雙重編碼.
Looks like you were accidentally double-encoding it.
我現(xiàn)在收到的回復(fù)類似于:
I now get a response which looks something like:
{
"access_token" : "1/_5pUwJZs9a545HSeXXXXXuNGITp1XtHhZXXxxyyaacqkbc",
"token_type" : "Bearer",
"expires_in" : 3600
}
編輯說明:請確保您的服務(wù)器上的日期/時間/時區(qū)/夏令時配置正確.將時鐘延遲幾秒鐘也會導(dǎo)致 invalid_grant
錯誤.http://www.time.gov 將提供美國政府的官方時間,包括 UTC.
Edited Note: please make sure to have the correct date/time/timezone/dst configuration on your server. Having the clock off by even a few seconds will result in an invalid_grant
error. http://www.time.gov will give the official time from the US govt, including in UTC.
這篇關(guān)于Google OAuth2 服務(wù)帳戶訪問令牌請求給出“無效請求"響應(yīng)的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!