You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(control-plane): delegation mints per-request JWT for caller's tenant
The initial delegation layer used Control Plane's long-lived admin
service JWT to authenticate forwarded requests. That's wrong for
reads: Core's query_events (and Query Service's auth pipeline)
resolves tenant from the JWT claims, so every forwarded query was
scoped to tenant="system" (CP's admin identity) and our injected
tenant_id query param was ignored. Users got cross-tenant reads —
including other users' events and the "default" tenant's seed data.
Live repro against the initial deploy:
POST /api/v1/events → event lands at tenant="default" (Core
v0.18.x hardcoded; since-fix landed via b08aa1a + redeploy)
GET /api/v1/events/query → returns 100 events from
tenant="default", not the caller's tenant
Fix: AuthClient.SignDelegationJWT(userID, tenantID, role) mints a
short-lived (60s) HS256 JWT that represents the authenticated
caller. delegationClient stores the signer as a func value — not a
single static token — and each forward call takes a bearer param.
ProxyIngestSingle / ProxyIngestBatch / ProxyEventsQuery now:
1. Pull user_id + tenant_id + role from AuthContext (set by
AuthMiddleware after JWT or ask_ validation).
2. Inject tenant into body (writes) or query param (reads).
3. Mint a per-request JWT with the caller's identity.
4. Forward with Authorization: Bearer <per-request JWT>.
Backends (Core, Query Service) now see the real caller's tenant and
enforce isolation as they always would. No backend changes needed.
Post-redeploy smoke test (allsource-control-plane.fly.dev):
- register → ask_ key with tenant=final-{ts}-at-test-local
- POST /events with body.tenant_id="SPOOFED" → returns event_id
- GET /events/query?event_type=final.{ts} → count=1, event has
tenant_id="final-{ts}-at-test-local" (spoofed value overwritten,
cross-tenant reads impossible)
Also requires allsource-core redeploy to pick up the tenant_id-from-
body fix that landed in main (commit b08aa1a) but shipped with
v0.18.0 on Fly. Done in parallel with this commit.
Tests: delegation tests updated to assert the per-request JWT shape
(stub signer echoes userID/tenantID/role into the forwarded
Authorization header for easy assertion). Full CP suite green.
0 commit comments