Genesis
This commit is contained in:
97
src/auth/googleSignIn.js
Normal file
97
src/auth/googleSignIn.js
Normal file
@@ -0,0 +1,97 @@
|
||||
const GIS_SCRIPT = 'https://accounts.google.com/gsi/client';
|
||||
|
||||
let scriptPromise;
|
||||
|
||||
function loadGoogleScript() {
|
||||
if (window.google?.accounts?.id) return Promise.resolve();
|
||||
if (scriptPromise) return scriptPromise;
|
||||
|
||||
scriptPromise = new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = GIS_SCRIPT;
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.onload = () => resolve();
|
||||
script.onerror = () => reject(new Error('Failed to load Google Sign-In'));
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
|
||||
return scriptPromise;
|
||||
}
|
||||
|
||||
function clickRenderedGoogleButton(clientId, onCredential) {
|
||||
const container = document.createElement('div');
|
||||
container.style.cssText = 'position:fixed;left:-9999px;top:0;opacity:0;pointer-events:none;';
|
||||
document.body.appendChild(container);
|
||||
|
||||
window.google.accounts.id.renderButton(container, {
|
||||
type: 'standard',
|
||||
size: 'large',
|
||||
theme: 'outline',
|
||||
});
|
||||
|
||||
const button = container.querySelector('[role="button"]');
|
||||
if (!button) {
|
||||
container.remove();
|
||||
throw new Error('Could not open Google Sign-In');
|
||||
}
|
||||
|
||||
window.google.accounts.id.initialize({
|
||||
client_id: clientId,
|
||||
callback: (response) => {
|
||||
container.remove();
|
||||
onCredential(response.credential);
|
||||
},
|
||||
auto_select: false,
|
||||
cancel_on_tap_outside: true,
|
||||
});
|
||||
|
||||
button.click();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt for a Google ID token (One Tap, falling back to the sign-in popup).
|
||||
*/
|
||||
export async function requestGoogleIdToken(clientId) {
|
||||
if (!clientId) {
|
||||
throw new Error('Google client ID is not configured');
|
||||
}
|
||||
|
||||
await loadGoogleScript();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let settled = false;
|
||||
|
||||
const finish = (fn, value) => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
fn(value);
|
||||
};
|
||||
|
||||
window.google.accounts.id.initialize({
|
||||
client_id: clientId,
|
||||
callback: (response) => finish(resolve, response.credential),
|
||||
auto_select: false,
|
||||
cancel_on_tap_outside: true,
|
||||
});
|
||||
|
||||
window.google.accounts.id.prompt((notification) => {
|
||||
if (settled) return;
|
||||
|
||||
const needsFallback =
|
||||
notification.isNotDisplayed() ||
|
||||
notification.isSkippedMoment() ||
|
||||
notification.isDismissedMoment();
|
||||
|
||||
if (!needsFallback) return;
|
||||
|
||||
try {
|
||||
clickRenderedGoogleButton(clientId, (credential) =>
|
||||
finish(resolve, credential),
|
||||
);
|
||||
} catch (err) {
|
||||
finish(reject, err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user