Self-Hosting

Configure Social Login (OAuth) Providers

Set up social login (OAuth/OIDC) providers for self-hosted Supabase with Docker.


This guide covers the server-side configuration required to enable social login providers on a self-hosted Supabase instance running with Docker Compose. This applies to all OAuth and OIDC-based providers, including third-party identity providers like Keycloak.

Before you begin#

You need:

  • A working self-hosted Supabase installation. See Self-Hosting with Docker.
  • API_EXTERNAL_URL set to the publicly reachable URL of your Supabase instance (e.g., https://<your-domain>).

Your OAuth callback URL is built from API_EXTERNAL_URL. For example, if API_EXTERNAL_URL is https://<your-domain>, the callback URL will become:

1
https://<your-domain>/auth/v1/callback

You will have to register this URL with each OAuth provider.

OAuth request flow#

When a user signs in with an OAuth provider, the following flow occurs:

  1. Your app calls supabase.auth.signInWithOAuth() and the browser redirects to the Auth service
  2. API gateway (Kong) routes the request to the Auth container (/auth/v1/authorize)
  3. Auth redirects the user to the OAuth provider (e.g., Google) for consent
  4. The provider redirects back to https://<your-domain>/auth/v1/callback
  5. Auth exchanges the authorization code for tokens and redirects the user to your SITE_URL or an allowed redirect URL

Auth environment variables#

The Auth service (GoTrue) uses the prefix GOTRUE_EXTERNAL_ followed by a provider name for all OAuth configuration. For example, when using Google:

  • GOTRUE_EXTERNAL_GOOGLE_ENABLED
  • GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID
  • GOTRUE_EXTERNAL_GOOGLE_SECRET
  • GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI

Step-by-step configuration#

The default .env.example and docker-compose.yml include commented-out placeholders for Google, GitHub, and Azure.

Step 1: Register your app with the provider#

  1. Go to the OAuth provider's developer console and create an application.
  2. Set the authorized redirect URL, e.g., https://<your-domain>/auth/v1/callback
  3. Copy the client ID and client secret into your .env file.

Step 2: Configure variables in the .env file#

Uncomment the lines for your provider in .env and add your client ID and secret, e.g., for Google:

1
GOOGLE_ENABLED=true
2
GOOGLE_CLIENT_ID=your-client-id
3
GOOGLE_SECRET=your-client-secret

Step 3: Enable the matching lines in docker-compose.yml#

Uncomment the corresponding GOTRUE_EXTERNAL_ lines in the auth service's environment:

1
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
2
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
3
GOTRUE_EXTERNAL_GOOGLE_SECRET: ${GOOGLE_SECRET}
4
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI: ${API_EXTERNAL_URL}/auth/v1/callback

Step 4: Restart the auth service#

1
docker compose up -d --force-recreate --no-deps auth

Step 5: Verify the configuration#

Check that the provider is enabled:

1
curl https://<your-domain>/auth/v1/settings

The response should include your provider under external:

1
{
2
"external": {
3
"google": true
4
}
5
}

Provider-specific setup#

Google Cloud Console setup:

  1. Go to Google Cloud Console
  2. Create or select a project
  3. Select Solutions > All products in the navigation menu on the left
  4. Go to APIs & services > OAuth consent screen and click Get started
  5. Follow the configuration steps and add an External app
  6. Go to APIs & Services > Credentials
  7. Click Create Credentials > OAuth client ID
  8. Set application type to Web application
  9. Under Authorized redirect URIs, add: https://<your-domain>/auth/v1/callback
  10. Click Create and copy the client ID and client secret

.env:

1
GOOGLE_ENABLED=true
2
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
3
GOOGLE_SECRET=your-google-client-secret

docker-compose.yml:

1
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
2
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
3
GOTRUE_EXTERNAL_GOOGLE_SECRET: ${GOOGLE_SECRET}
4
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI: ${API_EXTERNAL_URL}/auth/v1/callback

Other supported providers#

Supabase Auth supports the following OAuth providers:

ProviderEnv prefixAdditional variablesDocs
AppleAPPLE_-Login with Apple
Azure (Microsoft)AZURE_URL (tenant URL)Login with Azure
BitbucketBITBUCKET_-Login with Bitbucket
DiscordDISCORD_-Login with Discord
FacebookFACEBOOK_-Login with Facebook
FigmaFIGMA_-Login with Figma
GitHubGITHUB_URL (for GitHub Enterprise)Login with GitHub
GitLabGITLAB_URL (for self-hosted GitLab)Login with GitLab
GoogleGOOGLE_-Login with Google
KakaoKAKAO_-Login with Kakao
Keycloak (OIDC)KEYCLOAK_URL (realm URL, required)Login with Keycloak
LinkedIn (OIDC)LINKEDIN_OIDC_-Login with LinkedIn
NotionNOTION_-Login with Notion
Slack (OIDC)SLACK_OIDC_-Login with Slack
SnapchatSNAPCHAT_--
SpotifySPOTIFY_-Login with Spotify
TwitchTWITCH_-Login with Twitch
TwitterTWITTER_-Login with Twitter
WorkOSWORKOS_-Login with WorkOS
ZoomZOOM_-Login with Zoom

For each provider, you need at minimum ENABLED, CLIENT_ID, SECRET, and REDIRECT_URI in .env and docker-compose.yml.

Test the login flow#

You can test OAuth with the following minimal index.html served, e.g., via python -m http.server 3000:

1
<!doctype html>
2
<html>
3
<body>
4
<h1>Supabase OAuth Test</h1>
5
<button id="loginBtn">Sign in with Google</button>
6
<pre id="result"></pre>
7
8
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
9
<script>
10
document.addEventListener('DOMContentLoaded', function () {
11
const SUPABASE_URL = 'https://<your-domain>'
12
const SUPABASE_ANON_KEY = 'your-anon-key'
13
14
const supabase = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
15
16
const button = document.getElementById('loginBtn')
17
18
button.addEventListener('click', async () => {
19
const { error } = await supabase.auth.signInWithOAuth({
20
provider: 'google',
21
})
22
23
if (error) {
24
document.getElementById('result').textContent = JSON.stringify(error, null, 2)
25
}
26
})
27
28
supabase.auth.getSession().then(({ data }) => {
29
if (data.session) {
30
document.getElementById('result').textContent =
31
'Logged in as: ' + data.session.user.email
32
}
33
})
34
})
35
</script>
36
</body>
37
</html>

For detailed client-side integration, see Social Login.

Troubleshooting#

"Provider not enabled" or provider shows false in /auth/v1/settings#

  • Check that GOTRUE_EXTERNAL_*_ENABLED is set to true in docker-compose.yml
  • Verify the .env variable is not empty, e.g., check with docker compose exec auth env | grep GOOGLE

Variables added to .env but provider still not working#

Configuration variables from .env are not automatically available inside the container unless there's a matching passthrough definition in docker-compose.yml. Check, e.g., for:

1
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}

Run docker compose exec auth env | grep GOTRUE_EXTERNAL to verify the variables are reaching the container.

SITE_URL or redirect URL errors after login#

After a successful OAuth login, the Auth service redirects to SITE_URL or a URL from ADDITIONAL_REDIRECT_URLS. Ensure:

  • SITE_URL in .env is set to your application's URL
  • If your app uses a different redirect URL, add it to ADDITIONAL_REDIRECT_URLS (comma-separated)

Nonce check failure on mobile (Google Sign In)#

When using Google Sign In on mobile with ID tokens, nonce verification may fail because mobile SDKs don't always support the nonce flow that the Auth service expects.

To enable it, uncomment the following line in docker-compose.yml:

1
GOTRUE_EXTERNAL_SKIP_NONCE_CHECK: true

Auth service fails to start#

Check the auth container logs:

1
docker compose logs auth

Common causes:

  • Missing required environment variable (e.g., CLIENT_ID or SECRET is empty)
  • Invalid API_EXTERNAL_URL (must be a valid URL with protocol)

Environment variable reference#

All OAuth-related environment variables for the auth service in docker-compose.yml:

VariableDescriptionRequired
GOTRUE_EXTERNAL_*_ENABLEDEnable the provider (true/false)Yes
GOTRUE_EXTERNAL_*_CLIENT_IDOAuth client ID from the providerYes
GOTRUE_EXTERNAL_*_SECRETOAuth client secret from the providerYes
GOTRUE_EXTERNAL_*_REDIRECT_URICallback URL: ${API_EXTERNAL_URL}/auth/v1/callbackYes
GOTRUE_SITE_URLDefault redirect URL after authentication (set via SITE_URL in .env)Yes

Additional resources#