apigateway / docs /CLIENT_INTEGRATION.md
jebin2's picture
google sign in
1bd7131
|
raw
history blame
7.68 kB
# 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
<script src="https://accounts.google.com/gsi/client" async defer></script>
```
---
## Option A: One-Tap / Button Sign-In (Recommended)
```html
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" async defer></script>
</head>
<body>
<!-- Google One Tap prompt -->
<div id="g_id_onload"
data-client_id="YOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.com"
data-callback="handleGoogleSignIn"
data-auto_prompt="false">
</div>
<!-- Sign In Button -->
<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>
const API_BASE = 'https://your-api-gateway.com'; // Change this
async function handleGoogleSignIn(response) {
try {
// Send Google token to your backend
const res = await fetch(`${API_BASE}/auth/google`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id_token: response.credential,
temp_user_id: localStorage.getItem('temp_user_id') // optional
})
});
const data = await res.json();
if (data.success) {
// Store the access token
localStorage.setItem('access_token', data.access_token);
localStorage.setItem('user', JSON.stringify({
user_id: data.user_id,
email: data.email,
name: data.name,
credits: data.credits
}));
console.log('Signed in!', data.is_new_user ? 'New user' : 'Existing user');
// Redirect or update UI
window.location.reload();
} else {
alert('Sign in failed: ' + (data.detail || 'Unknown error'));
}
} catch (error) {
console.error('Sign in error:', error);
alert('Sign in failed. Please try again.');
}
}
</script>
</body>
</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 (
<div>
<div id="g_id_onload"
data-client_id="YOUR_CLIENT_ID"
data-callback="handleGoogleSignIn" />
<div className="g_id_signin" data-type="standard" />
</div>
);
}
return <div>Welcome, {user.name}! Credits: {user.credits}</div>;
}
```