Skills Development Implement Flexport Role-Based Access Control

Implement Flexport Role-Based Access Control

v20260423
flexport-enterprise-rbac
This guide details how to implement robust Role-Based Access Control (RBAC) for Flexport API integrations. It addresses enterprise needs by allocating scoped API keys and managing permissions at an application layer. Users can define specific roles (Viewer, Operator, Finance, Admin) with granular permissions, ensuring that different user roles can only access necessary endpoints, thereby enhancing security and supporting multi-tenant architectures.
Get Skill
196 downloads
Overview

Flexport Enterprise RBAC

Overview

Implement role-based access control for Flexport integrations. Since Flexport API keys are scoped at the account level, RBAC is implemented in your application layer with per-role API key allocation and request filtering.

Instructions

Step 1: Define Roles

Role API Key Scope Allowed Endpoints Use Case
Viewer Read-only GET /shipments, GET /products Dashboard users
Operator Read-write GET/POST /bookings, GET/PATCH /purchase_orders Ops team
Finance Read invoices GET /freight_invoices, GET /commercial_invoices Finance team
Admin Full access All endpoints System administrators

Step 2: Application-Layer RBAC

type Role = 'viewer' | 'operator' | 'finance' | 'admin';

const ROLE_PERMISSIONS: Record<Role, { methods: string[]; paths: RegExp[] }> = {
  viewer: {
    methods: ['GET'],
    paths: [/^\/shipments/, /^\/products/, /^\/purchase_orders/],
  },
  operator: {
    methods: ['GET', 'POST', 'PATCH'],
    paths: [/^\/shipments/, /^\/bookings/, /^\/purchase_orders/, /^\/products/],
  },
  finance: {
    methods: ['GET'],
    paths: [/^\/freight_invoices/, /^\/commercial_invoices/, /^\/shipments/],
  },
  admin: {
    methods: ['GET', 'POST', 'PATCH', 'DELETE'],
    paths: [/.*/],
  },
};

function checkPermission(role: Role, method: string, path: string): boolean {
  const perms = ROLE_PERMISSIONS[role];
  return perms.methods.includes(method) && perms.paths.some(p => p.test(path));
}

// Middleware
function rbacMiddleware(role: Role) {
  return (req: Request, res: Response, next: NextFunction) => {
    const flexportPath = req.params.flexportPath;
    if (!checkPermission(role, req.method, `/${flexportPath}`)) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }
    next();
  };
}

Step 3: Multi-Tenant API Key Management

// Each tenant/team gets their own Flexport API key
interface TenantConfig {
  tenantId: string;
  flexportApiKey: string;
  role: Role;
  allowedShipmentPrefixes?: string[];  // Filter visible data
}

class MultiTenantFlexport {
  private configs: Map<string, TenantConfig>;

  async request(tenantId: string, path: string, options: RequestInit = {}) {
    const config = this.configs.get(tenantId);
    if (!config) throw new Error('Unknown tenant');
    if (!checkPermission(config.role, options.method || 'GET', path)) {
      throw new Error('Permission denied');
    }
    return fetch(`https://api.flexport.com${path}`, {
      ...options,
      headers: {
        'Authorization': `Bearer ${config.flexportApiKey}`,
        'Flexport-Version': '2',
        'Content-Type': 'application/json',
      },
    }).then(r => r.json());
  }
}

Step 4: Audit Logging

async function auditLog(entry: {
  userId: string;
  role: Role;
  action: string;
  resource: string;
  result: 'allowed' | 'denied';
}) {
  await db.auditLogs.create({
    data: { ...entry, timestamp: new Date(), ip: req.ip },
  });
  logger.info(entry, 'RBAC audit');
}

Resources

Next Steps

For migration strategies, see flexport-migration-deep-dive.

Info
Category Development
Name flexport-enterprise-rbac
Version v20260423
Size 3.8KB
Updated At 2026-04-28
Language