Share
AI Agent Governance

Your Auth0 Scopes, Made Authoritative

A scope says what a permission is called. It does not say who may hold it at which position, who may hand it out, whether they were entitled to, or whether it was still valid when Claude Code used it. This week we asked those questions of an Auth0 catalogue, on camera, and Auth0 was told the answer.

An Auth0 API and its scopes, authored in IdentityRM, provisioned into Auth0, governed from here: given positions and owners, asked about, granted with a sealed record, used by Claude Code, Anthropic’s coding agent, from two positions with two answers, and taken back. The catalogue lives in Auth0; the authority over it, and the record of every decision, is mastered in IdentityRM. What that is, and what it is not.

Martin Gee 7 min read
authority-governance auth0 scopes mcp claude-code anthropic agent-authorization delegation
Martin Gee

"The permission belongs to Auth0. The authority to hand it out is ours. A scope becomes authoritative when someone has to ask before it is used, and someone else was entitled to say yes."

— Martin Gee, Founder & CEO, IdentityRM

Last week I showed this to a friend at Okta. The question any identity product manager asks first is the fair one: we already have scopes. An API in Auth0 carries its permissions, a role carries a set of them, a token carries the ones the holder has. What is left to govern?

Quite a lot, it turns out, and none of it is the scope itself. It also took minutes, not a project. The API and its three scopes were authored from IdentityRM into Auth0 in about five minutes. Two roles, one owner, and the whole thing was ready to govern in under ten minutes, by hand, on a laptop. Keep that number in mind while reading the rest.

Diagram: Okta and Auth0 sign people in; Auth0 holds the Developer Tooling API, its scopes and two roles, authored from IdentityRM; IdentityRM holds the authority model with Engineering, Jordan as owner, Morgan at two positions, and the three words ask, act, prove; Claude Code is an MCP client with a push hook, denied at Seattle Office and allowed at Engineering; arrows for sign in, authored and provisioned, told, ask and act, and the answer
One model, two providers, one question. Identity from Okta and Auth0, the catalogue in Auth0, authority asked of one model and kept.

A scope says what a permission is called. It does not say who may hold it at which position, who may hand it out, whether they were entitled to when they did, or whether it was still valid at the moment the agent used it. Those are the questions this series has been asking since the first post, and this week we asked them of someone else’s catalogue, with Claude Code, Anthropic’s coding agent, as the one doing the asking.

The catalogue lives in Auth0, and came from here

Developer Tooling API was authored in IdentityRM, provisioned into Auth0 through its handler, and is governed from here. Here it is as IdentityRM sees it: an Auth0 API, linked by its external id, with its three scopes as permissions. Beside it sits the native resource from the earlier posts, with no provider and no handler.

IdentityRM resources list showing Developer Tooling API linked to Auth0 beside the native dev_tooling resource
The Auth0-linked resource beside the native one. One was authored here and provisioned out; the other never left.

And here are the same three scopes in the Auth0 console. They were written there from our side, through the handler, with the same keys and the same descriptions. Nothing was typed twice.

Auth0 console showing the Developer Tooling API with the permissions git.push, git.force_push and git.tag
The permissions in Auth0, where they live, written from IdentityRM.

The line I used in the room: the permission is Auth0’s. The authority to hand it out is ours.

An Auth0 role, made authoritative

A scope becomes something a person can hold only when a role carries it. These two roles were authored from IdentityRM on the first day as native Auth0 roles, through the Auth0 role handler: Repository Pusher carrying git.push, Release Tagger carrying git.tag. Auth0 holds the role. IdentityRM holds the authority over it: who may hold it, at which position, who may hand it out, and the record. Creating a role here never adds a duplicate to the tenant. The handler checks Auth0 first, and when the role already exists it binds to it by Auth0’s role id. From that moment the Auth0 role is a managed role: its membership follows decisions made here, through the same handler that later puts Morgan on it.

IdentityRM Create Role wizard with the Auth0 Role Handler selected, reporting a matching external role named Release Tagger and offering to link it
Creating the role through the Auth0 handler. It binds to the existing Auth0 role instead of adding a duplicate, and from then on that role is managed from IdentityRM.

Give it a position and an owner

A role becomes authority only when it is tied to a position and someone is entitled to hand it out. Both roles sit at the Engineering team. Jordan Lee owns Repository Pusher there, and nobody owns Release Tagger.

The fifth question, answered on someone else’s catalogue

The Blueprint Alliance, the Okta-led group of a dozen vendors that formed in September around a shared architecture for securing AI agents, poses four questions: where are my agents, what can they do, what are they doing, how do I respond. Each is answered by someone in that Alliance. The fifth, by what authority, is answered here: a role at a position, with a named owner, checked before the act. The catalogue happened to be Auth0’s this week. The answer is the same for any member’s.

The Engineering node roles tab showing Release Pusher, Release Tagger and Repository Pusher with an owner badge on Repository Pusher
Two roles on an Auth0 catalogue, at one position, one of them owned.

That ownership is the whole difference. In Auth0, a role is a bag of scopes and an administrator assigns it. Here, the right to assign it is itself held, at a position, by a named person, and that right is what gets checked.

Ask

Here is the problem the whole industry is circling: an agent does not know what authority it holds, and nothing in the stack can tell it before it acts. The runtime answers that with one question, asked the same way by a person or an agent, and it is the first of the three words we gave the discipline we call authority governance: ask, act, prove.

Jordan asks whether she may grant each role at Engineering. The first answer is yes. The second is no. Same person, same position, same tool, two receipts, and the receipt says why: she owns one role there and not the other.

Parlay authorization check card: Jordan Lee, grant_role, Engineering, Authorized
Authorized to grant Repository Pusher at Engineering.
Parlay authorization check card: Jordan Lee, grant_role, Engineering, Not authorized
Not authorized to grant Release Tagger at the same position.

Neither receipt changed anything. They are the prospective tier, the Ask. The act comes next.

Act, and Auth0 is told

Jordan grants Repository Pusher to Morgan Reyes, a release engineer whose home is Seattle Office and who is a member of Engineering, for three days. The grant is a governed act with a sealed record, as the earlier posts showed. What is new this week is the second thing that happened on the same call.

Parlay Grant Role preview: Morgan Reyes at Engineering, Repository Pusher, starts 12 October 2026 2:19 PM PDT, expires 15 October 2026 2:19 PM PDT, business reason, Authority checked Eligible, Grant role button
The preview. Authority checked, eligible, three days, nothing granted yet.
Parlay Role Granted card: Morgan Reyes at Engineering, Repository Pusher, active, Authority sealed Granted; the events pane beside it shows Authority granted for operation role.assignment by actor 25 and User 15 granted role Repository Pusher
The act. Authority sealed, and the record of it in the events pane on the right.
Auth0 console, Repository Pusher role, Users tab: Morgan Reyes, west.release_engineer@idrm.local, listed as directly assigned
Morgan on the Auth0 role, in Auth0. The decision was ours; the membership followed.

Morgan appeared on the Repository Pusher role in the Auth0 console. The authority decision was computed and sealed on our side, and the provider was told. Before it writes, the grant checks that the person actually exists in Auth0; if he did not, it would stop there and say so. His own page shows the rest: linked to Auth0, home Seattle Office, and the grant with who gave it, when it ends, and the reason on the row.

Morgan Reyes user page: Auth0 linked, home Seattle Office, roles MCP Access at Seattle Office and Repository Pusher at Engineering granted by Jordan Lee, expires 2026-10-15
What he holds, who gave it, until when.

Prove

Morgan is a coding agent for this part: Claude Code, Anthropic’s coding agent, connected to IdentityRM over MCP on his credential. Nothing here is specific to Claude; any MCP client that asks before it acts gets the same answers and leaves the same records. He starts where his persona starts, at home. He asks to push. The hook asks IdentityRM whether git.push on Developer Tooling API is allowed from Seattle Office. It is not, and the node is named.

Claude Code terminal: the push refused with Permission denied for git.push on Developer Tooling API at Seattle Office
Refused at Seattle Office, with the position in the sentence.

I did not ask for the next paragraph. Claude Code wrote it on its own after the refusal, and it is the first time I have watched an agent explain authority back to me and get it right. Quoted exactly:

This is the governance model working as designed. The hook does not care that the same human holds push rights elsewhere. It evaluates the grant at the node you are acting from, so a persona with no role on the resource is denied even though the identity behind it could push from another node.

He switches persona to Engineering, which is itself a recorded act, and pushes again. Allowed.

Claude Code terminal: persona switched to Engineering, the push allowed and the remote updated
Same person, same key, same command. The position changed, so the answer changed.

Same person, same key, same command, same Auth0 scope. The answer depended on where he stood, and the record says so each time.

On the first run it went differently, and better. Claude Code worked out that the role lived at Engineering and tried to switch itself there. The harness would not let that happen silently: the switch needed a human to say yes, and it is itself a recorded act. In the first post of this series we let Claude Code stop asking for the things it had been given authority for. A change of position is not one of them. An agent reaching for authority it was not acting under is the whole problem, and this is what it looks like when the question gets asked, and when the agent learns the answer.

Take it back

We did not have to revoke anything. The grant carried a three-day expiry, the account and the position carry their own, and the earliest one wins. Jordan took it back by hand because the rehearsal was over, and that is a governed act with its own sealed record, like the grant. Issue, scope, expire, revoke, all on a catalogue we do not own, with a decision we do.

What this is and is not

It is a catalogue that lives in Auth0, mastered in IdentityRM: authored here, provisioned there, with positions, owners, a receipt before the act, a sealed decision at the act, a record either way, and the provider kept in step. It is under ten minutes of setup for a catalogue that already exists, which is the part I would put in front of anyone who thinks governing agent authority means a migration. It is not Auth0 enforcing anything. The push was checked by a hook that asked IdentityRM, and the hook could have asked about any catalogue. What makes the scope authoritative is the question that gets asked before it is used, and who is entitled to the answer. Nothing in it is specific to Auth0 either. The same handler shape exists for PingOne application permissions, and the questions do not change when the catalogue does.

Twenty years of policy engines have promised this. XACML, and AuthZEN as its cleaner request shape, never became the common case, because the policy they evaluate has to be written by hand, and the hand has to keep up with the org chart. Static machinery is expensive machinery. What you watched here is a smaller construct: a position in a governed model, asked before the act, with the answer kept.

This grant expires in three days. The next post is the one I promised last time: what the record says when it was alive at the start of the week and is not by the end of it.


IdentityRM is the system of record for authority: who may do what, where, until when, granted by whom, consulted at the moment of decision. Start with By What Authority? for the position, Then I Told It Who to Ask Instead for the grant, or the platform.

Provenance: every screen above is from two sessions on the same instance, 8 and 12 October 2026, captured by hand. Times on the cards are local.


Share
All Posts

More from the Blog

AI Agent Governance

Then I Told It Who to Ask Instead

The practical follow-on to I Told Claude Code to Stop Asking Me. We modeled git push as a permission, gave a delegated owner the authority to grant it, and put a hook in Claude Code that asks IdentityRM before the shell runs. Refused with a reason, fixed by someone whose authority to fix it was recorded, allowed with no prompt, refused again from a different position. Seven real frames, the server records for each, and a plain statement of what a courtesy hook does not enforce.

Read more →
AI Agent Governance

I Told Claude Code to Stop Asking Me

Coding agents like Claude Code and Codex stop and ask for permission constantly. That prompt is not a guardian - it is what an agent does when there is no authority model to consult, so the question gets routed to the only authority it can find: you. Allow once is an ungoverned grant. Allow always is a standing entitlement with no receipt. Here is what happens when the tools the agent calls carry their own authority model: the prompts disappear for governed operations and every governed act leaves a record instead of a click. And here is the catch I walked into: on the client side, that is still a moved click.

Read more →
AI Agent Governance

By What Authority?

The second question of delegation legitimacy, proven on camera: was the act in scope. The same engineer with the same credential is refused at New York Office and allowed at Engineering minutes apart, and IdentityRM names the position in its own sentence each time. The assistant switched positions on its own; the events API shows the whole bracket. Plus the two tiers of answer, what is sealed and what is only recorded, and why we speak the standards shape without claiming conformance.

Read more →