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
- Go to your Supabase Dashboard
- Select your project
- Navigate to Settings → API
- Copy the JWT Secret (under "JWT Settings")
Keep your JWT secret secure. Never expose it in client-side code.
Add Supabase provider in CloudSignal
- Go to CloudSignal Dashboard
- Navigate to Connections → Auth Providers
- Click Add Provider
- Select Supabase
- Enter your configuration:
| Field | Value |
|---|---|
| Name | A friendly name (for example, "Production Supabase") |
| Project URL | Your Supabase project URL (for example, https://abc123.supabase.co) |
| JWT Secret | The secret from Step 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: pubsubThe MQTT username derived from Supabase will be the user's email (sanitized) or UUID, depending on your configuration.
Troubleshooting
"Invalid token" error
| Check | What to verify |
|---|---|
| Token freshness | Supabase access tokens expire after 1 hour |
| JWT secret | Ensure the secret matches your Supabase project |
| Project URL | Must match exactly (including https://) |
"Provider not found" error
| Check | What to verify |
|---|---|
| Provider enabled | Confirm the provider is enabled in the CloudSignal dashboard |
| Provider name | Use "provider": "supabase" (lowercase) |
Connection drops after 1 hour
Supabase tokens expire. Implement token refresh handling as shown above.
Next steps
- Firebase integration - Same pattern, different provider
- Token Exchange API reference - Full request and response details
- ACL rules guide - Scope topics to the authenticated user