如何在 Firebase Github Auth 中获取 github 用户名

How to get github username in Firebase Github Auth

我在使用 Firebase Github 身份验证时尝试获取用户的用户名。但我无法得到它。我得到了除用户名以外的所有用户信息 这是我的代码:

import React, { useState, useContext, createContext, useEffect } from "react"
import { auth, createUserProfileDocument } from "../config/fbConfig"

const AuthContext = createContext()

export const useAuth = () => {
  return useContext(AuthContext)
}

export const AuthProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(null)

  const provider = new auth.GithubAuthProvider()
  provider.addScope("read:user")
  const githubSignIn = () => {
    return auth().signInWithRedirect(provider)
  }

  const githubSignOut = () => {
    return auth().signOut()
  }

  useEffect(() => {
    const unsubscribe = auth().onAuthStateChanged(async (userAuth) => {
      // setCurrentUser(user);
      if (userAuth) {
        const useRef = await createUserProfileDocument(userAuth)
        useRef.onSnapshot((snapShot) => {
          console.log(snapShot)
          setCurrentUser({
            id: snapShot.id,
            ...snapShot.data(),
          })
        })
      } else {
        setCurrentUser(userAuth)
      }
    })
    return unsubscribe
  }, [])

  const value = {
    currentUser,
    githubSignIn,
    githubSignOut,
  }

  return <AuthContext.Provider value={value}> {children} </AuthContext.Provider>
}

fbConfig.js 文件代码

export const createUserProfileDocument = async (userAuth) => {
  if (!userAuth) return
  const userRef = firestore.doc(`users/${userAuth.uid}`)
  const snapShot = await userRef.get()

  if (!snapShot.exists) {
    const { email, photoURL, providerData } = userAuth
    const createdAt = new Date()
    getGitHubUserData(providerData[0].uid)
      .then(async (gitHubUserData) => {
        const username = gitHubUserData.login
        try {
          await userRef.set({
            email,
            photoURL,
            createdAt,
            displayName: providerData[0].displayName,
            username,
          })
        } catch (error) {
          console.log(error.message)
        }
      })
      .catch((err) => console.error("Don't forget error handling: ", err))
  }
  return userRef
}

任何人都请帮助我。

对 GitHub 用户进行身份验证时,Firebase 会将以下信息存储在经过身份验证的用户的 ID 令牌 (auth.currentUser.providerData) 中:

{
  // User's GitHub display name
  displayName: "Display Name",
  // User's public email address, null when private/out-of-scope
  email: null,
  // Phone numbers aren't applicable. Always null.
  phoneNumber: null,
  // Link to user's GitHub profile image, may be hosted on Gravatar
  photoURL: "https://avatars.githubusercontent.com/u/GITHUB_ID?v=4",
  // Always "github.com" - used to identify this ProviderData entry
  providerId: "github.com",
  // Numeric Github User ID
  uid: "GITHUB_ID"
}

请注意,此数据的 none 提供了用户在 GitHub 上的用户名。这主要是因为 GitHub 用户可以随意更改他们的用户名,并且 GitHub 不会与 other side effects.

一起向任何连接的应用程序发送“新用户名”通知。

考虑到这一点,要将 GitHub 用户 ID 解析为他们的用户名,在 GitHub 上称为他们的 login,您可以查询 GitHub API 用户 ID:

https://api.github.com/user/{idOrLogin}

使用函数访问此数据得到:

async function getGitHubUserData(githubIdOrLogin) {
  return fetch(
    `https://api.github.com/user/${githubIdOrLogin}`,
    { headers: { 'Accept': 'application/json' } }
  )
    .then((response) => {
      if (!res.ok) {
        const err = new Error();
        err.response = res;
        if (res.status === 403 && res.headers.get('X-RateLimit-Remaining') == '0') {
          const resetsAtMS = Number(`${res.headers.get('X-RateLimit-Reset')}000`);
          err.message = `Rate limit exceeded, try again in ${Math.ceil((resetsAtMS-Date.now())/60000)}m`;
          err.code = "github/rate-limit-exceeded";
          err.resetsAt = resetsAtMS;
        } else if (res.status === 404) {
          err.message = `Could not find user data for github:${githubIdOrLogin}`);
          err.code = "github/not-found";
        } else { // add other cases if you want to handle them
          err.message = `Unexpected status code: ${res.status}`;
          err.code = "github/unknown";
        }
        return Promise.reject(err);
      }

      return res.json();
    });
}

然后就可以这样使用了:

const githubProviderData = auth.currentUser
  .providerData
  .find((pd) => pd.providerId === 'github.com');

getGitHubUserData(githubProviderData.uid)
  .then((githubUserData) => {
    // githubUserData.login will be their username
    // githubUserData.html_url will be a link to their profile
  })
  .catch((err) => console.error('Don\'t forget error handling: ', err));

备注:

  • 当匿名使用此 API 时(即无需身份验证),您将受到(在撰写本文时)该 IP 每小时 60 public API 次调用的限制地址。 GitHub 的速率限制超出响应代码是 403 Forbidden。如果您绑定用户的身份验证令牌,则此限制会对该用户增加到 5000 calls/hour。如果您使用 application/server 身份验证令牌,则此限制会增加到 12500 calls/hour。有关详细信息,请参阅 GitHub's documentation
  • 有可用的节点包消耗 GitHub API 像官方 @octokit/core, @octokit/request and @octokit/rest packages if you are doing more with the user's GitHub than just getting their username. See the GitHub request documentation 了解更多信息。 BVy使用@octokit/request,上面的代码可以简化为just(但错误处理不同):
request('GET /users/{username}', { username: idOrLogin })