If your MCP gateway calls backends as one service principal, your audit log names nobody
Most MCP gateways authenticate the user at the front door and then call every backend with a single credential. The gateway’s log records who asked, while the backend’s log records the service principal. The moment a tool writes to a database or opens a ticket, the person drops out of the record, and the backend applies the service principal’s permissions, which are almost always broader than any one user’s.
We’ve built our platform to be identity-first. We think it’s essential that an enterprise keep the end user’s identity intact from the AI client through to the backing system; that’s the difference between an audit trail that names a person and one that names a service account.
Two boundaries, two jobs
Inbound, the gateway does what the MCP specification asks: OAuth 2.1 authorization. It validates JWTs against your identity provider’s issuer, or introspects opaque tokens, and reads the roles and groups claims. Your identity provider stays the source of truth, and no separate user list lives in our gateway.
Outbound is where gateways diverge. Each backend needs the caller’s identity turned into something that the backend will accept, and there is no single answer. Our outbound configuration carries one strategy per backend: RFC 8693 token exchange, Cross-Application Access, AWS STS, header injection, upstream injection, client header pass-through, or on-behalf-of.
The same identity drives authorization, rate limits and audit
Once the identity survives the gateway, everything else can key on it.
Authorization is declarative and compiled to Cedar, an open-source policy language with a formally specified evaluation model. A role says what may be done, a binding says who may do it, matched on your identity provider’s groups and app roles, and a policy attaches the pair to a particular MCP server. The result is evaluated on every tool, prompt and resource access. Denied tools are also removed from the tools/list response, so an agent never sees a tool it cannot call. A visible but forbidden tool is a prompt-injection target and wasted context.
Rate limits key on the authenticated principal, the OIDC sub claim, rather than on a person. An agent running under its own service principal gets its own token bucket and cannot exhaust a human user’s allocation, and the same holds for an application.
Every audit event carries the user, the user_id from the sub claim, the client name and version, and an outcome of success, failure, error, denied or application_error. Denied calls are recorded, not only permitted ones.
Where identity stops
Some backing systems cannot accept a delegated token at all. Legacy applications and databases with static credentials fall back to a credential held in a Kubernetes Secret, External Secrets Operator or Vault. The gateway’s audit record still names the person who made the call, but end-to-end identity stops at that backend. Agree early which of your systems fall into this category.
Agents are authorized through the identity they carry, either a delegated user identity or a workload assertion through a JWT-bearer grant. There is no separately registered agent principal with its own lifecycle and credentials today. If your agent registry is meant to issue agent identities, that interface is something to design together.
As a parting thought, here’s a simple trick to use in your next MCP gateway vendor demo. Have the vendor make one tool call against a real backend and then open that backend’s own log, not the gateway’s. Check whose name is on the line.
October 15, 2026