> ## Documentation Index
> Fetch the complete documentation index at: https://exegia.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Provider setup

> The Supabase-side configuration that email/password does not need: OAuth providers, account linking, and passkey prerequisites.

Email/password, magic links and one-time codes work against a fresh local stack with no credentials at all. Everything below needs something only the project owner can supply.

<Note>
  For a local stack these values live in `supabase/config.toml`, which is read only at boot. After any change, run `supabase stop && supabase start`.
</Note>

## GitHub sign-in

Create an OAuth app at [github.com/settings/developers](https://github.com/settings/developers).

Set its **Authorization callback URL** to GoTrue, not to the plugin:

```
http://127.0.0.1:54321/auth/v1/callback
```

For a hosted project that is `https://<project>.supabase.co/auth/v1/callback`.

```bash theme={null}
export SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID=Ov23li...
export SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET=...
```

Then enable the provider:

```toml supabase/config.toml theme={null}
[auth.external.github]
enabled = true
```

## Google sign-in

Same shape, from [console.cloud.google.com](https://console.cloud.google.com/apis/credentials) → **OAuth client ID**, type *Web application*, with the same GoTrue callback URL.

```bash theme={null}
export SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID=...
export SUPABASE_AUTH_EXTERNAL_GOOGLE_SECRET=...
```

```toml supabase/config.toml theme={null}
[auth.external.google]
enabled = true
skip_nonce_check = true
```

<Warning>
  `skip_nonce_check = true` is required for loopback sign-in. The nonce cannot be verified over a local redirect.
</Warning>

## Apple sign-in

Apple does not fit the shape above, and the differences are the kind that cost an afternoon.

<Warning>
  **Apple sign-in cannot be tested against a local stack.** Apple rejects a Return URL that is `http://` or points at `localhost` / `127.0.0.1`, so `http://127.0.0.1:54321/auth/v1/callback` — the callback GitHub and Google use — cannot be registered on the Apple side at all. You need a hosted project, or an HTTPS tunnel terminating in front of GoTrue.
</Warning>

From [developer.apple.com](https://developer.apple.com/account/resources/identifiers/list/serviceId), create a **Services ID** — not an App ID. Its identifier is what GoTrue sends as `client_id`; the bundle ID of a native app is a different thing and will fail with `invalid_client`.

Set its **Return URL** to GoTrue:

```
https://<project>.supabase.co/auth/v1/callback
```

The client secret is not a string. Apple wants an **ES256-signed JWT** built from a `.p8` signing key, with `iss` set to your Team ID, `sub` to the Services ID, and `aud` to `https://appleid.apple.com`.

```bash theme={null}
export SUPABASE_AUTH_EXTERNAL_APPLE_CLIENT_ID=com.example.service
export SUPABASE_AUTH_EXTERNAL_APPLE_SECRET=eyJhbGciOiJFUzI1NiIs...
```

```toml supabase/config.toml theme={null}
[auth.external.apple]
enabled = true
```

<Warning>
  **The secret expires.** Apple refuses a client secret JWT dated more than six months out, so sign-in works for months and then starts failing with no code change and no deploy to blame. Rotate it on a calendar reminder, and keep the `.p8` — you need it to mint each replacement.
</Warning>

Two smaller differences worth knowing.

Apple sends the user's name **only on the very first authorization** for a given Apple ID, and never in the identity token — so there is nothing for GoTrue to populate `user_metadata` from on any later sign-in. Deleting the user server-side does not reset this: the authorization still exists on Apple's side, so they come back nameless. Only the user can restore it, by revoking the app under **Settings → Apple Account → Sign in with Apple** and authorizing again. If you need a display name, capture it on first sign-in or ask for it during onboarding.

Users may also sign in with **Hide My Email**, which mints a per-app `…@privaterelay.appleid.com` address that forwards to their real inbox. It is deliverable, but it is not their real address and the user can switch forwarding off per app at any time. Treat it as an identifier, not as a way to match an existing account by email.

## Redirect URLs

Every provider depends on `additional_redirect_urls`. The plugin binds the first free port from `oauth.callbackPorts` and asks GoTrue to redirect to `http://127.0.0.1:<port>/callback`. The list is matched exactly, so every candidate port must be present.

This is the hop *after* the provider, so the loopback address is fine here even for Apple — GoTrue redirects to it, Apple never sees it.

```toml supabase/config.toml theme={null}
[auth]
additional_redirect_urls = [
  "http://127.0.0.1:43823/callback",
  "http://127.0.0.1:43824/callback",
  "http://127.0.0.1:43825/callback",
]
```

Change `oauth.callbackPorts` in `tauri.conf.json` and this list has to change with it, or the round-trip dies after the consent screen with a redirect error that is not a structured plugin error.

## Account linking

```toml supabase/config.toml theme={null}
[auth]
enable_manual_linking = true
```

Off by default. Without it, `useIdentities()` can list identities but `link()` fails with a `configuration` error.

## Passkeys

The server side needs `[auth.passkey] enabled = true` plus the relying-party settings described in [Passkeys](/plugin/passkeys). What you supply beyond that is platform-dependent:

| Platform | What you need                                                                                                                                                                                                                                                                              |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Windows  | Nothing beyond `plugins.supabase-auth.passkeys.origin` in `tauri.conf.json`, listed in `rp_origins`                                                                                                                                                                                        |
| macOS    | An Apple Developer account, a provisioning profile whose App ID carries the Associated Domains capability, and an [AASA file](https://developer.apple.com/documentation/xcode/supporting-associated-domains) served over HTTPS at `https://<rp-id>/.well-known/apple-app-site-association` |
| Linux    | Not supported — supply your own ceremony via `PluginBuilder::ceremony_provider`                                                                                                                                                                                                            |

## Local development

```bash theme={null}
make supabase-up     # local stack; mail UI at http://127.0.0.1:54324
```

The mail UI catches confirmation and recovery messages, so email flows are testable end to end without a real inbox.
