Ask a named person to approve
Have an AI agent ask one named person to approve an action on their own device, and receive an access token that names both of them.
Sometimes an AI agent needs the approval of one particular person: the customer whose money it is moving, or the engineer whose change it is merging. The agent asks, the person answers on their own device, and the agent receives an access token that names that person.
This is OpenID Connect Client-Initiated Backchannel Authentication (CIBA), in poll mode. Backchannel means the person is asked outside the agent's own connection. Poll mode means the agent asks the token endpoint for the result until there is one.
To ask the agent's owner or approval group instead of a named person, see Ask before a sensitive action.
Before you begin
You need:
- A registered agent and its private key. See Give an AI agent an identity.
- The name the person signs in with, for example
[email protected].
The agent authenticates here exactly as it does to sign in: with a client assertion, a short statement signed with the agent's own key. $ASSERTION in the examples is a client assertion built as in Give an AI agent an identity. An assertion is accepted once, so build a new one for every request.
Send the request to the person
POST
/apis/regional/v1/ai/auth/backchannel-authorizeThe body is form-encoded.
curl https://acme.authfi.io/apis/regional/v1/ai/auth/backchannel-authorize \
-d client_id=agt_7f3a9c21 \
-d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
-d client_assertion="$ASSERTION" \
-d [email protected] \
-d scope="transfer:accounts" \
--data-urlencode "binding_message=Send 1,200 USD to Northwind Ltd" \
-d requested_expiry=300client_id is the agent ID, agt_7f3a9c21 in this example. The console shows it as "Client id" on the agent's Connect tab, under Identity > AI Agents.
{ "auth_req_id": "bXl0aWNrZXQtNDgyMQ...", "expires_in": 300, "interval": 5 }The person is notified. They see the agent's name and your binding message.
The person answers on the Approvals page of the console, under "Asking to act as you". They choose Approve to approve, or Refuse to deny. Only the named person can answer the request.
export AUTH_REQ_ID=<the auth_req_id from the response>Poll for the answer
Ask the token endpoint with the auth_req_id, no more often than every interval seconds. Each poll carries a fresh client assertion.
POST
/apis/regional/v1/ai/auth/tokencurl https://acme.authfi.io/apis/regional/v1/ai/auth/token \
-d grant_type=urn:openid:params:grant-type:ciba \
-d auth_req_id="$AUTH_REQ_ID" \
-d client_id=agt_7f3a9c21 \
-d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
-d client_assertion="$ASSERTION"Until the person answers, the response is a 400 with an OAuth error:
{ "error": "authorization_pending" }Use the access token
The access token says who approved and who is acting.
Send it as a Bearer credential. A service that receives it sees both identities: this is the agent, acting for that person. To check these claims in your own service, see Accept agents at your own API.
Check that it works
Send the request with your own sign-in name as login_hint.
- Poll once. The response is
400withauthorization_pending. - In the console, open Approvals. Under "Asking to act as you", choose Approve on the request. The console shows "Approved".
- Poll again. The response is
200with an access token. - Decode the access token.
subis you, andact.subis the agent.
How the approval is protected
- The agent cannot approve its own request. The person decides on a channel that belongs to them. The agent holds only the
auth_req_id, which approves nothing. - The scope is the one the person saw. The access token carries what was approved, not what the agent sends when it collects the token.
- An approval is used once. The first successful poll spends it. A second poll with the same
auth_req_idis rejected. - No answer is a denial. An unanswered request expires and can never be approved afterwards.
- A stolen
auth_req_idis useless alone. Every poll must be signed with the agent's key.
Write a good binding message
The binding message is the only thing the person reads before deciding, usually on a phone. Say exactly what will happen.
Name the amount, the destination and the thing. If the person cannot tell what will happen, they cannot approve it.
Troubleshooting
Every error of the token endpoint is listed in the errors reference.