CloudSignal Docs
GuidesAuth Providers

Supabase integration

Configure Supabase as an authentication provider for CloudSignal MQTT.

Configure Supabase as an authentication provider so your Supabase users can connect to CloudSignal MQTT with credentials derived from their Supabase JWT. Use this when your app already authenticates users via Supabase.

Prerequisites

  • A Supabase project with authentication enabled
  • A CloudSignal account with API keys
  • Your Supabase JWT secret

Configuration

Get your Supabase JWT secret

  1. Go to your Supabase Dashboard
  2. Select your project
  3. Navigate to SettingsAPI
  4. Copy the JWT Secret (under "JWT Settings")

Keep your JWT secret secure. Never expose it in client-side code.

Add Supabase provider in CloudSignal

  1. Go to CloudSignal Dashboard
  2. Navigate to ConnectionsAuth Providers
  3. Click Add Provider
  4. Select Supabase
  5. Enter your configuration:
FieldValue
NameA friendly name (for example, "Production Supabase")
Project URLYour Supabase project URL (for example, https://abc123.supabase.co)
JWT SecretThe secret from Step 1
  1. Click Save

Test the integration

Use the CloudSignal API to test token exchange:

curl -X POST https://api.cloudsignal.io/v2/tokens/exchange \
  -H "Authorization: Bearer YOUR_CLOUDSIGNAL_SK" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "supabase",
    "token": "YOUR_SUPABASE_ACCESS_TOKEN"
  }'

Implementation

React/Next.js example

import { createClient } from '@supabase/supabase-js';
import mqtt from 'mqtt';

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

// Exchange Supabase token for MQTT credentials
async function getMqttCredentials() {
  const { data: { session } } = await supabase.auth.getSession();

  if (!session) {
    throw new Error('User not authenticated');
  }

  const response = await fetch('/api/mqtt-credentials', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      supabaseToken: session.access_token
    })
  });

  return response.json();
}

// Connect to MQTT
async function connectMqtt() {
  const credentials = await getMqttCredentials();

  const client = mqtt.connect('wss://connect.cloudsignal.app:18885/', {
    username: credentials.mqtt_username,
    password: credentials.mqtt_password
  });

  client.on('connect', () => {
    console.log('Connected to MQTT');
  });

  return client;
}

API route (Next.js)

// app/api/mqtt-credentials/route.ts
import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  const { supabaseToken } = await request.json();

  const response = await fetch('https://api.cloudsignal.io/v2/tokens/exchange', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.CLOUDSIGNAL_SK}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      provider: 'supabase',
      token: supabaseToken
    })
  });

  const credentials = await response.json();
  return NextResponse.json(credentials);
}

React Native example

import { supabase } from './supabaseClient';
import mqtt from 'mqtt';

async function connectToMqtt() {
  // Get current Supabase session
  const { data: { session } } = await supabase.auth.getSession();

  if (!session) {
    throw new Error('Not logged in');
  }

  // Exchange token (via your backend)
  const response = await fetch('https://your-api.com/mqtt-credentials', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${session.access_token}`,
      'Content-Type': 'application/json'
    }
  });

  const { mqtt_username, mqtt_password } = await response.json();

  // Connect to MQTT
  const client = mqtt.connect('wss://connect.cloudsignal.app:18885/', {
    username: mqtt_username,
    password: mqtt_password
  });

  return client;
}

Handling token refresh

Supabase tokens expire. Handle reconnection with fresh credentials:

import { supabase } from './supabaseClient';

let mqttClient: mqtt.MqttClient | null = null;

// Listen for auth state changes
supabase.auth.onAuthStateChange(async (event, session) => {
  if (event === 'TOKEN_REFRESHED' && mqttClient) {
    // Get new MQTT credentials
    const credentials = await getMqttCredentials();

    // Reconnect with new credentials
    mqttClient.end();
    mqttClient = mqtt.connect('wss://connect.cloudsignal.app:18885/', {
      username: credentials.mqtt_username,
      password: credentials.mqtt_password
    });
  }
});

ACL rules for Supabase users

Create ACL rules that match Supabase user IDs:

# User can only access their own topics
User Pattern: %
Topic: users/%u/#
Permission: pubsub

The MQTT username derived from Supabase will be the user's email (sanitized) or UUID, depending on your configuration.

Troubleshooting

"Invalid token" error

CheckWhat to verify
Token freshnessSupabase access tokens expire after 1 hour
JWT secretEnsure the secret matches your Supabase project
Project URLMust match exactly (including https://)

"Provider not found" error

CheckWhat to verify
Provider enabledConfirm the provider is enabled in the CloudSignal dashboard
Provider nameUse "provider": "supabase" (lowercase)

Connection drops after 1 hour

Supabase tokens expire. Implement token refresh handling as shown above.


Next steps

On this page