Human-in-the-Loop (HITL) for Transactional Verification avec CIBA : comment Okta protège les actions à risque des agents IA

Comment Okta utilise le standard OpenID CIBA pour qu’un agent IA puisse initier une action sensible et qu’un humain l’approuve avant exécution.
Principe : l’agent agit, l’humain doit pouvoir dire non
Protéger la porte d’entrée d’une application — authentification OIDC ou SAML via un IdP de confiance reste indispensable. Ce n’est plus suffisant dès lors qu’un agent IA dispose déjà d’une session et d’outils : le risque se déplace de "qui s’est connecté ?" à "quelle action l’agent tente-t-il de réaliser maintenant ?"
Les agents ne se contentent plus de résumer un document. Ils appellent des outils, écrivent dans des SaaS, déclenchent des paiements, modifient des droits, suppriment des données. Leur donner des scopes et des tokens, c’est leur donner le droit d’agir. Pour autant, cela ne signifie pas leur donner le feu vert pour chaque opération (notamment à risque) sans validation.
Okta positionne explicitement le Human-in-the-Loop (HITL) pour ces cas : opérations sensibles (ex. supprimer des données de production) → workflow d’approbation humaine basé sur CIBA (Client-Initiated Backchannel Authentication). Chez Okta, ce mécanisme s’appelle aussi Transactional Verification.
HITL = le modèle (« l’agent attend un humain »).
CIBA / Transactional Verification = le protocole qui porte la confirmation.
L’idée :
L’agent (ou son UI) démarre l’action sur un appareil.
L’humain l’approuve sur un autre.
Comment on sécurise ces actions aujourd’hui
Pour l’authentification « front door », on s’appuie sur des standards matures. Pour la vérification d’une action une fois l’agent déjà en session, beaucoup de designs restent encore ad hoc.
Deux écueils reviennent souvent :
Expérience et confiance. Demander à l’humain de "re-prouver" son identité par des questions de type PII, un OTP SMS, ou un second login navigateur au milieu d’une tâche agentique, freine l’usage - et reste fragile face à l’ingénierie sociale.
Privilège trop large. Pour que l’agent (ou son backend) puisse exécuter l’opération, on lui confie souvent un credential large (jetons ou clés API avec des permissions trop étendues, compte de service trop large, clé API durable). S’il fuit, ou si l’agent enchaîne des appels aux outils de l'organisation, le risque est maximal.
On voudrait l’inverse : un mécanisme standard où l’agent initie la demande, l’humain confirme "hors bande", et l’application ne reçoit que le juste privilège pour cette transaction - pas un droit permanent de tout faire.
CIBA répond exactement à ce découplage.
Autorisation ≠ HITL
Un agent peut être correctement autorisé (scopes, policies, XAA, STS…) et malgré tout devoir s’arrêter avant une action destructive ou irréversible.
| Couche | Question | Mécanisme |
|---|---|---|
| Autorisation | L’agent peut-il faire cette classe d’actions ? | Scopes / policies |
| HITL | L’humain confirme-t-il cette action ? | CIBA / Transactional Verification |
Sans HITL, un agent "bien scopé" peut encore enchaîner des opérations sensibles sous une session valide. Avec CIBA, l’agent reste dans un état non privilégié pour cette transaction jusqu’à l’Approbation requise.
Découpler l’initiation et l’approbation avec CIBA
L’idée centrale est de découpler l’authentification / l’approbation de l’application qui consomme le résultat.
Avec CIBA, le client (ici : l’app ou le backend de l’AI Agent) initie le flux en back-channel vers le fournisseur OAuth 2.0, sans rediriger l’utilisateur via un navigateur sur l’appareil de consommation. La vérification se fait indépendamment sur un autre appareil (téléphone ou device enrôlé) en possession de l’humain responsable.
Pour un agent, cela signifie :
L’agent détecte une action à risque (parce qu'on lui a "expliqué" au préalable ce qu'est une action à risque) et envoie une requête CIBA à Okta.
Okta pousse une notification sur le mobile/device de la personne en charge d'approuver (pas une page de login sur l’UI de l’agent !).
L’humain lit le contexte et Approuve ou Refuse.
Okta délivre (ou non) un token scopé utilisateur à l’application, avec une durée de vie limitée : juste assez pour conclure cette opération.
Bénéfices directs :
Expérience : l’humain tranche sur son appareil de confiance, sans avoir à saisir de nouveau ses credentials sur le canal de l’agent.
Sécurité : le push enrôlé offre en pratique une meilleure garantie qu’un OTP SMS hors bande « faible ».
Moindre privilège : le token obtenu après l'action "Approve" est étroitement lié à l’utilisateur et à la transaction, plutôt qu’à un super-pouvoir permanent côté agent.
Deux appareils, un feu vert humain
CIBA étend OIDC : flux découplé, initié sur un appareil, vérifié sur un autre.
| Rôle | Nom Okta | Dans un scénario agent | Rôle |
|---|---|---|---|
| Qui initie | Consumption device | UI / backend de l’AI Agent (app Web OIDC) | Envoie /bc/authorize, poll le résultat |
| Qui valide | Authentication device | Mobile de l’humain + Custom Authenticator | Affiche le contexte, Approve / Deny |
L’agent continue son raisonnement / son parcours UI. L’humain reçoit le push, lit le binding_message, tranche. Okta délivre (ou non) les tokens - seulement alors l’action peut aboutir (ou non).
MFA vs CIBA : l’agent n’a pas besoin d’un second login — il a besoin d’un feu vert (approbation)
Le MFA protège surtout l’entrée en session (souvent celle de l’humain qui utilise l’agent, ou le sign-on associé).
CIBA protège la transaction que l’agent s’apprête à exécuter.
Le "binding_message" est le texte affiché sur le mobile. Pour un agent, il doit décrire l’action tentée, pas un login générique :
« L’agent demande à supprimer 12 enregistrements en production »
« L’agent demande un virement de 15 000 € »
« L’agent demande à exporter la base clients »
Sans ce contexte, un push ressemble à une fatigue MFA. Avec lui, c’est une preuve de volonté humaine sur une action d’agent nommée.
Le flux Agent IA → Okta → Humain → Agent IA
Quatre acteurs : l’AI Agent (qui initie), le consumption device, l’authorization server Okta, l’authentication device (humain).
Déroulement
L’agent détecte une action à haut risque et initie CIBA via le consumption device (son app / backend OIDC).
Requête
POST/oauth2/.../v1/bc/authorizeavec :scope(dontopenid, requis) ;soit
id_token_hint, soitlogin_hint(pas les deux) pour identifier l’humain qui doit approuver ;binding_messagedécrivant l’action de l’agent ;optionnellement
request_expiry.
Okta notifie le Custom Authenticator et renvoie
auth_req_id(+expires_in,interval).L’humain est notifié sur le mobile.
L’agent / le backend poll
/token(grant_type=urn:openid:params:grant-type:ciba+auth_req_id).Tant que l’humain n’a pas répondu :
authorization_pending— l’agent n’exécute pas.Après Approve : tokens délivrés.
Seulement alors : appel outil / API métier. Si Deny ou timeout : l’agent s’arrête ou bascule sur un chemin de secours.
id_token_hint convient quand l’humain est déjà authentifié auprès du même authorization server (session liée à l’usage de l’agent). login_hint identifie typiquement l’humain par email.
Sans request_expiry, la validité documentée par défaut est 300 secondes.
CIBA, sur OAuth 2.0 et OIDC
CIBA est une extension d’OIDC (elle-même fondée sur OAuth 2.0). Elle ajoute le grant :
urn:openid:params:grant-type:ciba
Comme pour les autres flux OIDC, le document de discovery expose des métadonnées supplémentaires, notamment backchannel_token_delivery_modes_supported et backchannel_authentication_endpoint.
La spécification définit trois modes pour notifier le client que l’authentification / l’approbation est terminée :
| Mode | Principe |
|---|---|
| Poll | Le client (backend / app de l’agent) interroge l’AS jusqu’au succès ou timeout. |
| Ping | Callback statut vers une URL du client, puis demande de tokens. |
| Push | Callback avec les tokens. |
Poll est le plus simple à implémenter. Ping et Push réduisent les allers-retours réseau, mais demandent plus de métadonnées et d’implémentation côté client.
Okta Workforce : mode documenté pour Transactional Verification = poll uniquement (backchannel_token_delivery_mode = poll). Le serveur d'autorisation Okta expose le grant CIBA ; l’authentification hors bande s’appuie seulement sur un Custom Authenticator (Devices SDK), embarqué dans l’application mobile métier ou dans une application compagnon.
Parce que la requête CIBA part en back-channel, le serveur d'autorisation doit pouvoir identifier l’humain à notifier : via login_hint ou id_token_hint (l’un ou l’autre, pas les deux).
Configurer CIBA pour un agent (org Okta)
Trois briques - le consumption device est l’app OIDC de l’AI Agent (ou de sa plateforme) :
1. App OIDC Web de l’agent (consumption)
Admin Console → Applications → Create App Integration.
OIDC → Web Application (type supporté pour CIBA dans le guide).
Grant types → Advanced → Client-initiated backchannel authentication (CIBA).
Preferred authenticator for CIBA → Custom Authenticator.
Redirect URIs, Client ID / secret (ou autre auth client documentée).
API : grant_types inclut urn:openid:params:grant-type:ciba, plus backchannel_custom_authenticator_id, et optionnellement backchannel_token_delivery_mode=poll.
2. Authorization Server (AS)
Org AS ou custom AS (default, etc.) :
Security → API → Authorization Servers.
Access policy → Advanced → activer le grant CIBA.
Update rule.
3. Custom Authenticator (côté humain)
Custom Authenticator via Devices SDK.
Device enrôlé pour l’utilisateur responsable.
Transactions CIBA activées (option utilisateur dans le sample Okta, ou activées par défaut dans une app métier).
Tant que CIBA n’a pas abouti, l’agent n’exécute pas
Le push seul ne sécurise rien si l’agent exécute quand même.
L’agent (ou sa gateway) bloque l’outil à risque tant que CIBA n’a pas réussi.
Après Approve, il dispose des tokens.
L’API / outil cible n’accepte l’opération sensible qu’avec une preuve valide - en plus des scopes d’autorisation habituels.
Autorisation + HITL, pas l’un ou l’autre.
Au-delà des agents : les mêmes fondations métier
CIBA n’a pas été inventé uniquement pour l’IA. Le blog Developer Okta décrit des cas où le login classique ne suffit pas : mise à jour d’email en centre d’appels, paiement POS sur terminal partagé, helpdesk, kiosques, contextes réglementaires (FAPI / Open Banking selon les régions).
La même mécanique sert l’actualité agents : initiation découplée, approbation humaine out-of-band, token en sortie.
Points de vigilance
Fatigue MFA / pushes répétés. Un attaquant (ou un agent mal configuré qui re-tente en boucle) peut saturer l’humain de demandes. Risque : Approve par lassitude. Côté agent, le rate limiting, un timeout clair et l’absence de retry agressif après Deny limitent ce risque.
Initiation forcée. Okta rappelle qu’un attaquant peut forcer l’initiation d’événements d’autorisation (guess d’identifiants, listes). Pour un agent, cela renforce l’intérêt de ne déclencher CIBA que sur une liste courte d’actions à haut risque - pas sur chaque tool call.
Same-device.
« CIBA should not be used in a same-device scenario where the consumption and authentication devices are the same. »
Source : Introducing CIBA for Secure Transaction Verification.
Si l’humain utilise l’agent sur le même téléphone que le Custom Authenticator, ce n’est pas le scénario recommandé pour CIBA.
Dans certains cas, Okta évoque le device code flow (initiation active par l’utilisateur via QR / code) comme alternative plus sûre face à l’initiation forcée.
Quand déclencher CIBA dans un agent ?
| Situation | CIBA / HITL |
|---|---|
| Tool call destructif (delete, wipe, revoke) | Oui |
| Montant / volume au-delà d’un seuil | Oui |
| Export de données sensibles | Oui |
| Lecture / recherche à faible impact | Non (scopes suffisent en général) |
| MFA de login utilisateur | Non - autre mécanisme |
| App agent + Approve sur le même device | Non recommandé |
Ce que ça change pour sécuriser les agents
Protéger la porte d’entrée ne suffit plus. Dès qu’un agent opère avec des outils, il faut une vigilance continue : zero trust aussi pendant l’exécution, pas seulement au login.
Au départ la question est : quel token l’agent possède-t-il ? Elle devient : pour cette action-là, un humain a-t-il confirmé et le backend peut-il le prouver ?
Identité & autorisation : qui est l’agent, quels scopes ?
HITL via CIBA : feu vert ponctuel, contextuel, out-of-band.
Preuve API : pas d’exécution sensible sans token / preuve après Approve.
Transactional Verification ne remplace pas XAA, STS ou les policies. Elle les complète - là où l’autonomie de l’agent croise le risque métier.


![Auth0 Series [1/10] : Introduction à Auth0](https://cdn.hashnode.com/res/hashnode/image/upload/v1758653492299/4e97a6ee-2bdf-46af-bc56-b5383d36aefd.jpeg)
