Authentication

← Back to Platform Architecture

Authentication

Current Authentication (Phase 1)

Status: Placeholder implementation. NOT production-ready. Critical security gap in HIPAA audit.

X-User-Id Header

All API requests require the X-User-Id header:
curl -H "X-User-Id: 3fc26b33-be13-4306-877a-c3b765cabe1d" \
  https://stratum-platform-api.fly.dev/api/precedents

Authentication Flow

  • Header Extraction — Middleware reads X-User-Id header
  • User Lookup — Backend queries users table: SELECT FROM users WHERE id = $1
  • Tenant Resolution — User record contains tenant_id, which becomes request context
  • Request Context — All subsequent queries filtered by this tenant_id
  • Implementation

    // src/middleware/tenant.ts
    middleware.use((req: Request, res: Response, next: NextFunction) => {
      const userId = req.headers['x-user-id'] as string;
      
      if (!userId) {
        return res.status(401).json({ error: 'Missing X-User-Id header' });
      }
      
      // Lookup user in database
      const user = await db.query('SELECT  FROM users WHERE id = $1', [userId]);
      if (!user) {
        return res.status(401).json({ error: 'User not found' });
      }
      
      // Attach to request context
      req.stratumAuth = {
        user: user,
        tenant_id: user.tenant_id,
      };
      
      next();
    });

    Built-in User

    For development and testing: Use this ID in dev/staging requests.

    Authorization: Role-Based Access Control

    After authentication, some routes require specific roles:

    Role Enforcement

    Routes enforce roles via middleware:
    // Admin only
    router.delete('/precedents/:id', requireRole('admin'), ...);
    
    // Admin or biller
    router.post('/precedents', requireRole('admin', 'biller'), ...);
    
    // All authenticated users
    router.get('/precedents', ...);  // No role requirement

    Permission Errors

    Insufficient role returns 403:
    {
      "error": "INSUFFICIENT_ROLE",
      "message": "De-identified exports require admin role"
    }

    Tenant Isolation

    Once tenant_id is resolved from user_id, all queries are filtered by tenant_id:
    // Example query in routes/precedents.ts
    const result = await db.query(
      'SELECT * FROM precedent_objects WHERE tenant_id = $1 AND id = $2',
      [req.stratumAuth.tenant_id, req.params.id]
    );
    
    // Cross-tenant access attempt returns 404 (not 403, to avoid leaking tenant existence)
    if (!result || result.tenant_id !== req.stratumAuth.tenant_id) {
      res.status(404).json({ error: 'NOT_FOUND' });
    }
    Key: All tables have tenant_id column; all queries include WHERE tenant_id = $1 as first filter. This is enforced at query level, not just route level.

    Future: Auth0/Clerk Integration (Phase 2)

    Planned: Replace X-User-Id header with OAuth 2.0 / OIDC flow.

    Architecture

  • User Registration/Login — Delegated to Auth0/Clerk
  • JWT Token — Client receives JWT after login
  • Authorization Header — Client sends Authorization: Bearer <jwt> with requests
  • Token Verification — Middleware validates JWT signature, extracts claims
  • Role Claims — JWT includes role and tenant_id claims
  • Example JWT Payload (Roadmap)

    {
      "sub": "user-uuid",
      "email": "clinician@provider.co",
      "tenant_id": "tenant-uuid",
      "role": "biller",
      "iat": 1712000000,
      "exp": 1712086400
    }

    Migration Plan

  • Phase 2a — Auth0 integration (new sign-ups only)
  • Phase 2b — Fallback to X-User-Id for existing users (6-month window)
  • Phase 2c — Deprecate X-User-Id header (after 6 months)
  • Planned Auth0 Configuration

    FieldValue
    ID3fc26b33-be13-4306-877a-c3b765cabe1d
    Emailadmin@stratumcollective.co
    Roleadmin
    TenantDefault seed tenant
    RoleAccess
    adminFull access (create, update, delete, export, deidentify, adjust credits)
    billerCreate/update precedents, create appeals, record outcomes
    userRead-only access to precedents, appeals, marketplace
    SettingValue
    Tenantstratumcollective.auth0.com
    Application NameStratum Platform
    Application TypeSingle Page Application (frontend on Cloudflare Workers)
    Allowed Callbackshttps://platform.stratumcollective.co/auth/callback
    Allowed Originshttps://platform.stratumcollective.co
    Logout URLhttps://platform.stratumcollective.co/logout
    Token Audiencehttps://stratum-platform-api.fly.dev

    Error Responses

    Missing Authentication

    curl https://stratum-platform-api.fly.dev/api/precedents
    Response:
    {
      "status": "error",
      "type": "unauthorized",
      "message": "Missing X-User-Id header",
      "details": {
        "header_name": "X-User-Id",
        "expected_format": "UUID"
      }
    }
    HTTP Status: 401 Unauthorized

    Invalid User

    curl -H "X-User-Id: 00000000-0000-0000-0000-000000000000" \
      https://stratum-platform-api.fly.dev/api/precedents
    Response:
    {
      "status": "error",
      "type": "unauthorized",
      "message": "User not found"
    }
    HTTP Status: 401 Unauthorized

    Insufficient Role

    # User with 'user' role attempts to delete
    curl -X DELETE \
      -H "X-User-Id: <user-uuid>" \
      https://stratum-platform-api.fly.dev/api/precedents/prec-uuid
    Response:
    {
      "status": "error",
      "type": "forbidden",
      "message": "Insufficient role: delete requires admin"
    }
    HTTP Status: 403 Forbidden

    Security Considerations

    Phase 1 Limitations: