# 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}
;
}
```