Guide

Configure Social Login (OAuth) Providers

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

This guide covers the server-side configuration required to enable social login providers on a self-hosted Zuvo 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 Zuvo installation. See Self-Hosting with Docker.
  • API_EXTERNAL_URL set to the publicly reachable URL of your Zuvo instance (e.g., https://<your-domain>/auth/v1).

Your OAuth callback URL should look like the following:

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. The API gateway 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 environment variables

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

GOOGLE_ENABLED=true
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_SECRET=your-client-secret

Step 3: Enable the matching lines in Docker Compose configuration

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

auth:
  environment:
    # ... existing variables ...
    GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
    GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
    GOTRUE_EXTERNAL_GOOGLE_SECRET: ${GOOGLE_SECRET}
    GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI: ${API_EXTERNAL_URL}/callback

Step 4: Restart the auth service

sh run.sh recreate auth

Step 5: Verify the configuration

Check that the provider is enabled:

curl -H 'apikey: your-anon-key' https://<your-domain>/auth/v1/settings

The response should include your provider under external:

{
  "external": {
    "google": true
  }
}

Provider-specific setup

Google

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
GOOGLE_ENABLED=true
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_SECRET=your-google-client-secret
auth:
  environment:
    # ... existing variables ...
    GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
    GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
    GOTRUE_EXTERNAL_GOOGLE_SECRET: ${GOOGLE_SECRET}
    GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI: ${API_EXTERNAL_URL}/callback
GitHub

GitHub setup:

  1. Go to GitHub Developer Settings
  2. Click New OAuth app
  3. Fill in Homepage URL, e.g., https://<your-domain>
  4. Set Authorization callback URL to: https://<your-domain>/auth/v1/callback
  5. Click Register application
  6. Copy the client ID, generate and copy a client secret
GITHUB_ENABLED=true
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_SECRET=your-github-client-secret
auth:
  environment:
    # ... existing variables ...
    GOTRUE_EXTERNAL_GITHUB_ENABLED: ${GITHUB_ENABLED}
    GOTRUE_EXTERNAL_GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID}
    GOTRUE_EXTERNAL_GITHUB_SECRET: ${GITHUB_SECRET}
    GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI: ${API_EXTERNAL_URL}/callback
Azure

Azure Portal setup:

  1. Go to Azure Portal
  2. Go to All services > Identity > App registrations via the navigation menu on the left
  3. Click New registration
  4. Add application Name
  5. Under Redirect URI, select Web and enter: https://<your-domain>/auth/v1/callback
  6. Click Register
  7. Copy the Application (client) ID
  8. Click on Client credentials > Add a certificate or secret
  9. Click on New client secret and add a client secret
  10. Copy the secret value (not "secret ID")
AZURE_ENABLED=true
AZURE_CLIENT_ID=your-azure-application-client-id
AZURE_SECRET=your-azure-client-secret
## Optional: restrict to a specific tenant (defaults to 'common')
# AZURE_URL=https://login.microsoftonline.com/your-tenant-id
auth:
  environment:
    # ... existing variables ...
    GOTRUE_EXTERNAL_AZURE_ENABLED: ${AZURE_ENABLED}
    GOTRUE_EXTERNAL_AZURE_CLIENT_ID: ${AZURE_CLIENT_ID}
    GOTRUE_EXTERNAL_AZURE_SECRET: ${AZURE_SECRET}
    GOTRUE_EXTERNAL_AZURE_REDIRECT_URI: ${API_EXTERNAL_URL}/callback
    ## Optional: uncomment for tenant-specific Azure login
    # GOTRUE_EXTERNAL_AZURE_URL: ${AZURE_URL}
Apple

Apple Developer setup:

  1. Refer to Apple Developer documentation to learn how to enable App ID and create a Services ID
  2. Create a private key for sign in with Apple
  3. Generate a client secret JWT from your private key. See Apple Developer documentation for details.
APPLE_ENABLED=true
APPLE_CLIENT_ID=com.example.your-services-id
APPLE_SECRET=your-generated-jwt-client-secret
auth:
  environment:
    # ... existing variables ...
    GOTRUE_EXTERNAL_APPLE_ENABLED: ${APPLE_ENABLED}
    GOTRUE_EXTERNAL_APPLE_CLIENT_ID: ${APPLE_CLIENT_ID}
    GOTRUE_EXTERNAL_APPLE_SECRET: ${APPLE_SECRET}
    GOTRUE_EXTERNAL_APPLE_REDIRECT_URI: ${API_EXTERNAL_URL}/callback
Keycloak

Keycloak setup:

  1. Open your Keycloak admin console
  2. Select (or create) the realm you want to use
  3. Go to Clients > Create client
  4. Set Client type to OpenID Connect
  5. Set Client ID (e.g., supabase)
  6. On the next screen, enable Client authentication
  7. Under Valid redirect URIs, add: https://<your-domain>/auth/v1/callback
  8. Save, then go to the Credentials tab and copy the Client secret
KEYCLOAK_ENABLED=true
KEYCLOAK_CLIENT_ID=supabase
KEYCLOAK_SECRET=your-keycloak-client-secret
## Required: your Keycloak realm URL
KEYCLOAK_URL=https://keycloak.example.com/realms/myrealm
auth:
  environment:
    # ... existing variables ...
    GOTRUE_EXTERNAL_KEYCLOAK_ENABLED: ${KEYCLOAK_ENABLED}
    GOTRUE_EXTERNAL_KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID}
    GOTRUE_EXTERNAL_KEYCLOAK_SECRET: ${KEYCLOAK_SECRET}
    GOTRUE_EXTERNAL_KEYCLOAK_REDIRECT_URI: ${API_EXTERNAL_URL}/callback
    GOTRUE_EXTERNAL_KEYCLOAK_URL: ${KEYCLOAK_URL}

Other supported providers

Zuvo 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 HTML page:

  • Save the code below to index.html
  • Start python -m http.server 3000 in the same directory
  • Make sure SITE_URL is set to http://localhost:3000 in your self-hosted Zuvo .env configuration
  • Open your browser and go to http://localhost:3000
<!doctype html>
<html>
  <body>
    <h1>Zuvo OAuth Test</h1>
    <button id="loginBtn">Sign in with Google</button>
    <pre id="result"></pre>

    <script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
    <script>
      document.addEventListener('DOMContentLoaded', function () {
        const SUPABASE_URL = 'https://<your-domain>'
        const SUPABASE_ANON_KEY = 'your-anon-key'

        const supabase = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY)

        const button = document.getElementById('loginBtn')

        button.addEventListener('click', async () => {
          const { error } = await supabase.auth.signInWithOAuth({
            provider: 'google',
          })

          if (error) {
            document.getElementById('result').textContent = JSON.stringify(error, null, 2)
          }
        })

        supabase.auth.getSession().then(({ data }) => {
          if (data.session) {
            document.getElementById('result').textContent =
              'Logged in as: ' + data.session.user.email
          }
        })
      })
    </script>
  </body>
</html>

For detailed client-side integration, see Social Login.

Troubleshooting

"Provider not enabled" or provider seen as false in 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 sh run.sh printenv auth | grep GOOGLE

Variables added to the environment 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:

auth:
  environment:
    # ... existing variables ...
    GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}

Run sh run.sh printenv auth | 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:

auth:
  environment:
    # ... existing variables ...
    GOTRUE_EXTERNAL_SKIP_NONCE_CHECK: 'true'

Auth service fails to start

Check the auth container logs:

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 - including protocol and ending with /auth/v1)

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}/callbackYes
GOTRUE_SITE_URLDefault redirect URL after authentication (set via SITE_URL in .env)Yes

Additional resources