← 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:
| Field | Value |
| ID | 3fc26b33-be13-4306-877a-c3b765cabe1d |
| Email | admin@stratumcollective.co |
| Role | admin |
| Tenant | Default seed tenant |
Use this ID in dev/staging requests.
Authorization: Role-Based Access Control
After authentication, some routes require specific roles:
| Role | Access |
| admin | Full access (create, update, delete, export, deidentify, adjust credits) |
| biller | Create/update precedents, create appeals, record outcomes |
| user | Read-only access to precedents, appeals, marketplace |
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
| Setting | Value |
| Tenant | stratumcollective.auth0.com |
| Application Name | Stratum Platform |
| Application Type | Single Page Application (frontend on Cloudflare Workers) |
| Allowed Callbacks | https://platform.stratumcollective.co/auth/callback |
| Allowed Origins | https://platform.stratumcollective.co |
| Logout URL | https://platform.stratumcollective.co/logout |
| Token Audience | https://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:
- X-User-Id header can be spoofed (no signature, no validation of origin)
- No rate limiting or request logging at auth level
- JWT not used (stateless validation impossible)
- Suitable only for development and early-stage testing
Roadmap:
- Implement Auth0/Clerk for production compliance
- Add request signing (HMAC-SHA256 on request body)
- Implement rate limiting per user/tenant
- Log all authentication events
Testing Authentication
Local Development
# With dev user
curl -H "X-User-Id: 3fc26b33-be13-4306-877a-c3b765cabe1d" \
http://localhost:3001/api/precedents
With invalid user (should return 401)
curl -H "X-User-Id: 00000000-0000-0000-0000-000000000000" \
http://localhost:3001/api/precedents
Without header (should return 401)
curl http://localhost:3001/api/precedents
Testing Role-Based Access
# Admin user (seed user has admin role)
curl -X POST \
-H "X-User-Id: 3fc26b33-be13-4306-877a-c3b765cabe1d" \
-H "Content-Type: application/json" \
-d '{ ... }' \
http://localhost:3001/api/precedents
Biller user (create additional test user with biller role)
curl -X POST \
-H "X-User-Id: <biller-user-uuid>" \
-H "Content-Type: application/json" \
-d '{ ... }' \
http://localhost:3001/api/precedents
See Also
OVERVIEW.md — API design philosophy, HTTP status codes
ERROR-HANDLING.md — Error response formats
/stratum-platform/CLAUDE.md — Phase 1 auth limitations documented in project context