我正在尝试向 Google APIs AdMob 服务发出请求。此 API 需要新的 OAuth 2.0 身份验证过程,该过程用于服务到服务的集成,是一个两步过程:1) 创建本地并签名的 JWT 并将其发送给 Google 2) 检索令牌以查询 API。我一直在测试手动创建 JWT 并使用官方库,但他们最终抛出了同样的错误:
“admob 服务抛出异常。HttpStatusCode 未授权。请求缺少必需的身份验证凭据。需要 OAuth 2 访问令牌、登录 cookie 或其他有效的身份验证凭据。”
使用官方库的代码
// path to the .p12 certificate
var privateKeyFilePath = Path.Combine(X509_KEY_FILE_NAME);
var certificate = new X509Certificate2(privateKeyFilePath, "MySecret", X509KeyStorageFlags.Exportable);
CertificateCredentials = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(emailAccountId)
{
ProjectId = "MyProjectId",
Scopes = new[] { AdMobService.Scope.AdmobReadonly },
}.FromCertificate(certificate));
...
var adMobService = new AdMobService(new BaseClientService.Initializer()
{
HttpClientInitializer = CertificateCredentials,
ApplicationName = "MyProjectId",
});
// line that throws the error
var accountsResponse = await adMobService.Accounts.List().ExecuteAsync(cancellationToken);
var account = accountsResponse.Account.FirstOrDefault();
使用本地签名令牌的代码:
// we reuse X509 loaded previously
var signingCredentials = new SigningCredentials(new RsaSecurityKey(certificate.GetRSAPrivateKey()), SecurityAlgorithms.RsaSha256);
var jwtHeader = new JwtHeader(signingCredentials)
{
{ "kid", kid }
};
var jwtPayload = new JwtPayload(
issuer: emailAccountId,
audience: GoogleAuthConsts.TokenUrl,
claims: new List<Claim>()
{
new Claim("scope", AdMobService.Scope.AdmobReadonly),
},
notBefore: null,
expires: DateTime.Now.AddHours(1),
issuedAt: DateTime.Now);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.WriteToken(new JwtSecurityToken(jwtHeader, jwtPayload));
var httpClient = new HttpClient();
var parameters = new Dictionary<string, string> {
{ "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer" },
{ "assertion", jwt }
};
var httpContent = new FormUrlEncodedContent(parameters);
var response = await httpClient.PostAsync(GoogleAuthConsts.OidcTokenUrl, httpContent, cancellationToken);
var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
var TokenResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<TokenResponse>(responseContent);
var httpClientAdMob = new HttpClient();
httpClientAdMob.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", TokenResponse.AccessToken);
var responseAdMob = await httpClientAdMob.GetAsync("https://admob.googleapis.com/v1/accounts", cancellationToken);
if (responseAdMob.IsSuccessStatusCode)
{
// line that throws the error
var contentAdMob = await responseAdMob.Content.ReadAsStringAsync(cancellationToken);
}
通过删除 JWT Payload 的额外值,因为“Kid”似乎没有影响。
我尝试了 Google.Apis.Auth 和 Google.Apis.AdMob.v1 库的官方版本。除了手动创建 JWT 以从 Google OAuth 的令牌 端点检索访问令牌。