Technology · Discipline

Identity and access management for AI agents

I worked out, from real tenant evidence, how an AI employee legitimately answers, calls and acts inside Microsoft 365, with per-employee tokens minted server-side and never handed to a model.

OAuth 2.0 server in PythonAuth and access plane · HelixMicrosoft 365 and Entra
Where identity sits
M
model seat, no key · action server, a token per employee · Microsoft 365
  • 30 daysa pending client lives, for assistants that cache their client ID and never register again

One authorization server for every assistant

Auth and access plane: I wanted commercial AI assistants, including Microsoft Copilot Studio, to reach my private tool estate on my terms. I was not willing to run a server per vendor or hand out a secret per connection, so I decided that one OAuth 2.0 authorization server would issue every token and that a person would approve every client.

I built that server in Python. It issues RS256-signed JWTs and supports the authorization-code grant with PKCE, client credentials and refresh tokens, revocation, and the published key set and metadata documents that MCP clients read first. Assistants register themselves as temporary clients and wait for a person.

1234
1 registers a temporary client2 pending, no token3 a person approves, sets lifetimes4 RS256 JWT issued
✓signature✓issuer✓audience✓expiry✓scopechecked offline at the gateway, against the published keys; more than one issuer trusted

Interoperability was the hard part. Each assistant orders discovery differently and caches its client ID differently, and one flow had to serve all of them.

A hardening pass gated client registration, and the next day the gate locked out every assistant whose cached client had expired. I reverted it with a one-line change, because an attacker who registers a client still cannot get a code without my approval. The episode is told in The hardening fix that locked everyone out.

Gate on registration
locked out; reverted
Consent screen
approved clients get a code

One key set, three verifiers

The issuer, the tool gateway and an edge verifier run in different languages and places, and all of them trust one published key set.

Authorization serverPython · signs; its key persists, so tokens survive a restart
published key set
Tool gatewayRust · verifies
Edge verifieredge · verifies

A digital employee that acts as itself

Helix: a digital employee in Microsoft 365 has to act as itself. A shared service account would have made every action untraceable to the employee. Tokens in a model's context would have handed the model the employee's authority. I put identity in the server.

Every call to the meeting action server names the acting employee. The server signs certificate client assertions for the employee and exchanges them for that employee's own Microsoft Graph tokens. Tokens are cached per employee and their claims are checked in-process before use. The tenant installer refuses to provision an employee until its calling contract is sealed.

agent-user tokens: one per employee, minted on the server, for actions attributed to that employee
application token: calling and roster
raise own hand: no supported API, typed refusal
Who may connect to the meeting server is decided apart from which employee acts, which keeps per-tool grant layers out of it.

In the Teams working service, ownership comes from the user's Entra sign-in, and voice access to work tools stays off unless every person in the room is authorized. The full account is in Solving the digital-employee identity.

Microsoft remains the permission authority for the digital employee, and my layer grants nothing the tenant has not.

I design identity for AI clients and AI employees from the standards up. Entra Agent ID and Agent 365 are Microsoft's platform, which I configured. The authorization server, the gateway checks and the identity layer around the employee are mine.