Skip to main content
Glama
ZayLinux26

agent-identity-control-plane

by ZayLinux26

Agent Identity Control Plane

Identity, delegated authorization, and governance for AI agents, built as first-class non-human identities. A working reference implementation of the patterns that Microsoft Entra Agent ID and Okta Cross App Access sell, built from the protocol up so you can see every token and every policy decision.

Runs on a laptop with nothing but Python. No cloud tenant required.

End-to-end demo

The problem

Enterprises spent twenty years hardening human identity: MFA, privileged access management, joiner-mover-leaver, access reviews. AI agents break most of the assumptions that work was built on. They authenticate at machine speed, spawn sub-agents mid-task, have no HR record to trigger offboarding, and in many environments already outnumber human users by 25 to 1 or more.

The industry noticed all at once. Gartner named both agentic AI oversight and IAM adaptation to agents as top 2026 trends. NIST's Center for AI Standards launched an AI Agent Standards Initiative in February 2026, and its NCCoE concept paper said plainly that SP 800-53 has no purpose-built controls to tell an agent apart from a human, scope an agent to a task, or attribute an action to a non-human principal. Microsoft shipped Entra Agent ID to general availability in April 2026. Okta's Cross App Access started rolling out through the Okta Integration Network in August 2026.

Three things go wrong with agent identity today, and this project has an answer to each.

  1. Agents have no owner of record. When the person who created an agent leaves, the agent keeps its access and nobody owns it. Reporting in 2026 found roughly 8 percent of enterprise non-human identities lose their ownership link after the creator departs.

  2. Credentials are static and long-lived. 24 million non-human-identity secrets were found leaked on GitHub in 2025, and 70 percent of the ones from 2022 still worked.

  3. Tokens do not say who is acting. A service-account token tells you nothing about the human behind a request or the agent in front of it.

Related MCP server: identity-aware-mcp-server

What this is, honestly

This is an engineering build, not a vendor console configuration. I implemented the control patterns myself: OAuth 2.1 token exchange, the RFC 9728 resource-server contract, subject-plus-actor tokens, policy-as-code, and cascading revocation. It implements the same primitives that Entra Agent ID and Okta Cross App Access productize, so the point is to understand the mechanism underneath the products, not to screenshot a console.

What that means for how to describe it: this is a reference implementation. It does not manage identities in a live Entra or Okta tenant. The honest wall section says exactly what is real and what a production deployment adds, and infra/ maps each piece here to the platform component that does it in production.

New to the vocabulary? docs/concepts.md is a plain-English explainer of every term and RFC used here, written to be read start to finish.

Architecture

Architecture

Five layers, each mapping to a control an enterprise identity team would recognize.

How it works, layer by layer

This section is the walkthrough. Each layer says what it fixes, the idea to hold onto, and the standard it maps to.

1. Registry and lifecycle

What it fixes: orphaned agents, no lifecycle, and no way to contain a runaway.

The idea: every agent has a human owner of record. An agent with no owner cannot get a credential or a token, full stop; the rule is is_authorizable(). Agents move through an explicit lifecycle (registered to active to revoked to decommissioned) instead of living forever. Ephemeral sub-agents carry a parent_id, so revoking a parent cascades to every child and its credentials in one call. That is the blast-radius control.

Maps to: Microsoft Entra Agent ID blueprints, where agents are created from a reusable template and the blueprint, not the agent, holds the signing material.

Registry

2. Credentials, with no static secrets

What it fixes: the leaked long-lived API key.

The idea: an agent proves itself with a short-lived workload identity called an SVID (60 second lifetime), then exchanges it for a scoped secret (120 seconds) to reach a downstream system. The blueprint caps which scopes the exchange will ever grant. Nothing here is a standing key in an environment variable.

Maps to: SPIFFE/SPIRE issuing SVIDs, exchanged into HashiCorp Vault. This is the pattern Block put into production and that Vault 1.21 shipped natively.

Credentials

3. Delegated authorization, subject plus actor

What it fixes: tokens that cannot tell you who is acting.

The idea: every access token names both parties. sub is the delegating human. act.sub is the acting agent, carried in the actor claim, along with its owner and blueprint. aud binds the token to exactly one resource, and it expires in five minutes. The authorization server signs with a private RSA key; resource servers verify with the public JWKS, so no shared secret exists that could mint tokens.

Maps to: RFC 8693 token exchange for the actor claim, RFC 8707 resource indicators for the audience binding. Entra models this exactly: the subject is the user, the actor is the agent.

Delegated token

4. The MCP server as an OAuth 2.1 resource server

What it fixes: an MCP server that authenticates agents the wrong way.

The idea: the MCP authorization spec makes an MCP server a plain OAuth 2.1 resource server. It validates tokens and serves tools, and it never issues tokens or logs anyone in. This one publishes RFC 9728 protected resource metadata, returns 401 with a WWW-Authenticate header on an unauthenticated call, validates signature, expiry, and audience, and rejects a token minted for a different resource. It never forwards the caller's token upstream; to reach a downstream API it runs its own token exchange. Forwarding the caller's token is the confused-deputy bug the spec forbids.

Maps to: the MCP Authorization spec (2025-06-18 and later), RFC 9728, RFC 8707.

MCP resource server

5. Policy as code

What it fixes: authorization scattered through the codebase.

The idea: every tool call is decided by one ordered rule set. Deny wins, and the default is deny. The rules check owner, granted scope, scope shape, rate, and off-hours writes. The running engine is Python; the exact same logic is written in Rego so it is portable to an Open Policy Agent sidecar. Every decision is logged with the id of the rule that decided it.

Maps to: Open Policy Agent (Rego) or AWS Cedar.

Policy as code

6. Governance, detection, and response

What it fixes: no visibility into the agent population and slow revocation.

The idea: discovery finds orphaned agents and dangling credentials. A unified audit trail tags every action with the principal that caused it, so an agent's action carries principal_type=non_human and its agent_id. Detection watches that stream for rate spikes and repeated denials and auto-revokes on a confirmed anomaly, with the time-to-revoke measured. The target is minutes; most organizations need a day or more to respond to a credential exposure.

Maps to: the NIST audit-and-accountability gap the NCCoE called out, and non-human identity governance tooling.

Governance and auto-revoke

Run it

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

make test     # 24 tests
make demo     # the full end-to-end walkthrough (the screenshot up top)
make serve    # HTTP API + Swagger UI at http://localhost:8080/docs

make serve brings up every component behind one FastAPI app. The /docs page reads like the architecture: authz, registry, credentials, mcp, governance.

Standards and RFCs implemented

Standard

What it governs here

RFC 8693 OAuth 2.0 Token Exchange

The subject-plus-actor delegated token

RFC 8707 Resource Indicators

The audience binding on every token

RFC 9728 Protected Resource Metadata

What the MCP server publishes for discovery

MCP Authorization (2025-06-18+)

MCP server as an OAuth 2.1 resource server

SPIFFE

The workload-identity shape of the SVID exchange

OWASP NHI Top 10 / Agentic ASI

The risk framework the controls map to

Full risk-to-control mapping: docs/owasp-nhi-mapping.md. Threat model: docs/threat-model.md.

Honest wall: what is built vs what needs a platform

Built and real here: the registry and lifecycle, owner-of-record enforcement, cascading revoke, short-lived credential issuance and exchange, RS256 subject-plus-actor tokens with audience binding, the RFC 9728 resource-server contract with no token forwarding, the policy engine and its Rego twin, and governance with audit and auto-revoke.

What a production deployment adds: SVIDs here are signed opaque tokens, not real X.509 certificates (SPIRE issues those). The authorization server is a local RSA signer, not Keycloak or Entra. Storage is SQLite, not Postgres. Runtime input and output screening against prompt injection is a separate control layer and is out of scope. None of these change the design; they are the component swaps documented in infra/.

Production path

The Python core proves the model. For a real deployment, swap the reference pieces for the platform components with no change to the interfaces: Keycloak or Entra as the authorization server, SPIRE for SVIDs, Vault for secrets, OPA for policy, Postgres for storage, and Terraform to codify Entra Agent ID and Okta Cross App Access. See infra/README.md.

Repo layout

aicp/
  registry/       agent registry + lifecycle, owner of record, cascading revoke
  credentials/    SVID issue + scoped-secret exchange, short TTLs
  authz/          OAuth 2.1 token exchange, subject+actor tokens, JWKS
  mcp_server/     MCP server as an OAuth 2.1 resource server
  policy/         policy-as-code engine + the equivalent Rego policy
  governance/     discovery, anomaly detection, auto-revoke, posture
  common/         config, RSA signing keys, SQLite store, audit trail
  app.py          one FastAPI surface over all of it
scripts/demo.py   the end-to-end walkthrough
tests/            24 pytest tests
docs/             concepts, architecture, threat model, OWASP mapping, ADRs
infra/            the production path: Keycloak, SPIRE, Vault, Terraform

License

MIT. See LICENSE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    MCP server for enterprise authentication and authorization — JWT validation, OIDC token inspection, OAuth 2.0 introspection, and role-based access control for AI agents.
    8
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    A production-ready MCP server that authenticates agents via OAuth 2.1 Bearer tokens, validates JWTs with JWKS, enforces tool-level scopes and roles, and logs the full delegation chain.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Multi-tenant MCP server with OAuth 2.1 authorization, enabling tenant-scoped tool access and audit logging.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enforces fine-grained, context-aware access control on MCP tool calls, with a tamper-evident, replayable audit log that records denials and verifies every decision.
    MIT