Skip to main content
FlowDrop supports three authentication providers that control how API requests are authenticated. Choose based on your security requirements.

No Authentication

For development and prototyping when your backend doesn’t require auth:
import { NoAuthProvider } from '@flowdrop/flowdrop/core';

const app = await mountFlowDropApp(container, {
  authProvider: new NoAuthProvider()
});
NoAuthProvider sends no authentication headers. This is also the default if you don’t specify an authProvider.

Static Token Authentication

For simple deployments with a fixed token:
import { StaticAuthProvider } from '@flowdrop/flowdrop/core';

Bearer Token

const authProvider = new StaticAuthProvider({
  type: 'bearer',
  token: 'your-jwt-token'
});
// Sends: Authorization: Bearer your-jwt-token

API Key

const authProvider = new StaticAuthProvider({
  type: 'api_key',
  apiKey: 'your-api-key'
});
// Sends: X-API-Key: your-api-key

Custom Headers

const authProvider = new StaticAuthProvider({
  type: 'custom',
  headers: {
    'X-Custom-Auth': 'value',
    'X-Tenant-ID': 'tenant-123'
  }
});
Static tokens can’t be refreshed.If the token expires, FlowDrop API calls fail with 401 errors until the editor is remounted with a new token.

Callback Authentication (Enterprise)

For enterprise integrations where your application manages auth:
import { CallbackAuthProvider } from '@flowdrop/flowdrop/core';

const authProvider = new CallbackAuthProvider({
  // Called before EVERY API request
  getToken: async () => {
    return authService.getAccessToken(); // return null if not authenticated
  },

  // Called when API returns 401
  onUnauthorized: async () => {
    const refreshed = await authService.refreshToken();
    return refreshed; // true = retry request, false = give up
  },

  // Called when API returns 403
  onForbidden: async () => {
    showError("You don't have permission to access this resource");
  }
});

Token Refresh Pattern

The callback provider supports automatic token refresh:
const authProvider = new CallbackAuthProvider({
  getToken: async () => {
    // Check if token is still valid
    if (tokenStore.isExpired()) {
      await tokenStore.refresh();
    }
    return tokenStore.getToken();
  },
  onUnauthorized: async () => {
    // Token was rejected by server, try refresh
    try {
      await tokenStore.refresh();
      return true; // retry the failed request
    } catch {
      redirectToLogin();
      return false; // don't retry
    }
  }
});

OAuth2 / OIDC Integration

const authProvider = new CallbackAuthProvider({
  getToken: async () => {
    // Get token from your OAuth2 library
    const token = await oidcClient.getUser()?.access_token;
    return token || null;
  },
  onUnauthorized: async () => {
    // Trigger silent token renewal
    try {
      await oidcClient.signinSilent();
      return true;
    } catch {
      // Silent renewal failed, redirect to login
      await oidcClient.signinRedirect();
      return false;
    }
  }
});

Error Handling with Auth

Combine auth providers with the onApiError event handler for centralized error management:
const app = await mountFlowDropApp(container, {
  authProvider,
  eventHandlers: {
    onApiError: (error, operation) => {
      if (error.message.includes('401')) {
        // Auth provider's onUnauthorized already handled this
        return true; // suppress toast
      }
      if (error.message.includes('403')) {
        showPermissionError(operation);
        return true;
      }
      // Let other errors show the default toast
    }
  }
});

Choosing a Provider

ScenarioProviderWhy
Local developmentNoAuthProviderNo backend auth needed
Simple deploymentStaticAuthProviderToken set once at page load
Single-page app with JWTCallbackAuthProviderToken refresh on expiry
Enterprise SSO / OAuth2CallbackAuthProviderIntegrates with auth library
Multi-tenantStaticAuthProvider (custom)Add tenant headers

Next Steps