Configuring Entra ID SAML SSO with Self-Hosted Supabase

This guide walks through configuring Microsoft Entra ID (formerly Azure AD) as a SAML identity provider for your self-hosted Supabase instance to enable SSO authentication with sfp pro CLI/codev

Prerequisites

Before starting the configuration, ensure you have:

  • Self-Hosted Supabase Requirements:

    • Running Supabase instance (Docker or Kubernetes)

    • Access to modify environment variables and configuration files

    • SSL certificates configured (SAML requires HTTPS)

    • Ability to restart services

  • Entra ID Requirements:

    • Admin access to your Microsoft Entra ID tenant

    • At least one verified domain in your Entra ID tenant

    • Ability to create Enterprise Applications

  • sfp Requirements:

    • sfp CLI installed

    • Access to your sfp server instance

    • sfp server URL (e.g., https://your-sfp-server.com)

Step 1: Enable SAML in Self-Hosted Supabase

Generate Private Key

SAML requires a private key for signing. Generate one:

bash

# Generate private key in DER format
openssl genpkey -algorithm rsa -outform DER -out private_key.der

# Convert to base64
base64 -i private_key.der

Configure Environment Variables

Add to your .env file (in the same directory as docker-compose.yml):

bash

# Enable SAML authentication
GOTRUE_SAML_ENABLED=true
GOTRUE_SAML_PRIVATE_KEY=<your-base64-private-key>

# Ensure your external URL is set correctly
API_EXTERNAL_URL=https://your-supabase-instance.com
GOTRUE_EXTERNAL_URL=https://your-supabase-instance.com

Update Docker Compose Configuration

In your docker-compose.yml, pass the SAML environment variables to the auth container:

yaml

services:
  auth:
    container_name: supabase-auth
    image: supabase/gotrue:v2.99.0
    environment:
      # ... existing environment variables ...
      GOTRUE_SAML_ENABLED: ${GOTRUE_SAML_ENABLED}
      GOTRUE_SAML_PRIVATE_KEY: ${GOTRUE_SAML_PRIVATE_KEY}
      GOTRUE_EXTERNAL_URL: ${GOTRUE_EXTERNAL_URL}
      API_EXTERNAL_URL: ${API_EXTERNAL_URL}

Configure Kong API Gateway

Edit /docker/volumes/api/kong.yml to expose SAML endpoints:

yaml

## Open SSO routes for SAML
- name: auth-v1-open-sso-acs
  url: "http://auth:9999/sso/saml/acs"
  routes:
    - name: auth-v1-open-sso-acs
      strip_path: true
      paths:
        - /auth/v1/sso/saml/acs
        - /sso/saml/acs
  plugins:
    - name: cors

- name: auth-v1-open-sso-metadata
  url: "http://auth:9999/sso/saml/metadata"
  routes:
    - name: auth-v1-open-sso-metadata
      strip_path: true
      paths:
        - /auth/v1/sso/saml/metadata
  plugins:
    - name: cors

Configure Reverse Proxy (if applicable)

If using Nginx as a reverse proxy, add:

nginx

# SSO endpoints
location ~ ^/sso/(.*)$ {
    proxy_set_header Host $host;
    proxy_pass http://kong;
    proxy_redirect off;
}

location ~ ^/auth/v1/sso/(.*)$ {
    proxy_set_header Host $host;
    proxy_pass http://kong;
    proxy_redirect off;
}

Restart Services

bash

# Restart Docker services
docker-compose down
docker-compose up -d

# If using Nginx
sudo systemctl restart nginx

Verify SAML is Enabled

bash

# Get your service role key from .env or docker-compose.yml
API_KEY=<your-service-role-key>

# Check settings
curl -X GET https://your-supabase-instance.com/auth/v1/settings \
  -H "APIKey: $API_KEY" \
  -H "Authorization: Bearer $API_KEY"

You should see "saml_enabled": true in the response.

Step 2: Note Your Supabase Configuration

Gather your self-hosted instance information:

bash

# Your Supabase instance URL
SUPABASE_URL=https://your-supabase-instance.com

# Your Supabase anon key (from .env or docker-compose.yml)
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# SAML endpoints
Entity ID: https://your-supabase-instance.com/auth/v1/sso/saml/metadata
ACS URL: https://your-supabase-instance.com/auth/v1/sso/saml/acs
Metadata URL: https://your-supabase-instance.com/auth/v1/sso/saml/metadata

Step 3: Configure Entra ID Enterprise Application

Create the Application

  1. Sign in to Azure Portal

  2. Navigate to Microsoft Entra IDEnterprise applications

  3. Click New applicationCreate your own application

  4. Select Integrate any other application you don't find in the gallery (Non-gallery)

  5. Name it (e.g., "sfp SSO Self-Hosted")

  6. Click Create

Configure SAML Settings

  1. In your application, go to Single sign-on

  2. Select SAML as the method

  3. Click Edit in Basic SAML Configuration

  4. Configure these URLs (use your actual instance URL):

  1. Click Save

Configure Attributes and Claims

  1. In Attributes & Claims, click Edit

  2. Ensure these claims are configured:

Download Federation Metadata

  1. In SAML Certificates section

  2. Download Federation Metadata XML

  3. Note the SAML Metadata URL if available

Assign Users

  1. Go to Users and groups

  2. Click Add user/group

  3. Select users who need sfp access

  4. Click Assign

Step 4: Add SAML Provider to Self-Hosted Supabase

Since self-hosted Supabase doesn't have CLI support for SSO management, use the Admin API:

Add the Identity Provider

bash

# Set your service role key
API_KEY=<your-service-role-key>

# Add SAML provider using metadata URL
curl -X POST https://your-supabase-instance.com/auth/v1/admin/sso/providers \
  -H "APIKey: $API_KEY" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "saml",
    "metadata_url": "https://login.microsoftonline.com/<tenant-id>/federationmetadata/2007-06/federationmetadata.xml",
    "domains": ["yourdomain.com"]
  }'

Or using metadata XML content:

bash

# Read metadata file content
METADATA_XML=$(cat /path/to/federation-metadata.xml | jq -sR .)

# Add provider with metadata XML
curl -X POST https://your-supabase-instance.com/auth/v1/admin/sso/providers \
  -H "APIKey: $API_KEY" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"type\": \"saml\",
    \"metadata_xml\": $METADATA_XML,
    \"domains\": [\"yourdomain.com\"]
  }"

Configure Attribute Mappings

Get the provider ID from the previous response, then update mappings:

bash

PROVIDER_ID=<provider-id-from-response>

curl -X PUT "https://your-supabase-instance.com/auth/v1/admin/sso/providers/$PROVIDER_ID" \
  -H "APIKey: $API_KEY" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "attribute_mapping": {
      "keys": {
        "email": {
          "name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
        },
        "full_name": {
          "name": "http://schemas.microsoft.com/identity/claims/displayname"
        },
        "first_name": {
          "name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
        },
        "last_name": {
          "name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"
        }
      }
    }
  }'

Verify Provider Configuration

bash

# List all providers
curl -X GET https://your-supabase-instance.com/auth/v1/admin/sso/providers \
  -H "APIKey: $API_KEY" \
  -H "Authorization: Bearer $API_KEY"

Step 5: Configure sfp CLI

Configure sfp to use your self-hosted Supabase instance:

bash

# Set your self-hosted Supabase URL
sfp config:set auth-supabase-url https://your-supabase-instance.com

# Set your Supabase anon key
sfp config:set auth-supabase-anon-key eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# Optionally, set default SSO domain
sfp config:set auth-sso-domain yourdomain.com

Example:

bash

sfp config:set auth-supabase-url https://supabase.mycompany.com
sfp config:set auth-supabase-anon-key "your-anon-key-from-env"
sfp config:set auth-sso-domain mycompany.com

Step 6: Test SAML Authentication

Test SSO URL Generation

First, verify the SSO URL can be generated:

bash

API_KEY=<your-service-role-key>

curl -X POST https://your-supabase-instance.com/auth/v1/sso \
  -H "APIKey: $API_KEY" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "yourdomain.com",
    "skip_http_redirect": true
  }'

You should receive a JSON response with a URL to the Entra ID login page.

Test with sfp CLI

bash

sfp server auth login \
  --email [email protected] \
  --provider saml \
  --sso-domain yourdomain.com \
  --sfp-server-url https://your-sfp-server.com \
  --no-global-auth

Example:

bash

sfp server auth login \
  --email [email protected] \
  --provider saml \
  --sso-domain mycompany.com \
  --sfp-server-url https://sfp.mycompany.com \
  --no-global-auth

Troubleshooting

Common Issues

"saml_enabled": false in settings

  • Check environment variables are set correctly

  • Verify docker-compose.yml passes SAML variables to auth container

  • Restart all containers: docker-compose down && docker-compose up -d

Kong routes not working

  • Verify kong.yml has been updated with SSO routes

  • Check Kong logs: docker logs supabase-kong

  • Ensure paths are correctly configured

SSL/HTTPS issues

  • SAML requires HTTPS - ensure SSL is properly configured

  • Check reverse proxy configuration if using one

  • Verify API_EXTERNAL_URL and GOTRUE_EXTERNAL_URL use https://

"No SSO provider assigned for this domain"

  • Check provider was added successfully

  • Verify domain matches exactly

  • List providers to confirm configuration

Metadata URL not accessible

  • For on-premise Entra ID behind VPN, use metadata XML instead

  • Ensure your Supabase instance can reach Microsoft's URLs

Debug Commands

bash

# Check Docker logs
docker logs supabase-auth
docker logs supabase-kong

# Verify SAML endpoints are accessible
curl https://your-supabase-instance.com/auth/v1/sso/saml/metadata

# Check sfp configuration
sfp config:list

# Test with debug logging
sfp server auth login \
  --email [email protected] \
  --provider saml \
  --sso-domain yourdomain.com \
  --sfp-server-url https://your-sfp-server.com \
  --no-global-auth \
  --loglevel debug

Security Considerations

SSL/TLS Configuration

Ensure proper SSL configuration for SAML:

nginx

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

Network Security

  1. Firewall Rules: Allow HTTPS traffic from Entra ID services

  2. Internal Communication: Secure communication between containers

  3. Secret Management: Store sensitive keys securely

Monitoring

  1. Set up log aggregation for auth services

  2. Monitor failed authentication attempts

  3. Track certificate expiration dates

  4. Regular security audits

Managing Multiple Environments

For different environments with self-hosted instances:

bash

# Development
sfp config:set auth-supabase-url https://dev.supabase.mycompany.com
sfp config:set auth-supabase-anon-key "dev-anon-key"

# Production
sfp config:set auth-supabase-url https://supabase.mycompany.com
sfp config:set auth-supabase-anon-key "prod-anon-key"

Or use environment variables:

bash

export SUPABASE_URL=https://dev.supabase.mycompany.com
export SUPABASE_ANON_KEY=dev-anon-key
export AUTH_SSO_DOMAIN=dev.mycompany.com

Next Steps

After successful configuration:

  1. Document the setup for your operations team

  2. Create runbooks for common issues

  3. Set up monitoring and alerting

  4. Plan for certificate rotation

  5. Consider implementing SCIM for user provisioning

  6. Document disaster recovery procedures

Last updated