How to Set Up Supabase Authentication for the GPT-Image-2 Website

The GPT-Image-2 website uses Supabase Auth with Google OAuth for user sign-in, storing sessions via a singleton client in src/supabaseClient.js while reserving the service-role key for server-side credit and billing operations.

The freestylefly/awesome-gpt-image-2 repository implements a complete authentication and billing system using Supabase. Setting up Supabase authentication requires configuring the Google OAuth provider, applying database migrations for user credits and billing, and integrating the Supabase client wrapper into the React frontend.

Prerequisites and Project Structure

Before configuring authentication, ensure you have created a Supabase project at supabase.com. The repository relies on specific database tables and RPC functions defined in the migration files located in the supabase/migrations/ directory. These migrations establish the schema for tracking user credits, membership billing, and payment processing.

Key components you will configure include:

Configuring Supabase Auth in the Dashboard

To enable authentication, navigate to the Authentication → Settings section of your Supabase dashboard.

First, enable the Google provider by adding your Google Cloud Console Client ID and Client Secret. If you require a Google-only sign-in experience as implemented in the source code, disable the Email provider in the same settings panel.

Next, configure the Redirect URLs to include your production domain (e.g., https://gpt-image2.canghe.ai) and local development URLs (e.g., http://localhost:5173). This allows Supabase to return users to the correct endpoint after successful OAuth authentication.

Database Schema and Migrations

The authentication system relies on tables and functions defined in the migration files. Execute these SQL files against your Supabase database via the SQL Editor or CLI:

These migrations create the backend infrastructure that stores user data and handles credit deductions when users generate images.

Client-Side Integration

Initializing the Supabase Client

The src/supabaseClient.js file creates a singleton client instance that the entire frontend uses to interact with Supabase Auth. This file reads the public environment variables prefixed with VITE_ (Vite-specific) to ensure they are available at runtime.

// src/supabaseClient.js
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;

export const supabase = createClient(supabaseUrl, supabaseAnonKey);

Implementing Google OAuth Sign-In

To trigger authentication, components call supabase.auth.signInWithOAuth() with the Google provider. This method redirects the user to Google's consent screen and handles the OAuth flow automatically.

// Example component implementation
import { supabase } from '../supabaseClient';

export default function SignInButton() {
  const handleLogin = async () => {
    const { error } = await supabase.auth.signInWithOAuth({ 
      provider: 'google' 
    });
    if (error) console.error('Authentication error:', error);
  };

  return (
    <button onClick={handleLogin} className="google-btn">
      Sign in with Google
    </button>
  );
}

Handling Authentication State

The entry point src/main.jsx initializes the application and can check for existing sessions using supabase.auth.getUser(). Protected routes should verify the current user before rendering sensitive components.

// src/components/ProtectedRoute.jsx
import { useEffect, useState } from 'react';
import { supabase } from '../supabaseClient';
import { Navigate } from 'react-router-dom';

export default function ProtectedRoute({ children }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    supabase.auth.getUser().then(({ data: { user } }) => {
      setUser(user);
      setLoading(false);
    });
  }, []);

  if (loading) return <div>Loading…</div>;
  return user ? children : <Navigate to="/login" />;
}

Server-Side Privileged Operations

For operations requiring elevated privileges—such as adjusting user credits or processing payments—the application uses the Service Role Key. This key bypasses Row Level Security (RLS) and must never be exposed to the browser. Server-side API routes (e.g., api/billing/checkout.js) initialize a separate client instance using SUPABASE_SERVICE_ROLE_KEY.

// Server-side API route example
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.VITE_SUPABASE_URL,
  process.env.SUPABASE_SERVICE_ROLE_KEY
);

export default async function handler(req, res) {
  const { userId, adjustment } = req.body;
  const { data, error } = await supabase.rpc('adjust_user_credits', {
    uid: userId,
    delta: adjustment,
  });

  if (error) return res.status(500).json({ error });
  res.status(200).json({ data });
}

Environment Variables Configuration

Create a .env file based on the repository's .env.example template. The following variables are required:

  • VITE_SUPABASE_URL: Your Supabase project URL (public)
  • VITE_SUPABASE_ANON_KEY: Your Supabase anonymous/public key (public)
  • SUPABASE_SERVICE_ROLE_KEY: Your Supabase service role key (server-only)

When deploying to Vercel as specified in the README, add these variables to your project settings. The VITE_ prefix ensures Vite exposes these variables to the client-side code, while the service role key remains server-side only.

Summary

  • Create a Supabase project and run the migration files in supabase/migrations/ to establish the user credits and billing schema
  • Enable Google OAuth in Authentication → Settings and optionally disable Email authentication for a Google-only flow
  • Configure redirect URLs for both production and local development environments
  • Initialize the client in src/supabaseClient.js using VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY
  • Use supabase.auth.signInWithOAuth({ provider: 'google' }) to trigger sign-in from the frontend
  • Reserve SUPABASE_SERVICE_ROLE_KEY for server-side operations that modify user credits or billing data
  • Reference src/main.jsx for initialization patterns and implement protected routes using supabase.auth.getUser()

Frequently Asked Questions

How do I disable email authentication and force Google-only sign-in?

Navigate to Authentication → Settings in your Supabase dashboard and disable the Email provider while keeping the Google provider enabled. This configuration matches the repository's intended authentication flow where users must sign in with Google.

What is the difference between the Anon Key and the Service Role Key?

The Anon Key is safe to expose in browser code and respects Row Level Security (RLS) policies. The Service Role Key has full database access and bypasses RLS, making it suitable for server-side operations like adjusting credits via the adjust_user_credits RPC function. Never expose the Service Role Key in client-side code.

Which migration files are required for the authentication system to function?

You must execute 202605090001_user_credits.sql for basic credit tracking and 20260509090000_membership_billing.sql for subscription management. The 20260721090000_alipay_webpay.sql migration is only necessary if you plan to support Alipay payments. These files create the tables and RPC functions that the frontend expects when calling credit-related operations.

How does the frontend maintain the user session after sign-in?

The Supabase client stores the session in localStorage automatically. Components can retrieve the current user by calling supabase.auth.getUser(), which returns the user object and JWT. This session persists across page reloads until the user signs out or the token expires.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →