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

<script src="https://accounts.google.com/gsi/client" async defer></script>

Option A: One-Tap / Button Sign-In (Recommended)

<!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

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:

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

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
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

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