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

跨开发者账号的Google Games身份认证一致性方案问询

解决跨开发者账号的Google Play Games玩家身份统一问题

我们搭建了一套多Unity游戏对接单Node服务器的系统,目前支持用户通过Google Play在自有游戏中登录,同一玩家在不同自有游戏里靠Google提供的持久化playerId保持身份一致。现在要开放外部开发者账号的游戏接入,但同一玩家在这些外部游戏里获取到的Google Play playerId和自有游戏里的不一样,导致身份无法统一,想问有没有办法关联账号,让所有应用(不管所属开发者账号)返回的playerId保持一致?

当前服务端实现代码:

const { code, gameId } = req.query;

if (!code) {
  throw new BadRequestError('code is required in query params');
}
if (!gameId) {
  throw new BadRequestError('gameId is required in query params');
}
const googlePlayJson = JSON.parse(
  process.env.GOOGLE_PLAY_JSON
) as GooglePlayJson;
if (!googlePlayJson) {
  throw new NotFoundError(
    'googlePlayJson not found please contact backend dev'
  );
}
//based on gameId get the correct client id and secret from the array
const json = googlePlayJson.find((game) => game.gameId === gameId);
if (!json) {
  throw new NotFoundError(
    `gameId ${gameId} not found in env json please contact backend dev`
  );
}

const oauth2Client = new OAuth2Client({
  clientId: json.clientId,
  clientSecret: json.clientSecret
});

const { tokens } = await oauth2Client.getToken({
  code: req.query.code as string
});

oauth2Client.setCredentials(tokens);
const games = google.games({
  version: 'v1',
  auth: oauth2Client
});

const response = await games.players.get({
  playerId: 'me',
  language: 'en'
});

const playerId = response.data.playerId;
if (!playerId) {
  throw new NotFoundError('playerId not found');
}
const displayName = response.data.displayName;
let user = await prisma.user.findUnique({
  where: { playerId }
});
if (!user) {
  user = await prisma.user.create({
    data: {
      playerId,
      name: displayName
    }
  });
}

核心结论与解决方案

Google Play Games的playerId本身与开发者账号强绑定,不同开发者账号下的应用,同一玩家的playerId必然不同,无法直接让其统一。但可以通过以下方式实现跨应用的身份统一:

使用Google账号OpenID Connect获取全局统一用户ID

改用Google账号的OpenID Connect协议,获取用户的sub字段——这是Google账号全局唯一且永久不变的用户标识,不受应用所属开发者账号影响。所有接入的应用只要通过Google OAuth2/OpenID Connect授权,就能获取到同一个sub值,以此作为用户的统一身份ID。

具体实现修改步骤

  1. 调整授权范围:外部游戏在发起Google授权请求时,必须包含openid email profile这些OpenID Connect相关的scope,不能仅使用Google Play Games的专属scope。
  2. 修改服务端验证逻辑:不再调用Google Games API获取playerId,而是解析OAuth返回的ID Token(JWT),从中提取sub字段作为统一用户ID。

修改后的代码示例

const { code, gameId } = req.query;

if (!code) {
  throw new BadRequestError('code is required in query params');
}
if (!gameId) {
  throw new BadRequestError('gameId is required in query params');
}
const googlePlayJson = JSON.parse(
  process.env.GOOGLE_PLAY_JSON
) as GooglePlayJson;
if (!googlePlayJson) {
  throw new NotFoundError(
    'googlePlayJson not found please contact backend dev'
  );
}
const json = googlePlayJson.find((game) => game.gameId === gameId);
if (!json) {
  throw new NotFoundError(
    `gameId ${gameId} not found in env json please contact backend dev`
  );
}

const oauth2Client = new OAuth2Client({
  clientId: json.clientId,
  clientSecret: json.clientSecret
});

const { tokens } = await oauth2Client.getToken({
  code: req.query.code as string
});

// 解析ID Token获取全局唯一的sub字段
const ticket = await oauth2Client.verifyIdToken({
  idToken: tokens.id_token,
  audience: json.clientId,
});
const payload = ticket.getPayload();
const unifiedUserId = payload.sub;
if (!unifiedUserId) {
  throw new NotFoundError('unified user id not found');
}
const displayName = payload.name;

// 使用unifiedUserId作为用户唯一标识查询或创建用户
let user = await prisma.user.findUnique({
  where: { unifiedUserId } // 需要在数据库中新增unifiedUserId字段并设置唯一约束
});
if (!user) {
  user = await prisma.user.create({
    data: {
      unifiedUserId,
      name: displayName,
      // 可选:保留原playerId字段,用于关联不同开发者账号下的游戏身份
      // playerId: 原playerId
    }
  });
}

额外注意事项

  • 数据库调整:需在用户表中新增unifiedUserId字段,设置为唯一索引,替换原playerId的唯一标识逻辑。
  • 外部游戏接入要求:外部开发者需在自己的Google Cloud项目中配置OAuth2客户端,将回调地址指向你的服务器,并确保授权请求包含OpenID Connect的scope。
  • 兼容性过渡:原有自有游戏可逐步迁移到新逻辑,或同时保留两种身份标识,实现平滑过渡。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:33:08