CloudSignal Docs
GuidesAuth Providers

Auth0 integration

Configure Auth0 as an authentication provider for CloudSignal MQTT.

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

Prerequisites

  • An Auth0 account with an application configured
  • A CloudSignal account with API keys
  • Auth0 domain and audience values

Configuration

Get Auth0 configuration values

  1. Go to Auth0 Dashboard
  2. Navigate to ApplicationsAPIs
  3. Note your API Audience (identifier)
  4. Go to SettingsDomain and copy your domain

Your domain will look like: your-tenant.auth0.com

Add Auth0 provider in CloudSignal

  1. Go to CloudSignal Dashboard
  2. Navigate to ConnectionsAuth Providers
  3. Click Add Provider
  4. Select Auth0
  5. Enter your configuration:
FieldValue
NameA friendly name (for example, "Production Auth0")
DomainYour Auth0 domain (for example, your-tenant.auth0.com)
AudienceYour API identifier (for example, https://api.yourapp.com)
  1. Click Save

Test the integration

Exchange an Auth0 access token:

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

Implementation

React example with Auth0 SDK

import { useAuth0 } from '@auth0/auth0-react';
import mqtt from 'mqtt';
import { useState, useEffect } from 'react';

function MqttComponent() {
  const { getAccessTokenSilently, isAuthenticated } = useAuth0();
  const [mqttClient, setMqttClient] = useState<mqtt.MqttClient | null>(null);

  async function getMqttCredentials() {
    // Get Auth0 access token
    const accessToken = await getAccessTokenSilently({
      authorizationParams: {
        audience: 'https://api.yourapp.com'
      }
    });

    // Exchange via your backend
    const response = await fetch('/api/mqtt-credentials', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ auth0Token: accessToken })
    });

    return response.json();
  }

  useEffect(() => {
    if (!isAuthenticated) return;

    async function connect() {
      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');
      });

      setMqttClient(client);
    }

    connect();

    return () => {
      mqttClient?.end();
    };
  }, [isAuthenticated]);

  return <div>MQTT Status: {mqttClient ? 'Connected' : 'Disconnected'}</div>;
}

API route (Next.js)

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

export async function POST(request: Request) {
  const { auth0Token } = 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: 'auth0',
      token: auth0Token
    })
  });

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

Express.js backend

import express from 'express';
import { auth } from 'express-oauth2-jwt-bearer';

const app = express();

// Auth0 middleware
const checkJwt = auth({
  audience: 'https://api.yourapp.com',
  issuerBaseURL: 'https://your-tenant.auth0.com/',
});

app.post('/mqtt-credentials', checkJwt, async (req, res) => {
  // Token is already validated by middleware
  const auth0Token = req.headers.authorization?.split(' ')[1];

  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: 'auth0',
      token: auth0Token
    })
  });

  const credentials = await response.json();
  res.json(credentials);
});

React Native with Auth0

import Auth0 from 'react-native-auth0';
import mqtt from 'mqtt';

const auth0 = new Auth0({
  domain: 'your-tenant.auth0.com',
  clientId: 'YOUR_CLIENT_ID'
});

async function connectToMqtt() {
  // Get credentials (assuming user is logged in)
  const credentials = await auth0.credentialsManager.getCredentials();

  if (!credentials.accessToken) {
    throw new Error('Not authenticated');
  }

  // Exchange token via your backend
  const response = await fetch('https://your-api.com/mqtt-credentials', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${credentials.accessToken}`,
      '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

Auth0 access tokens have configurable expiration. Handle refresh:

import { useAuth0 } from '@auth0/auth0-react';

function useMqttWithRefresh() {
  const { getAccessTokenSilently } = useAuth0();
  const [client, setClient] = useState<mqtt.MqttClient | null>(null);

  // Refresh credentials before expiry
  useEffect(() => {
    if (!client) return;

    const refreshInterval = setInterval(async () => {
      try {
        const credentials = await getMqttCredentials();

        // Update client credentials
        client.options.username = credentials.mqtt_username;
        client.options.password = credentials.mqtt_password;

        // Reconnect with new credentials
        client.reconnect();
      } catch (error) {
        console.error('Failed to refresh credentials:', error);
      }
    }, 50 * 60 * 1000); // Refresh every 50 minutes

    return () => clearInterval(refreshInterval);
  }, [client]);

  return client;
}

ACL rules for Auth0 users

Create ACL rules that match Auth0 user IDs or emails:

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

The MQTT username will be derived from Auth0's sub claim (user ID) or email.

Using Auth0 actions for custom claims

You can add custom claims in Auth0 to control MQTT access:

// Auth0 Action: Add MQTT-related claims
exports.onExecutePostLogin = async (event, api) => {
  // Add custom namespace claims
  api.accessToken.setCustomClaim('https://cloudsignal.io/mqtt_topics', [
    'agents/#',
    'alerts/' + event.user.user_id
  ]);
};

Troubleshooting

"Invalid token" error

CheckWhat to verify
Token freshnessAccess tokens expire based on your Auth0 settings
AudienceMust match exactly what's configured
Token typeThe token exchange expects access tokens, not ID tokens

"Provider not found" error

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

"Token signature verification failed"

CheckWhat to verify
DomainMust match your Auth0 tenant domain exactly
AudienceAPI identifier must match

Next steps

On this page