反应谷歌身份服务

Tom*_*más 8 javascript reactjs google-identity

我一直在尝试在我的 React 应用程序中实现 Google 的身份服务 API,但无法让它工作。

我正在尝试实现以下非常简单的 JS 代码:https://developers.google.com/identity/gsi/web/guides/display-button#javascript

我想出的是以下内容:

  useEffect(() => {
    //I'm adding the <script>
    const elemScript = document.createElement('script'); 
    elemScript.src = "https://accounts.google.com/gsi/client";
    elemScript.async = true;
    elemScript.defer = true;
    document.body.append(elemScript);

    //adding the code from the documentation
    window.onload = function () {
      /*global google*/
      console.log(google)
      google.accounts.id.initialize({
        client_id: "<don't worry, I put the ID here>",
        callback: handleCredentialResponse
      });
      google.accounts.id.renderButton(
        googleButton.current, //this is a ref hook to the div in the official example
        { theme: "outline", size: "large" }  // customization attributes
      );
    }

    return () => {
      //I get ride of the <scripts> when the elements is unmounted
      document.body.removeChild(elemScript);
    }
  }, [])

  //This is my main and only objective, to get the token...
  function handleCredentialResponse(response) {
    console.log("Encoded JWT ID token: " + response.credential);
  }

  return (
    <div ref={googleButton}></div>
  )
}

export default GoogleAuth
Run Code Online (Sandbox Code Playgroud)

当我在主应用程序中调用此组件时,它有时会呈现按钮,有时不会(其原因似乎是react-router-dom,因为如果我从我的另一个页面移动,它就不会加载)域到按钮所在的位置)。即使当我得到渲染时,我也会收到错误并且无法登录。

感谢 Bogdanof 的回答解决了按钮仅通过使用 Promise 有时出现的问题。

现在我唯一的问题如下:

[GSI_LOGGER]: The given origin is not allowed for the given client ID.

我已经在Google上为这个应用程序制作了ID OAuth2.0。我启用了 http://localhost:3000,因为它是 JS 来源(对于 URI 也是如此),但我仍然得到这个答案。我尝试更换浏览器,甚至删除我的缓存和 cookie,因为我读到这可能会有所帮助,但没有任何效果。

有人对如何解决这个问题有任何想法吗?

Tom*_*más 17

嘿,所以我得到了最终结果,由于使用了 Promises,以下代码在渲染按钮时没有任何问题(再次感谢 bogdanoff 对此的帮助):

//External imports
import { useEffect, useRef } from 'react'

  const loadScript = (src) =>
  new Promise((resolve, reject) => {
    if (document.querySelector(`script[src="${src}"]`)) return resolve()
    const script = document.createElement('script')
    script.src = src
    script.onload = () => resolve()
    script.onerror = (err) => reject(err)
    document.body.appendChild(script)
  })

const GoogleAuth = () => {

  const googleButton = useRef(null);

  useEffect(() => {
    const src = 'https://accounts.google.com/gsi/client'
    const id = "< your ID here ;) >"

    loadScript(src)
      .then(() => {
        /*global google*/
        console.log(google)
        google.accounts.id.initialize({
          client_id: id,
          callback: handleCredentialResponse,
        })
        google.accounts.id.renderButton(
          googleButton.current, 
          { theme: 'outline', size: 'large' } 
        )
      })
      .catch(console.error)

    return () => {
      const scriptTag = document.querySelector(`script[src="${src}"]`)
      if (scriptTag) document.body.removeChild(scriptTag)
    }
  }, [])

  function handleCredentialResponse(response) {
    console.log("Encoded JWT ID token: " + response.credential);
  }

  return (
    <div ref={googleButton}></div>
  )
}

export default GoogleAuth
Run Code Online (Sandbox Code Playgroud)

然后,为了解决 OAuth 问题,我在 Crow 的回答中找到了解决方案:给定的客户端 ID (GSI) 不允许给定的来源

基本上将没有端口的 http://localhost 添加到您的源(不知道为什么 gsi 需要这个,但它需要它)

希望这对某人有帮助