---
title: Add an OAuth provider
description: 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:

```ts
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:

```ts
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:

```bash
# 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](/guides/environment).

## Step 3. Pass the keys through

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

```ts
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:

```ts
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:

```ts
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](/guides/going-to-production).

## Related

- [Authentication](/packages/authentication) — what else sign-in gives you
- [Environment](/guides/environment) — declaring keys safely
- [Web](/apps/web) — where the sign-in form lives
- [Going to production](/guides/going-to-production) — the full checklist
