Skip to content

Authentication Patterns

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

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.

For simple deployments with a fixed token:

import { StaticAuthProvider } from '@flowdrop/flowdrop/core';
const authProvider = new StaticAuthProvider({
type: 'bearer',
token: 'your-jwt-token'
});
// Sends: Authorization: Bearer your-jwt-token
const authProvider = new StaticAuthProvider({
type: 'api_key',
apiKey: 'your-api-key'
});
// Sends: X-API-Key: your-api-key
const authProvider = new StaticAuthProvider({
type: 'custom',
headers: {
'X-Custom-Auth': 'value',
'X-Tenant-ID': 'tenant-123'
}
});

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");
}
});

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
}
}
});
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;
}
}
});

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
}
}
});
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