Raypx

OAuth (Google & GitHub)

Configuring Google and GitHub OAuth providers.

Raypx supports social sign-in with Google and GitHub. OAuth providers are loaded dynamically based on which environment variables are set, and each provider can be individually toggled with feature flags.

Google OAuth

Step 1: Create OAuth Credentials

  1. Go to the Google Cloud Console.
  2. Create a new project (or select an existing one).
  3. Navigate to APIs & Services > Credentials.
  4. Click Create Credentials > OAuth 2.0 Client ID.
  5. Set Application type to "Web application".
  6. Add Authorized redirect URIs: http://localhost:3000/api/auth/callback/google (and your production URL).
  7. Copy the Client ID and Client Secret.

Step 2: Set Environment Variables

.env
VITE_PUBLIC_AUTH_GOOGLE_ID=your-google-client-id.apps.googleusercontent.com
AUTH_GOOGLE_SECRET=your-google-client-secret
VITE_PUBLIC_AUTH_GOOGLE_ENABLED=true
VariableRequiredDescription
VITE_PUBLIC_AUTH_GOOGLE_IDYesGoogle OAuth Client ID (exposed to client).
AUTH_GOOGLE_SECRETYesGoogle OAuth Client Secret (server-only).
VITE_PUBLIC_AUTH_GOOGLE_ENABLEDNoSet to "false" to disable Google sign-in. Defaults to enabled.

GitHub OAuth

Step 1: Create OAuth App

  1. Go to GitHub Developer Settings.
  2. Click New OAuth App.
  3. Set Application name to your app name.
  4. Set Homepage URL to your app's URL.
  5. Set Authorization callback URL to http://localhost:3000/api/auth/callback/github.
  6. Copy the Client ID and generate a Client Secret.

Step 2: Set Environment Variables

.env
AUTH_GITHUB_ID=your-github-client-id
AUTH_GITHUB_SECRET=your-github-client-secret
VITE_PUBLIC_AUTH_GITHUB_ENABLED=true
VariableRequiredDescription
AUTH_GITHUB_IDYesGitHub OAuth Client ID (server-only).
AUTH_GITHUB_SECRETYesGitHub OAuth Client Secret (server-only).
VITE_PUBLIC_AUTH_GITHUB_ENABLEDNoSet to "false" to disable GitHub sign-in. Defaults to enabled.

Feature Flags

Both OAuth providers can be toggled independently without removing credentials:

# Disable Google (even if credentials are set)
VITE_PUBLIC_AUTH_GOOGLE_ENABLED=false

# Disable GitHub
VITE_PUBLIC_AUTH_GITHUB_ENABLED=false

The sign-in form checks these flags at render time and only shows the corresponding SocialButton when the provider is enabled.

Dynamic Provider Loading

OAuth providers are loaded dynamically in createAuth(). If credentials are missing, the provider is simply not registered:

packages/auth/src/index.ts
const socialProviders: Record<string, unknown> = {}

if (env.VITE_PUBLIC_AUTH_GOOGLE_ID && env.AUTH_GOOGLE_SECRET) {
  socialProviders.google = {
    clientId: env.VITE_PUBLIC_AUTH_GOOGLE_ID,
    clientSecret: env.AUTH_GOOGLE_SECRET,
  }
}

if (env.AUTH_GITHUB_ID && env.AUTH_GITHUB_SECRET) {
  socialProviders.github = {
    clientId: env.AUTH_GITHUB_ID,
    clientSecret: env.AUTH_GITHUB_SECRET,
  }
}

return betterAuth({
  socialProviders: Object.keys(socialProviders).length > 0
    ? socialProviders
    : undefined,
  // ...
})

This approach means you can safely commit .env.example with empty OAuth values. The providers will simply not appear in the sign-in UI until you configure real credentials.

Client Usage

SocialButton Component

Raypx provides a SocialButton component that handles OAuth sign-in:

import { SocialButton } from "@/components/social-button"
import { authClient } from "@/lib/auth-client"

<SocialButton
  provider="google"
  onClick={() => {
    authClient.signIn.social(
      { provider: "google" },
      {
        onSuccess: () => navigate({ to: "/dashboard" }),
        onError: (error) => {
          toast.error(error.error.message || "Google sign-in failed")
        },
      },
    )
  }}
/>

Direct API Usage

You can also call signIn.social() directly without the SocialButton component:

// Google
authClient.signIn.social({ provider: "google" }, { onSuccess, onError })

// GitHub
authClient.signIn.social({ provider: "github" }, { onSuccess, onError })

Conditional Rendering

The sign-in form only renders social buttons when the corresponding provider is enabled. Here is the pattern used in the built-in SignInForm:

const googleEnabled =
  typeof window !== "undefined" &&
  import.meta.env.VITE_PUBLIC_AUTH_GOOGLE_ID &&
  import.meta.env.VITE_PUBLIC_AUTH_GOOGLE_ENABLED !== "false"

const githubEnabled =
  typeof window !== "undefined" &&
  import.meta.env.VITE_PUBLIC_AUTH_GITHUB_ENABLED !== "false"

GitHub OAuth requires AUTH_GITHUB_ID and AUTH_GITHUB_SECRET to be set server-side. Unlike Google, these are not exposed to the client -- the client-side check only looks at the VITE_PUBLIC_AUTH_GITHUB_ENABLED flag.

On this page