I have been trying to implement Google's identity services API in my React app, but couldn't get it to work.
I'm trying to implement the following really simple JS code: https://developers.google.com/identity/gsi/web/guides/display-button#javascript
What I came up with is the following:
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
When I call this component in my main App it sometimes renders the button, sometimes it doesn't (and the cause of this seems to be react-router-dom as it won't load if I'm moving from another page in my domain to where the button is). And even when I get the render I get errors and I can't login.
Thanks to Bogdanof's answer solved the problem of the button only appearing sometimes through the use of Promises.
Now my only problem is the following:
[GSI_LOGGER]: The given origin is not allowed for the given client ID.
I have made and ID OAuth2.0 on Google only for this App. I enabled http://localhost:3000 as it's JS origin (and the same for the URIs), but I'm still getting that answer. I tried changing browsers and even deleting my cache and cookies as I read that it may help, but nothing worked.
Someone has any ideas about how to solve this?
Hey so I got the final result, the following code doesn't has any problem with rendering the button thanks to the use of Promises (again thanks bogdanoff for his help with this):
//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
Then for solving the OAuth problem I found the solution here in Crow's answer: The given origin is not allowed for the given client ID (GSI)
Basically add http://localhost without a port to your origins (dunno why gsi needs this, but it needs it)
Hope this helps someone
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With