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

如何在Firebase云函数中稳定获取GitHub授权用户的显示名称

解决Firebase Auth onCreate触发器中GitHub用户displayName不稳定的问题

首先得明确问题根源:当functions.auth.user().onCreate触发时,Firebase Auth可能还没完成与GitHub身份提供商的用户数据同步——顶层的user.displayName字段有时候会滞后于第三方提供商的原始数据,导致频繁拿到undefined。下面是两个不依赖延迟的可靠解决方案:

方案1:主动拉取完整用户信息

不要直接使用事件传入的event.data,而是通过Firebase Admin SDK调用getUser方法获取最新的用户数据。这个方法会从Auth系统中拉取完整的、同步后的用户信息,能避开事件触发时数据未同步的坑。

修改后的代码示例:

exports.initUser = functions.auth.user().onCreate(async (event) => {
  const uid = event.data.uid;
  const score = 0;

  // 主动获取最新的完整用户信息
  const user = await admin.auth().getUser(uid);
  
  let name = uid;
  // 优先使用顶层displayName,为空则从GitHub提供商数据提取
  if (user.displayName) {
    name = validator.escape(user.displayName);
  } else {
    // 定位GitHub提供商的原始数据
    const githubProvider = user.providerData.find(provider => provider.providerId === 'github.com');
    if (githubProvider && githubProvider.displayName) {
      name = validator.escape(githubProvider.displayName);
    }
  }

  // 合并所有数据库操作,确保全部完成后再结束函数
  await Promise.all([
    admin.database().ref(`users/${uid}/score`).set(score),
    admin.database().ref(`users/${uid}/name`).set(name),
    admin.database().ref(`scores/${uid}`).set(score)
  ]);

  console.log("Created User: " + name);
  return true;
});

方案2:直接从ProviderData提取GitHub原始信息

顶层的user.displayName是Firebase合并后的字段,同步可能有延迟,但user.providerData里存储的是各身份提供商的原始数据,这里的GitHub信息会更可靠。我们可以直接从这里提取displayName:

exports.initUser = functions.auth.user().onCreate(async (event) => {
  const uid = event.data.uid;
  const score = 0;

  let name = uid;
  const user = event.data;
  
  // 直接定位GitHub提供商的数据
  const githubProvider = user.providerData.find(provider => provider.providerId === 'github.com');
  if (githubProvider) {
    // 优先用GitHub的原始displayName
    if (githubProvider.displayName) {
      name = validator.escape(githubProvider.displayName);
    }
  } else if (user.displayName) {
    // 兜底用顶层displayName
    name = validator.escape(user.displayName);
  }

  await Promise.all([
    admin.database().ref(`users/${uid}/score`).set(score),
    admin.database().ref(`users/${uid}/name`).set(name),
    admin.database().ref(`scores/${uid}`).set(score)
  ]);

  console.log("Created User: " + name);
  return true;
});

额外优化建议

  • 用async/await和Promise.all管理异步操作,确保所有数据库写入完成后函数才终止,避免因函数提前结束导致的写入失败。
  • 设置多重兜底逻辑:先取GitHub原始displayName,再取顶层displayName,最后用uid,最大程度保证能拿到可用的用户名。

这两个方案都不需要依赖延迟,而是通过更可靠的数据获取逻辑解决同步问题,能大幅提升displayName获取的稳定性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:36:17