# Sign in with GitHub

> Add GitHub sign-in to a SupaHost project: register a GitHub OAuth app with your project's callback URL, paste the Client ID and secret into the Auth tab, and call signInWithOAuth.

Source: https://supahost.app/docs/auth/github · Updated 2026-11-11

GitHub sign-in is a good fit for developer tools, internal dashboards and anything where your users already live on GitHub. You register an OAuth app on GitHub, give it your project's callback URL, and paste its credentials into SupaHost.

## What you need

- A GitHub account (personal or an organization you administer).
- Your project's callback URL from *Dashboard → your project → **Auth** tab → **OAuth providers***. For project `app-one` on instance `acme`:

```
https://app-one.acme.supahost.space/auth/v1/callback
```

If an active custom domain is shown there instead, use that.

## 1. Register an OAuth app on GitHub

1. Go to **GitHub → Settings → Developer settings → OAuth Apps** ([github.com/settings/developers](https://github.com/settings/developers)). For an organization-owned app, use the organization's **Settings → Developer settings** instead.
2. Click **New OAuth App**.
3. Fill in:
   - **Application name**: what users see on the consent screen, such as "Standup Notes".
   - **Homepage URL**: your app's public URL, such as `https://standup.example.com`.
   - **Authorization callback URL**: the SupaHost callback URL.
4. Click **Register application**.
5. Copy the **Client ID**, then click **Generate a new client secret** and copy the secret. GitHub shows it only once.

A GitHub OAuth app has a single callback URL, so create one OAuth app per SupaHost project. A common setup is one app for production and one for a staging project or branch.

Use an **OAuth App**, not a GitHub App, for sign-in. GitHub Apps are built for acting on repositories and have a different token model.

## 2. Turn on GitHub in SupaHost

1. *Dashboard → your project → **Auth** tab → **OAuth providers***, click **GitHub**.
2. Switch on **Enabled**.
3. Paste the **Client ID** and **Client secret**.
4. Click **Save GitHub**.

On the **Auth** card, make sure the pages you'll return to are in **Redirect URLs**:

```
http://localhost:5173/**
https://standup.example.com/**
```

Click **Save Auth settings**. Both changes reach the project within about a minute.

## 3. Sign in from your app

```ts
const { error } = await supabase.auth.signInWithOAuth({
  provider: 'github',
  options: { redirectTo: `${window.location.origin}/auth/callback` },
})
```

For server-rendered apps, start the flow on the server and exchange the returned `code` in a callback route. See [Server-side auth](/docs/auth/server-side).

After the redirect, the user's GitHub profile is in `user_metadata`: `user_name`, `full_name`, `avatar_url` and `email`, among others. For example, to show their avatar:

```ts
const { data: { user } } = await supabase.auth.getUser()
const avatar = user?.user_metadata.avatar_url
const handle = user?.user_metadata.user_name
```

## Asking for more access

By default Auth asks GitHub for the user's profile and email. Add scopes when you need to call GitHub's API, for example to list the user's organizations:

```ts
await supabase.auth.signInWithOAuth({
  provider: 'github',
  options: { scopes: 'read:org', redirectTo },
})
```

The `provider_token` in the session right after sign-in is a GitHub access token with those scopes. Use it from your server:

```ts
const res = await fetch('https://api.github.com/user/orgs', {
  headers: { Authorization: `Bearer ${providerToken}`, Accept: 'application/vnd.github+json' },
})
```

Auth doesn't store this token, so save it yourself at sign-in if you need it later.

## Limiting sign-in to your organization

Auth signs in anyone with a GitHub account. To restrict an internal tool to members of your organization, check membership yourself after sign-in (with `read:org` and the API call above) and record the result somewhere only your server can write, such as `app_metadata` set through the admin API. Then make your policies check it. See [Roles, custom claims and RBAC](/docs/auth/custom-claims-rbac).

## Users with a private email

Some GitHub users hide their email address. Auth still receives a verified email from GitHub's API in most cases, but a few accounts have none that can be shared. Handle a user whose `email` is empty instead of assuming it's always set.

If a GitHub user's email matches an existing user who signed up with a password or another provider, and the email is verified, Auth links the GitHub identity to that existing user. See [Linking identities](/docs/auth/identity-linking).

## Troubleshooting

| Problem | Fix |
|---|---|
| "The redirect_uri is not associated with this application" | The Authorization callback URL on GitHub doesn't match SupaHost's callback URL exactly |
| You return to the Site URL instead of your page | Add the `redirectTo` URL to Redirect URLs |
| Worked before, fails after adding a custom domain | Change the Authorization callback URL to the custom-domain callback. See [OAuth after a custom domain](/kb/oauth-after-custom-domain) |
| You come back with an error like "Unable to exchange external code" | The client secret is wrong or was regenerated on GitHub. Generate a new one and save it in SupaHost |

Other providers follow the same pattern. See [Every OAuth provider](/docs/auth/oauth-providers).
