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

集成Play Integrity API与GoogleAuth时遭遇403 Forbidden错误排查

问题:Play Integrity API后端解码返回403 Forbidden

已将Android应用部署到内部测试环境,Play Console配置完成,Android端能正常获取Integrity Token,但后端用Node.js通过GoogleAuth调用decodeIntegrityToken接口时,虽能拿到token和accessToken,却返回403 Forbidden错误。已完成Cloud项目关联、API启用、服务账号JSON配置,求排查缺失的配置步骤。


Android端代码

val integrityTokenResponse = integrityTokenProvider.request(
                StandardIntegrityTokenRequest.builder()
                    .setRequestHash(hash)
                    .build()
            )
            integrityTokenResponse.addOnSuccessListener { response ->
                lifecycleScope.launch {
                    val apiResponse = retrofit.verifyHash(VerifyHashRequest(response.token()))
                    runOnUiThread {
                        textView.text = apiResponse.message
                    }
                }
                     }.addOnFailureListener { exception ->
                Toast.makeText(this@MainActivity,"Failure ${exception.message}",Toast.LENGTH_LONG).show()
            }

后端Node.js代码

import { GoogleAuth } from "google-auth-library";
import path from "path";
 
 const {
      token,
    }: {
      token: string;
    } = await request.json();
  
    const keyFilePath = path.resolve(
      "./my.json"
    );

    const auth = new GoogleAuth({
      keyFile: keyFilePath,
      scopes: ["https://www.googleapis.com/auth/playintegrity"],
    });
    const packageName = "myandroidpackagename";

    const client = await auth.getClient();
    const accessToken = await client.getAccessToken();
    const url = `https://playintegrity.googleapis.com/v1/${packageName}:decodeIntegrityToken`;

    console.log("token", token);
    console.log("accessToken", accessToken.token);
    const response = await fetch(url, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessToken.token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        integrityToken: token,
      }),
    });

    console.log("response", response);

    if (!response.ok) {
      throw new Error(response.statusText);
    }

    const json = await response.json();

    return Response.json({
      message: JSON.stringify(json),
    });
  } catch (e) {
    return Response.json({
      message: "Error " + e,
    });
  }

错误响应

{
  status: 403,
  statusText: 'Forbidden',
  headers: Headers {
    vary: 'Origin, X-Origin, Referer',
    'content-type': 'application/json; charset=UTF-8',
    date: 'Sun, 29 Dec 2024 08:19:31 GMT',
    server: 'ESF',
    'content-length': '154',
    'x-xss-protection': '0',
    'x-frame-options': 'SAMEORIGIN',
    'x-content-type-options': 'nosniff',
    'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000'
  },
  body: ReadableStream { locked: false, state: 'readable', supportsBYOB: true },
  bodyUsed: false,
  ok: false,
  redirected: false,
  type: 'basic',
  url: 'https://playintegrity.googleapis.com/v1/myapppackage:decodeIntegrityToken'
}

缺失的配置步骤排查

  • 给服务账号分配Play Integrity API 解码器角色
    进入Google Play Console,找到目标应用 → 开发者账号 → API访问 → 找到关联的服务账号,点击「授予访问权限」,添加「Play Integrity API 解码器」角色(该角色是解码Integrity Token的必备权限)。
  • 确认服务账号所属Cloud项目与Play Console绑定项目一致
    检查Play Console中API访问页面显示的Cloud项目ID,和服务账号JSON文件里的project_id是否完全匹配,项目不匹配会导致权限验证失败。
  • 验证内部测试账号与版本状态
    确保获取Token的设备所用Google账号已加入内部测试授权列表,且应用的内部测试版本已完成发布(非草稿状态),未发布或未授权的测试版本生成的Token无法被正常解码。
  • 检查包名完全匹配
    后端代码中的packageName必须和Android应用的包名完全一致,包括大小写(Android包名通常为小写,但严格匹配是必要的)。
  • 重新确认服务账号JSON文件有效性
    重新下载服务账号的JSON密钥文件,确保文件未被修改,其中的client_email和project_id与对应项目信息一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 06:54:57