From CIBA to Deferred Token Response

Max Gerber

May 2026

Why HITL Matters

Agents need a human in the loop

Agents operate autonomously. But some actions are too high-risk to let an agent execute without a human confirming.

  • Irreversible: deleting an account, sending a wire transfer
  • Expensive: provisioning infrastructure, purchasing inventory
  • Sensitive: sharing a document, modifying permissions
  • Regulated: compliance-gated transactions, financial approvals

Re-engaging the human prior to execution is table-stakes for agent auth.

Modeling HITL

HITL approval can be managed in two ways:

  1. The Agent Harness is responsible
  2. The Domain being accessed is responsible

Agent Harness Managed

ResourceServerLLMAgentFrameworkuser@exampleAccessTokenCan I do this?Yes/No

Agent Harness Managed

Agent Harness intercepts tool calls and determines if human confirmation is needed.
Examples: Claude Code / A2H

Pros:

  • Native experience built into Agent UX
  • Agent Harness understands intent across many domains

Cons:

  • Can Harness be trusted to do HITL correctly?
  • How is HITL "proven" to the Domain being acted on?
  • How does logging / audit work?

Domain Harness

ResourceServerLLMAgentFramework1. Try Requestuser@exampleAuthz Server2. Fail with Challenge3. Request Token4. Can agent do this? 5. Yes/No6. Return Token7. Retry with Token

Domain Harness Managed

Resource Server issues WWW-Authenticate challenge. Client replays challenge to Auth Server. Auth Server contacts user.

Pros:

  • HITL approval cryptographically embedded via Access Token
  • AS in change of logging / audit responsibilities

Cons:

  • Approval workflow is Domain-specific

We are primarily interested in Domain Harness Managed HITL

  • Increasing usefulness of Access Tokens is good
  • Consolidating decision-making within the AS is good
  • Building on top of OAuth ecosystem is good

CIBA as a Solution for HITL

CIBA is often floated as the answer

OpenID Connect Client-Initiated Backchannel Authentication checks many boxes:

  1. AS owns the notification of the user (out-of-band channel: SMS, push, email)
  2. Client waits around for the result and retries later (polling)
  3. Newly issued access token contains verified proof of HITL from the AS

CIBA flow

ClientAuthorizationUserClient(Agent)AuthorizationServerUser(on phone)POST /backchannel/authenticate(id_token_hint, scope, binding_message)auth_req_id, expires_in, intervalOut-of-band notification(SMS, push, email)loop[polling]POST /token(grant_type=ciba, auth_req_id){ error: "authorization_pending" }ApprovesPOST /token(grant_type=ciba, auth_req_id)access_token, id_token

CIBA back half is great

The parts that work well for HITL:

  • AS decides how to reach the user. The client doesn't need to know the channel.
  • Polling is simple. Client just retries on an interval.
  • Token is proof. The issued token carries evidence that a human approved.
  • AS can take its time. No browser session to keep alive.

This is exactly what we want. But...

Problem 1: Client Initiated

The client decides when CIBA is required. The server has no way to signal it.

There's no mechanism for the AS to say, in response to a normal token request:

"Actually, I need human approval before I can issue this token. You need to wait a minute."

The client must know in advance that CIBA is the right thing to do, and once CIBA is initiated the user must be contacted.

What if the server wants to decide when HITL is required dynamically, based on risk, policy, or context?

Problem 2: Backchannel Authentication

CIBA is an OIDC extension, not an OAuth extension. It's optimized for authenticating a user, not requesting authorization to a resource.

The client must tell the AS who to send the notification to:

  • id_token_hint (a previously issued ID token)
  • login_hint (an email, phone number, etc.)
  • login_hint_token

The server cannot choose who to route the approval based on the request context.

What if the client doesn't know who the approver is?

With CIBA, the client must already know who that owner is and have an identifier for them. But often:

  • The client doesn't know who owns the resource
  • The approval might route to a system (ServiceNow, Okta Engine), not a person
  • The approver might not be the resource owner (delegated approval)
  • Multiple humans might need to approve

CIBA can't model any of this.

What We Actually Want

Ideal flow

ClientAuthorizationSomething ...ClientAuthorizationServerSomething ???POST /token(any grant type){ error: "authorization_pending",auth_req_id, expires_in, interval }Requests authorization(AS decides who/what/how)loop[polling]POST /token(auth_req_id){ error: "authorization_pending" }ApprovedPOST /token(auth_req_id)access_token

Key differences from CIBA

CIBA What we want
Who decides HITL is needed? Client Server
Who initiates? Client Server
Who picks the approver? Client Server
Which grant types? CIBA grant only Any

We could call this...

Server Initiated Backchannel Authorization

(SIBA)

just kidding...

Deferred Token Response

AS reaches out to "something"

That "something" is not constrained to be a single user that the client names. This unlocks:

Authorization ServerResource OwnerApproval System(ServiceNow, Okta)Delegation Chain(manager approvesfor OOO IC)client route to resource owner(client doesn't need to know who)route to external systemsmulti-human ordelegated approvals

Concrete flexibility

  • Route to resource owner: Client wants to modify a document. AS knows who owns it. Client doesn't need to.
  • Route to systems: Approval goes to a ServiceNow ticket, Jira workflow, or Slack channel.
  • Delegated approval: IC is on vacation. Their manager can approve on their behalf.
  • Multi-party: Two of three admins must approve before the token is issued.

None of this is possible when the client picks the approver.

Some CIBA implementations pepper the end user with individual approvals - one per unique request.

This leads to consent fatigue and increases the risk of a user approving a request they shouldn't.

CIBA is optimized for short-lived interactions notifying a specific user. By breaking this model we unlock:

  • Batch approval workflows combining requests from many resources & clients
  • Routing requests to users in a better position to evaluate them (IT Admins, Security professionals)
  • Programmatic approval or denial of requests based on standing policy

Batch Approval workflows

Authorization ServerClient 1Client 2Client 3user Resource AResource BResource CResource DResource EResource FResource GOne Batch NotificationBulk approve/deny

Examples

Example: Client Credentials

AgentAuthorizationResourceAgentAuthorizationServerResourceOwnerPOST /tokengrant_type=client_credentialsscope=docs:readaccess_token (read-only)Agent reads resources,identifies one to modifyPOST /tokengrant_type=client_credentialsscope=doc:write&resource=doc-789{ error: "authorization_pending",auth_req_id, interval }"Agent wants to modify doc-789.Approve?"ApprovedPOST /token (auth_req_id)access_token(scoped to doc-789, write)

Example: Token Exchange

AgentAuthorizationApproverAgentAuthorizationServerApproverPOST /tokengrant_type=token-exchangesubject_token=<valid token>resource=sensitive-api{ error: "authorization_pending",auth_req_id, interval }Token is valid, butthe requested resourcerequires approval.Requests authorizationApprovedPOST /token (auth_req_id)access_token(scoped to sensitive-api)

Beyond Agentic HITL

Example: Refresh Token

AgentAuthorizationAccountAgentAuthorizationServerAccountOwnerRefresh token expires in 6 months.At 5.9 months, AS proactivelyreaches out.(draft-ietf-oauth-refresh-token-expiration)"Agent still has access toyour account. Re-authorize?"At 6 months, agenttries to refresh.POST /tokengrant_type=refresh_tokenrefresh_token=rt_abc{ error: "authorization_pending",auth_req_id, interval }Re-authorizesPOST /token (auth_req_id)access_token, refresh_token(same RT, extended)No new auth_code flow needed.User didn't have to visit the app.Original grant is extended in-place

Banking already needs this

We care about HITL for agents, but it turns out this pattern is generally useful.
Some banking patterns require deferral for auth_code flows today.

Use Case: High-Risk Transaction Evaluation

A user initiates a high-risk transaction at their bank.
The OP notices unusual behavior and decides to defer until further verification is complete.

Verification may involve:

  • Contacting the user through alternative channels
  • Manual review by a fraud analyst
  • Additional security checks

The user does not need to remain in the banking application.
Transaction processing continues in the background as soon as a decision is made.

This can take minutes to hours.

Use Case: ID Verification from Physical Evidence

Many jurisdictions lack widespread digital identity. Identity verification relies on scanning physical documents (passport, driver's license) plus a liveness check.

Usually automated systems handle this. Sometimes a human operator must manually verify. This takes a long time and may involve contacting the user via another channel.

The RP can continue with steps that don't require completed verification, and notify the user when the final decision lands. Compliant with regulation on automated decision-making.

Prior art

Already an OIDF draft: openid-deferred-token-response-1_0.

It introduces response_type=deferred_code for auth_code flows that need arbitrary time to complete.

We're generalizing this: not just a new response type, but a pattern that applies to any /token response.

Significant overlap with draft-parecki-oauth-jwt-grant-interaction-response as well.

Parallel Workstreams

DTR describes how the AS notifies the Client during an approval workflow.

There is no standard for cases where the AS wants to route the approval to a separate system (ServiceNow, Okta Engine).

draft-mcguinness-authzen-access-request-latest in AuthZen WG seeks to address this gap.

This draft describes a common standard for requesting access from a workflow engine.

Next Steps

  • Work with OIDF authors to split the OIDF draft into 2
    • Core IETF draft
    • OIDF profile that only incudes OIDF concerns
  • Publish as an Individual Draft
  • Get on the agenda for IETF 126