Agents act while the user is somewhere else. Sooner or later a decision needs a person: to grant access in the first place, to prove it is really them, to approve something they cannot approve alone, or to confirm one specific action. This part maps each of those moments to the standard that handles it, and to the one rule that cuts across all of them.
That rule comes from the IETF’s draft on AI agents, draft-ietf-wimse-aims: a confirmation shown in the agent’s own interface does not, by itself, constitute authorization. It has to map to a verifiable grant, such as a token issued after the user approved on a channel the agent does not control. The agent must not treat a local “OK” as enough. A prompt-injected agent can draw its own confirmation dialog.
Four moments a human is needed
| Moment | The question | Who answers | Standard |
|---|---|---|---|
| Consent | May this agent act for me at all, and how far? | The user, once, up front | OAuth authorization code; RFC 9396 for detail |
| Step-up | Is this still really me, with strong enough authentication? | The user, at the authorization server | RFC 9470; MCP scope challenges |
| Approval | Should this access be granted, by someone allowed to grant it? | An approver, often not the user | AuthZEN Access Request and Approval Profile (draft) |
| Confirmation | Do I want this specific action, now? | The user, on a device they trust | CIBA; MCP URL-mode elicitation for third-party flows |
Consent at authorization time
The first human moment is the OAuth consent screen, and it is usually too vague to mean much. “Finance Assistant wants to access your payments” tells the user little about what the agent will actually do.
Rich Authorization Requests (RFC 9396) make consent specific. Instead of a scope string, the client sends authorization_details: an array of typed objects describing exactly what is requested. The RFC’s own example is a payment_initiation object with actions, an instructed amount and currency, and the creditor’s name and account. The RFC says this detail is what the authorization server needs to inform the user and obtain their consent. For an agent, that turns “access payments” into “pay up to 250 EUR to this creditor”, and the resulting token carries the same limits.
The MCP spec adds consent duties of its own. Authorization servers that accept Client ID Metadata Documents must clearly show the redirect URI’s hostname and should warn when every redirect URI is localhost (Part 4). MCP servers that proxy a third-party API with a static client ID must get the user’s consent for each dynamically registered client, to close the confused-deputy hole.
Step-up: more scope, or stronger authentication
Two different challenges look alike and are easy to confuse.
More scope. The MCP spec’s own step-up (Part 4): the server answers 403 with error="insufficient_scope" and the scopes it needs, and the client re-authorizes for the union of old and new scopes. The user may see a consent screen again, but nothing proves who they are more strongly than before.
Stronger authentication. RFC 9470, the OAuth 2.0 Step Up Authentication Challenge Protocol (September 2023), covers the case where the token is fine but the login behind it is not. The resource server answers with error="insufficient_user_authentication" and one or both of:
acr_values: the authentication context classes it will accept, in order of preference, such as one that requires a phishing-resistant authenticator;max_age: the most seconds allowed since the user last actively authenticated.
The client sends the user back to the authorization endpoint with those values, gets a new token, and retries. The new token records what happened in acr and auth_time. If the authorization server cannot meet the request, it should return unmet_authentication_requirements rather than a token that will fail again.
The MCP spec does not list RFC 9470 among its references. But an MCP server is an OAuth resource server, and nothing stops it using this challenge for high-risk tools. A rule like “payments require authentication in the last five minutes” maps to max_age=300.
Both kinds of step-up need the user at a browser. That is fine for an agent in a chat window, and a problem for one running in the background. That is the case CIBA solves.
Out-of-band approval with CIBA
OpenID’s Client-Initiated Backchannel Authentication (CIBA Core 1.0, Final) was built for a client that cannot redirect the user’s browser, which describes most background agents. The client asks the authorization server directly; the user approves on a separate authentication device, typically their phone. draft-ietf-wimse-aims names it as the human-in-the-loop mechanism for agents, because the agent never touches the user’s credentials.
The steps, in poll mode:
- The agent POSTs to the authorization server’s
backchannel_authentication_endpoint, authenticating as it would at the token endpoint. It sendsscope(includingopenid), exactly one hint identifying the user (login_hint,id_token_hintorlogin_hint_token), and abinding_message. - The server returns an opaque
auth_req_id, itsexpires_inand a pollinginterval, 5 seconds by default. - The user’s device shows the request with the binding message, for example “Approve transfer of 250 EUR, code 4F7K”. The same message appears on the device where the request started, so the user can check they match.
- The user approves, or doesn’t.
- The agent polls the token endpoint with grant type
urn:openid:params:grant-type:cibaand theauth_req_id. - Once approved, it receives the tokens.
- It retries the tool call with the new token.
The delivery mode is fixed when the client registers. Besides poll, there is ping, where the server calls the client’s notification endpoint and the client then fetches the tokens, and push, where the server sends the tokens directly. Ping and push need a client_notification_token and an HTTPS notification endpoint, and push needs extra protection for that endpoint.
For agents, the binding message does the important work. It is what lets the user see that the approval on their phone is for this transfer, and not one a prompt-injected agent made up. Make it specific: amount, payee, a short code.
draft-ietf-wimse-aims also marks the limit. CIBA covers flows the client starts. Interrupting an agent mid-task to ask the user something, at different stages of execution, may need more standards work.
Approvals after a deny: the AuthZEN Access Request and Approval Profile
Sometimes the user cannot approve the action themselves: the agent needs access the user does not have, or policy requires a manager or a second person. The AuthZEN Access Request and Approval Profile (Draft 1, November 2026, an OpenID AuthZEN working-group draft) standardizes what happens after such a deny.
- The PDP marks the deny as requestable. It returns
decision: falsewith acontext.access_requestobject.expires_atis required;endpoint,template,displayhints and abinding_tokenare optional. - The PEP submits a request. It POSTs the denied subject, resource and action, plus the
denialvalues echoed unchanged, to the given endpoint or the PDP’saccess_request_endpoint. It may add context, a requested end time and anemergencyflag. - The service returns a task. A
201or202with a taskid,statusandstatus_endpoint. - The PEP waits. It polls the status endpoint with exponential backoff and jitter, honouring
Retry-After, or receives a callback defined by a companion profile. Statuses arepending,approved,denied,expired,cancelledandfailed, and anything unknown counts as not approved. - On approval, the PEP asks again. It runs a new evaluation with the
approvalobject incontext.approval. The approval never grants access on its own; the PDP decides again, with the approval as evidence.
The security rules are what make this safe for agents:
- A requestable deny is still a deny. The PEP must not grant anything because
access_requestis present. - The PDP must not authorize on a known approval ID alone. It must check the approval against trusted state or integrity-protected material: subject, resource, action, scope, expiry and revocation.
approval.approved_untilbounds everything. The PEP must not use the approval after it, and any downstream credentials must expire by then.- Approver eligibility and separation of duties are enforced before approval, and
emergencyis a request signal, not an override. - Approval IDs and review links should not be forwarded to end clients, which for us means: keep them away from the agent.
Asking the user from inside MCP: elicitation
MCP has its own way for a server to ask the user something mid-request: elicitation. It has two modes, and they have very different roles.
Form mode collects structured data through the MCP client, using a flat JSON schema. Servers must not use it for sensitive information: passwords, API keys, access tokens or payment credentials. Clients must show which server is asking and offer clear decline and cancel options, and the user answers with accept, decline or cancel. Form mode is fine for “which account should I use?”. By the rule at the top of this part, it is not an authorization for “move the money”.
URL mode sends the user to a web page outside the client, for interactions that must not pass through it. Its main use is third-party OAuth: the MCP server acts as an OAuth client to another service and needs the user to authorize it. The spec’s rules here are strict:
- URL mode is not for authorizing the MCP client to the MCP server; that is MCP authorization (Part 4). Servers must not use it to authorize users for themselves.
- Third-party credentials must not pass through the MCP client, and the server must not use the client’s token at the third party, which would be token passthrough.
- The server must check that the person who completes the flow is the same user who triggered it. Otherwise an attacker can send the link to a victim and end up with tokens bound to the attacker’s session.
- Clients must show the full URL, must not open it without explicit consent, must not pre-fetch it, and must open it where neither the client nor the model can see the content or the user’s input.
One gap to know about: COAZ-MCP (Part 5) leaves server-initiated requests, including elicitation/create, out of scope in its current draft. Elicitations are not checked by the PDP.
Choosing the mechanism
Start from the situation the agent is in, not from the standard:
| Situation | Use | Why not the alternatives |
|---|---|---|
| The agent needs a well-defined grant, such as a payment limit, before it starts | RAR (RFC 9396) at consent | Scope strings are too coarse for the user to judge |
| The token lacks a scope for this tool | MCP insufficient_scope step-up | Nothing about the user’s authentication is in question |
| The action needs a recent or stronger login, and the user is at a browser | RFC 9470 with acr_values or max_age | CIBA works too, but a redirect is simpler when the user is there |
| The action needs the user’s approval and they are not at the agent’s screen | CIBA with a binding_message | An in-agent dialog is not authorization (draft-ietf-wimse-aims) |
| The access must be approved by someone else, or needs separation of duties | AuthZEN Access Request and Approval Profile | CIBA asks only the user; approvals need an approver and an audit trail |
| The MCP server needs the user to connect a third-party account | MCP URL-mode elicitation | Form mode must not collect credentials, and passthrough is forbidden |
| The agent needs a non-sensitive choice from the user | MCP form-mode elicitation | It gathers input, not authorization |
Standards status (November 2026)
| Standard | Status |
|---|---|
| RFC 9396, Rich Authorization Requests | RFC (May 2023) |
| RFC 9470, Step Up Authentication Challenge | RFC (September 2023) |
| OpenID CIBA Core 1.0 | OpenID Final (2021) |
| AuthZEN Access Request and Approval Profile | OpenID working-group draft, Draft 1 (November 2026) |
| MCP elicitation, form and URL modes | MCP revision 2026-07-28; URL mode was introduced in 2025-11-25 and may still change |
| AI Identity Management System (draft-ietf-wimse-aims) | WIMSE working-group draft -01, Informational |
Sources
- RFC 9396: OAuth 2.0 Rich Authorization Requests
- RFC 9470: OAuth 2.0 Step Up Authentication Challenge Protocol
- OpenID Client-Initiated Backchannel Authentication (CIBA) Core 1.0
- AuthZEN Access Request and Approval Profile 1.0, Draft 1
- MCP Elicitation (revision 2026-07-28)
- MCP Authorization Security Considerations
- AI Identity Management System, draft-ietf-wimse-aims
- COAZ-MCP: COAZ Binding for the Model Context Protocol, Draft 1