Sign In

We're the bridge between marketing ambition and financial wisdom. Born from the frustration of seeing e-commerce companies chase growth at any cost, we built a platform that turns complex customer data into simple profit signals.

Ready to turn your marketing budget into pure rocket fuel? 🚀

Drop us a line at hello@headw.ai and let's explore how we can boost your ROI. (We promise the demo will be worth your time!)

© Copyright 2026 Headwai. All Rights Reserved.

    Legal
    • Privacy Policy

    OAuth

    Sign in with Google, GitHub, and other OAuth providers.

    Note: This is mock/placeholder content for demonstration purposes.

    Allow users to sign in with their existing accounts from Google, GitHub, and other providers.

    Supported Providers

    Supabase supports many OAuth providers:

    • Google
    • GitHub
    • GitLab
    • Bitbucket
    • Azure
    • Facebook
    • Twitter
    • Discord
    • Slack
    • And more...

    Setting Up OAuth

    Configure in Supabase Dashboard

    1. Go to Authentication → Providers
    2. Enable your desired provider (e.g., Google)
    3. Add your OAuth credentials:
      • Client ID
      • Client Secret
      • Redirect URL: https://your-project.supabase.co/auth/v1/callback

    Google OAuth Setup

    1. Go to Google Cloud Console
    2. Create a new project or select existing
    3. Enable Google+ API
    4. Create OAuth 2.0 credentials
    5. Add authorized redirect URIs:
      • Production: https://your-project.supabase.co/auth/v1/callback
      • Development: http://localhost:54321/auth/v1/callback

    GitHub OAuth Setup

    1. Go to GitHub Settings → Developer Settings → OAuth Apps
    2. Click "New OAuth App"
    3. Fill in details:
      • Application name: Your App
      • Homepage URL: https://yourapp.com
      • Authorization callback URL: https://your-project.supabase.co/auth/v1/callback
    4. Copy Client ID and Client Secret to Supabase

    Implementation

    OAuth Sign In Button

    'use client';
    
    import { signInWithOAuthAction } from '../_lib/actions';
    
    export function OAuthButtons() {
      const handleGoogleSignIn = async () => {
        await signInWithOAuthAction('google');
      };
    
      const handleGitHubSignIn = async () => {
        await signInWithOAuthAction('github');
      };
    
      return (
        <div className="space-y-2">
          <button
            onClick={handleGoogleSignIn}
            className="w-full flex items-center justify-center gap-2 border rounded-lg p-2"
          >
            <GoogleIcon />
            Continue with Google
          </button>
    
          <button
            onClick={handleGitHubSignIn}
            className="w-full flex items-center justify-center gap-2 border rounded-lg p-2"
          >
            <GitHubIcon />
            Continue with GitHub
          </button>
        </div>
      );
    }
    

    Server Action

    'use server';
    
    import { enhanceAction } from '@kit/next/actions';
    import { getSupabaseServerClient } from '@kit/supabase/server-client';
    import { z } from 'zod';
    
    const OAuthProviderSchema = z.enum([
      'google',
      'github',
      'gitlab',
      'azure',
      'facebook',
    ]);
    
    export const signInWithOAuthAction = enhanceAction(
      async (provider) => {
        const client = getSupabaseServerClient();
        const origin = process.env.NEXT_PUBLIC_SITE_URL!;
    
        const { data, error } = await client.auth.signInWithOAuth({
          provider,
          options: {
            redirectTo: `${origin}/auth/callback`,
          },
        });
    
        if (error) throw error;
    
        // Redirect to OAuth provider
        redirect(data.url);
      },
      {
        schema: OAuthProviderSchema,
      }
    );
    

    OAuth Callback Handler

    // app/auth/callback/route.ts
    import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
    import { cookies } from 'next/headers';
    import { NextResponse } from 'next/server';
    
    export async function GET(request: Request) {
      const requestUrl = new URL(request.url);
      const code = requestUrl.searchParams.get('code');
    
      if (code) {
        const cookieStore = cookies();
        const supabase = createRouteHandlerClient({ cookies: () => cookieStore });
    
        await supabase.auth.exchangeCodeForSession(code);
      }
    
      // Redirect to home page
      return NextResponse.redirect(new URL('/home', request.url));
    }
    

    Customizing OAuth Flow

    Scopes

    Request specific permissions:

    await client.auth.signInWithOAuth({
      provider: 'google',
      options: {
        scopes: 'email profile https://www.googleapis.com/auth/calendar',
      },
    });
    

    Query Parameters

    Pass custom parameters:

    await client.auth.signInWithOAuth({
      provider: 'azure',
      options: {
        queryParams: {
          prompt: 'consent',
          access_type: 'offline',
        },
      },
    });
    

    Skip Browser Redirect

    For mobile apps or custom flows:

    const { data } = await client.auth.signInWithOAuth({
      provider: 'google',
      options: {
        skipBrowserRedirect: true,
      },
    });
    
    // data.url contains the OAuth URL
    // Handle redirect manually
    

    Account Linking

    Linking Additional Providers

    Allow users to link multiple OAuth accounts:

    export const linkOAuthProviderAction = enhanceAction(
      async (provider) => {
        const client = getSupabaseServerClient();
        const user = await requireAuth();
    
        const { data, error } = await client.auth.linkIdentity({
          provider,
        });
    
        if (error) throw error;
    
        redirect(data.url);
      },
      { schema: OAuthProviderSchema, auth: true }
    );
    

    Unlinking Providers

    export const unlinkOAuthProviderAction = enhanceAction(
      async ({ provider, identityId }) => {
        const client = getSupabaseServerClient();
    
        const { error } = await client.auth.unlinkIdentity({
          identity_id: identityId,
        });
    
        if (error) throw error;
    
        revalidatePath('/settings/security');
      },
      {
        schema: z.object({
          provider: z.string(),
          identityId: z.string(),
        }),
        auth: true,
      }
    );
    

    Viewing Linked Identities

    import { getSupabaseServerClient } from '@kit/supabase/server-client';
    
    export async function getLinkedIdentities() {
      const client = getSupabaseServerClient();
      const { data: { user } } = await client.auth.getUser();
    
      return user?.identities || [];
    }
    

    User Data from OAuth

    Accessing Provider Data

    const { data: { user } } = await client.auth.getUser();
    
    // User metadata from provider
    const {
      full_name,
      avatar_url,
      email,
    } = user.user_metadata;
    
    // Provider-specific data
    const identities = user.identities || [];
    const googleIdentity = identities.find(i => i.provider === 'google');
    
    console.log(googleIdentity?.identity_data);
    

    Storing Additional Data

    export const completeOAuthProfileAction = enhanceAction(
      async (data) => {
        const client = getSupabaseServerClient();
        const user = await requireAuth();
    
        // Update user metadata
        await client.auth.updateUser({
          data: {
            username: data.username,
            bio: data.bio,
          },
        });
    
        // Update profile in database
        await client.from('profiles').upsert({
          id: user.id,
          username: data.username,
          bio: data.bio,
          avatar_url: user.user_metadata.avatar_url,
        });
    
        redirect('/home');
      },
      { schema: ProfileSchema, auth: true }
    );
    

    Configuration

    Enable OAuth in Config

    // config/auth.config.ts
    export const authConfig = {
      providers: {
        emailPassword: true,
        oAuth: ['google', 'github'],
      },
    };
    

    Conditional Rendering

    import { authConfig } from '~/config/auth.config';
    
    export function AuthProviders() {
      return (
        <>
          {authConfig.providers.emailPassword && <EmailPasswordForm />}
    
          {authConfig.providers.oAuth?.includes('google') && (
            <GoogleSignInButton />
          )}
    
          {authConfig.providers.oAuth?.includes('github') && (
            <GitHubSignInButton />
          )}
        </>
      );
    }
    

    Troubleshooting

    Redirect URI Mismatch

    Ensure redirect URIs match exactly:

    • Check Supabase Dashboard → Authentication → URL Configuration
    • Verify OAuth app settings in provider console
    • Use exact URLs (including http/https)

    Missing Email

    Some providers don't share email by default:

    const { data: { user } } = await client.auth.getUser();
    
    if (!user.email) {
      // Request email separately or prompt user
      redirect('/auth/complete-profile');
    }
    

    Rate Limiting

    OAuth providers may rate limit requests:

    • Cache OAuth tokens appropriately
    • Don't make excessive authorization requests
    • Handle rate limit errors gracefully

    Best Practices

    1. Request minimum scopes - Only ask for what you need
    2. Handle errors gracefully - OAuth can fail for many reasons
    3. Verify email addresses - Some providers don't verify emails
    4. Support account linking - Let users connect multiple providers
    5. Provide fallback - Always offer email/password as backup
    6. Log OAuth events - Track sign-ins and linking attempts
    7. Test thoroughly - Test with real provider accounts