Skip to content
zap.ts
Esc
navigateopen⌘Jpreview
On this page

Add an OAuth provider

Let people sign in with GitHub, or any other provider, next to the Google sign-in that already ships.

OAuth lets a person sign in with an account they already have, such as Google or GitHub. They never create a password on your site.

zap.ts ships with Google already working. This page adds a second provider. The example uses GitHub. Every provider follows the same four steps.

Where the provider is set

Sign-in is configured in packages/authentication/src/auth.ts.

Look for this line:

socialProviders: { google },

socialProviders is the list. Right now it holds one entry. You are going to add a second.

Just above, the keys come from a typed config object:

export interface AuthConfig {
  connectionString: string;
  baseURL: string;
  secret: string;
  google: { clientId: string; clientSecret: string };
}

So adding a provider means touching four places: the settings file, this interface, where the config is built, and the socialProviders list.

Step 1. Get your keys

Create an OAuth app in the provider’s own dashboard. For GitHub, that is under your developer settings.

It asks for a callback URL. Use this one while you develop:

http://localhost:3000/api/auth/callback/github

Change github to the provider’s name if you use a different one. You get back a client ID and a client secret.

Step 2. Declare the two keys

Open the root .env.schema. Find the GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET lines and copy their shape:

# GitHub
# @docs(https://docs.github.com/apps/oauth-apps)
GITHUB_CLIENT_ID=local_dev_github_client_id

# @sensitive
GITHUB_CLIENT_SECRET=local_dev_github_client_secret

@sensitive matters. It keeps the secret out of the browser and hides it in logs. Copy how the Google secret is marked and do the same.

Put your real values in a .env.local file next to the schema. That file is never saved to git. See Environment.

Step 3. Pass the keys through

In packages/authentication/src/auth.ts, add the provider to the config interface:

export interface AuthConfig {
  connectionString: string;
  baseURL: string;
  secret: string;
  google: { clientId: string; clientSecret: string };
  github: { clientId: string; clientSecret: string };
}

Then add it to the list:

socialProviders: { google, github },

Finally, find where the config is built from the environment, and read your two new values there, exactly as the Google ones are read.

Step 4. Add the button

The sign-in form needs a button for the new provider.

The call is the same one Google uses, with a different name:

await authClient.signIn.social({ provider: "github" });

Find the existing Google button in the sign-in form and copy it. Change the provider name and the label.

Try it

Restart the app. Click your new button. You should land on GitHub, approve, and come back signed in.

If nothing happens, the callback URL is almost always the problem. It must match what you registered, character for character, including the port.

In production

Register a second callback URL with your real domain:

https://app.your-domain.com/api/auth/callback/github

Most providers let you register several. Keep the localhost one so local development keeps working.

Then set the two keys for your deployed app. See Going to production.

Last updated on September 22, 2026

Was this page helpful?