# Google Sign-In Client Integration Guide Quick guide for frontend developers to integrate Google Sign-In with the APIGateway. ## Setup ### 1. Get Your Google Client ID Use the same `GOOGLE_CLIENT_ID` that's configured on the backend. ### 2. Add Google Identity Services Script ```html ``` --- ## Option A: One-Tap / Button Sign-In (Recommended) ```html
``` --- ## Option B: Programmatic Sign-In ```javascript const API_BASE = 'https://your-api-gateway.com'; // Initialize Google Sign-In function initGoogleSignIn(clientId) { google.accounts.id.initialize({ client_id: clientId, callback: handleGoogleSignIn }); // Render button in a container google.accounts.id.renderButton( document.getElementById('google-signin-btn'), { theme: 'outline', size: 'large', text: 'signin_with' } ); } // Handle the response async function handleGoogleSignIn(response) { const res = await fetch(`${API_BASE}/auth/google`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id_token: response.credential }) }); const data = await res.json(); if (data.success) { localStorage.setItem('access_token', data.access_token); } } // Call on page load window.onload = () => initGoogleSignIn('YOUR_CLIENT_ID.apps.googleusercontent.com'); ``` --- ## Making API Calls After sign-in, use the access token for all API calls: ```javascript const API_BASE = 'https://your-api-gateway.com'; async function apiCall(endpoint, options = {}) { const token = localStorage.getItem('access_token'); if (!token) { throw new Error('Not signed in'); } const response = await fetch(`${API_BASE}${endpoint}`, { ...options, headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', ...options.headers } }); if (response.status === 401) { // Token expired - need to sign in again localStorage.removeItem('access_token'); window.location.href = '/login'; return; } return response.json(); } // Examples async function getCurrentUser() { return apiCall('/auth/me'); } async function generateText(prompt) { return apiCall('/gemini/generate-text', { method: 'POST', body: JSON.stringify({ prompt }) }); } async function checkJobStatus(jobId) { return apiCall(`/gemini/job/${jobId}`); } ``` --- ## API Endpoints Reference | Endpoint | Method | Auth Required | Description | |----------|--------|---------------|-------------| | `/auth/google` | POST | ❌ | Sign in with Google token | | `/auth/me` | GET | ✅ | Get current user info | | `/auth/refresh` | POST | ❌ | Refresh access token | | `/gemini/generate-text` | POST | ✅ | Generate text (costs 1 credit) | | `/gemini/generate-video` | POST | ✅ | Generate video (costs 1 credit) | | `/gemini/job/{job_id}` | GET | ✅ | Check job status | --- ## Sign Out ```javascript function signOut() { localStorage.removeItem('access_token'); localStorage.removeItem('user'); // Optionally call logout endpoint for audit fetch(`${API_BASE}/auth/logout`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` } }); // Revoke Google session google.accounts.id.disableAutoSelect(); window.location.href = '/'; } ``` --- ## Error Handling | Status | Meaning | Action | |--------|---------|--------| | 401 | Token expired/invalid | Redirect to sign-in | | 402 | Insufficient credits | Show "buy credits" prompt | | 429 | Rate limited | Wait and retry | ```javascript async function apiCallWithErrorHandling(endpoint, options) { const response = await apiCall(endpoint, options); if (response.status === 402) { alert('You have run out of credits!'); return null; } return response; } ``` --- ## React Example ```jsx import { useEffect, useState } from 'react'; function App() { const [user, setUser] = useState(null); useEffect(() => { // Check if already signed in const token = localStorage.getItem('access_token'); if (token) { fetch('/auth/me', { headers: { 'Authorization': `Bearer ${token}` } }) .then(r => r.json()) .then(setUser) .catch(() => localStorage.removeItem('access_token')); } // Initialize Google Sign-In window.handleGoogleSignIn = async (response) => { const res = await fetch('/auth/google', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id_token: response.credential }) }); const data = await res.json(); if (data.success) { localStorage.setItem('access_token', data.access_token); setUser(data); } }; }, []); if (!user) { return (
); } return
Welcome, {user.name}! Credits: {user.credits}
; } ```