You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core用X.509证书调用Google AdMob API时OAuth 2.0 JWT令牌错误

调用Google AdMob API时的未授权认证错误

我正尝试调用Google AdMob API服务,该API要求采用OAuth 2.0服务到服务集成流程,需分两步操作:

  • 创建本地签名JWT并发送至Google
  • 获取令牌以查询API

但测试手动创建JWT和使用官方库两种方式时,均抛出相同的未授权错误:

“服务admob抛出异常。HttpStatusCode为Unauthorized。请求缺少必需的认证凭据。预期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负载中的额外值(如"Kid"),无效果
  • 使用官方发布的Google.Apis.Auth和Google.Apis.AdMob.v1库
  • 手动创建JWT从Google OAuth令牌端点获取访问令牌

内容的提问来源于stack exchange,提问作者Jose Cordero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 19:23:19