I'm migrating from Google Sign-in platform to the newer Google Identity Services library.
App.svelte:
<svelte:head>
<script src="https://accounts.google.com/gsi/client" async defer></script>
</svelte:head>
<div id="g_id_onload"
data-client_id="x.apps.googleusercontent.com"
data-callback="handleCredentialResponse">
</div>
<div class="g_id_signin"
data-type="standard"
data-size="large"
data-theme="outline"
data-text="sign_in_with"
data-shape="rectangular"
data-logo_alignment="left">
</div>
<script>
function decodeJwtResponse(token) {
let base64Url = token.split('.')[1]
let base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
let jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload)
}
let responsePayload;
function handleCredentialResponse(response) {
// decodeJwtResponse() is a custom function defined by you
// to decode the credential response.
responsePayload = decodeJwtResponse(response.credential);
console.log("ID: " + responsePayload.sub);
console.log('Full Name: ' + responsePayload.name);
console.log('Given Name: ' + responsePayload.given_name);
console.log('Family Name: ' + responsePayload.family_name);
console.log("Image URL: " + responsePayload.picture);
console.log("Email: " + responsePayload.email);
}
</script>
Reloading the page and I saw this error in the console:
[GSI_LOGGER]: The value of 'callback' is not a function. Configuration ignored.
What is the problem?
After many hours searching, I found this answer: Call Svelte component's function from global scope
Simply, handleCredentialResponse needs to be global (window) scope.
JavaScript
window.handleCredentialResponse = (response) => {
// decodeJwtResponse() is a custom function defined by you
// to decode the credential response.
responsePayload = decodeJwtResponse(response.credential);
console.log("ID: " + responsePayload.sub);
console.log('Full Name: ' + responsePayload.name);
console.log('Given Name: ' + responsePayload.given_name);
console.log('Family Name: ' + responsePayload.family_name);
console.log("Image URL: " + responsePayload.picture);
console.log("Email: " + responsePayload.email);
}
TypeScript
You need to modify Window interface so that TS won't raise error: How do you explicitly set a new property on `window` in TypeScript?
// global.d.ts
export {};
declare global {
interface Window {
handleCredentialResponse: (response: any) => void;
}
}
Looks like we have to render the Sign In With Google button by using Javascript.
<svelte:head>
<script src="https://accounts.google.com/gsi/client" async defer on:load={googleLoaded}></script>
</svelte:head>
<script>
import { onMount } from 'svelte';
let googleReady = false;
let mounted = false;
onMount(() => {
mounted = true;
if (googleReady) {
displaySignInButton()
}
});
function googleLoaded() {
googleReady = true;
if (mounted) {
displaySignInButton()
}
}
function displaySignInButton() {
google.accounts.id.initialize({
client_id: "x.apps.googleusercontent.com",
callback: handleCredentialResponse
});
google.accounts.id.renderButton(
document.getElementById("buttonDiv"),
{ theme: "outline", size: "large" } // customization attributes
);
google.accounts.id.prompt(); // also display the One Tap dialog
}
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