De l’Aperçu à l’Implémentation#
Dans la Partie 2 de cette série j’ai présenté les quatre patterns d’accès qu’Okta for AI Agents (O4AA) fournit — XAA, STS, PSK et Service Account — ainsi que le cadre stratégique pour choisir entre eux. Cet article répondait à quel pattern et pourquoi.
Cette plongée approfondie répond au comment. Pour chaque pattern, je détaille le flux du protocole, les diagrammes de séquence, la structure du token (lorsque pertinent), les signaux d’audit à attendre dans les journaux système Okta, les cas d’usage où il s’applique, et les étapes de configuration concrètes dans la console d’administration Okta. Si vous êtes architecte ou ingénieur solutions sur le point d’implémenter l’un de ces patterns, c’est le guide de référence à garder ouvert dans un second onglet.
Allez directement au pattern que vous mettez en œuvre — chaque section est autonome :
- Cross App Access (XAA) — le pattern stratégique basé sur ID-JAG
- Secure Token Service (STS) — pont OAuth pour les SaaS n’ayant pas encore adopté ID-JAG
- Pre-Shared Key (PSK) — secrets en coffre-fort pour les services legacy à clés API
- Service Account — nom d’utilisateur/mot de passe pour les systèmes qui ne supportent rien d’autre
- De la Théorie à la Pratique — guide de configuration dans la console d’administration Okta
Cross App Access (XAA)#
Cross App Access (XAA) est le pattern d’accès phare d’Okta for AI Agents. Il implémente un accès délégué par l’utilisateur et tenant compte du contexte utilisateur via l’Identity Assertion JWT Authorization Grant (ID-JAG), un standard IETF émergent pour la délégation sécurisée1.

Pourquoi XAA est Important#
XAA est le premier pattern d’accès à intégrer le contexte d’identité complet à chaque étape d’un workflow d’agent. Chaque token contient à la fois :
sub: L’identité utilisateur (qui a autorisé cette action)act.sub: L’identité de l’agent (quel agent agit en son nom)
Cette structure à double identité permet des capacités impossibles avec les comptes de service traditionnels :
- Attribution d’audit par utilisateur : Chaque action de l’agent est traçable jusqu’à l’utilisateur spécifique qui l’a autorisée
- Révocation chirurgicale : Désactiver l’accès d’un utilisateur à un agent sans affecter les autres utilisateurs ou agents
- Réduction de portée : Les permissions effectives du token correspondent à l’intersection la plus étroite de ce que l’agent est autorisé à faire, de ce à quoi l’utilisateur a droit, et de ce que la tâche spécifique requiert
- Conformité réglementaire : Pistes d’audit complètes satisfaisant aux exigences de traçabilité NIST SP 800-63-42, EU AI Act3, NIS24 et DORA5
Comment Fonctionne XAA : Le Flux ID-JAG#
Le flux XAA implique une séquence d’échange de tokens où Okta garantit l’identité de l’utilisateur auprès du serveur d’autorisation de la ressource cible.
sequenceDiagram
autonumber
actor User
participant Client as 🤖 Client
(AI Agent)
box rgba(243, 242, 247,0.3) Okta Cloud
participant IdP as 🔐 IdP AS
(Okta Org AS)
participant AS as 🛡️ Resource AS
(Custom AS)
end
participant RS as 📦 Resource Server
(Protected API)
Note over User, RS: Étape 1 : Authentification Utilisateur (OIDC SSO)
User->>Client: Initier l'action
Client->>IdP: Auth Code + PKCE
IdP->>User: Authentification (MFA)
User-->>IdP: Identifiants
IdP-->>Client: ID Token + Refresh Token
Note left of IdP: sub:user
aud:client
Note over User, RS: Étape 2 : Échange de Token (RFC 8693)
Client->>IdP: Requête d'échange de token
Note right of Client: grant_type:token-exchange
subject_token:ID_Token
requested_token_type:id-jag
audience:Resource AS
IdP->>IdP: Valider l'ID Token
Note right of IdP: private_key_jwt
politique de connexion gérée
IdP->>IdP: Générer l'ID-JAG
IdP-->>Client: ID-JAG (Identity Assertion)
Note left of IdP: sub:user
aud:Resource AS
client_id:agent
Note over User, RS: Étape 3 : JWT Bearer Grant (RFC 7523)
Client->>AS: Requête JWT Bearer
Note right of Client: grant_type:jwt-bearer
assertion:ID-JAG
scope:orders:read
AS->>AS: Valider l'ID-JAG
Note left of AS: correspondance aud
correspondance client_id
signature (JWKS)
AS->>AS: Appliquer la politique d'autorisation
AS-->>Client: Access Token
Note left of AS: sub + act.sub + scope
éphémère
Note over User, RS: Étape 4 : Appel API
Client->>RS: Appel API (avec Access Token)
RS->>RS: Valider le Token (JWKS)
RS-->>Client: Données de réponse
Décomposition étape par étape#
- Authentification utilisateur (OIDC SSO) : L’utilisateur initie une action via l’application client. Le client redirige vers le serveur d’autorisation Org d’Okta en utilisant Authorization Code + PKCE. L’utilisateur s’authentifie (MFA incluse si configurée), et Okta émet un ID Token et optionnellement un Refresh Token. Cet ID Token devient le
subject_tokenpour l’étape suivante. - Échange de token chez Okta (RFC 8693) : L’agent s’authentifie avec ses identifiants de charge de travail (
private_key_jwt) et demande un échange de token (grant_type: token-exchange,subject_token: ID Token,requested_token_type: id-jag,audience: Custom AS). Okta valide le token, vérifie la politique de connexion gérée, et génère un ID-JAG — un JWT signé contenantsub(utilisateur),aud(Custom AS) etclient_id(agent). - JWT Bearer grant au Custom AS (RFC 7523) : L’agent présente l’ID-JAG au point de terminaison token du Custom AS (
grant_type: jwt-bearer,assertion: ID-JAG,scope: orders:read). Le Custom AS valide la signature de l’ID-JAG via JWKS, confirme queaudetclient_idcorrespondent, applique sa politique d’autorisation locale, et émet un token d’accès éphémère avecsub+act.sub. - Appel API : L’agent appelle la ressource protégée avec le token d’accès à portée limitée. La ressource valide le token via JWKS et retourne les données.
Ce diagramme utilise les noms de rôles de la spécification ID-JAG. Voici comment chaque rôle IETF correspond à l’implémentation Okta :
| Rôle IETF | Équivalent Okta |
|---|---|
| Client | L’agent IA (ou sa couche frontend/orchestration) — le principal de charge de travail enregistré dans Okta |
| IdP AS | Le serveur d’autorisation Org d’Okta, adossé à Universal Directory et Okta SSO |
| Resource AS | Un Custom Authorization Server dans Okta, protégeant les APIs en aval |
| Resource Server (RS) | La ressource protégée — une API interne, un serveur MCP ou une API tierce |
En pratique, le bloc « Client » représente plusieurs composants travaillant ensemble : une application frontend (interface de chat, application web) gérant l’authentification utilisateur via OIDC, une couche d’orchestration gérant l’état des conversations et les appels d’outils, et un ou plusieurs agents backend (principaux de charge de travail) effectuant les échanges de tokens. Je les ai regroupés dans un seul bloc pour garder le focus sur le flux protocolaire plutôt que sur l’architecture interne.
Présence Utilisateur et Modèle de Consentement#
Un avantage clé de XAA est l’élimination de l’étape de consentement interactif auprès du Resource Authorization Server. Contrairement aux flux OAuth traditionnels où chaque ressource demande le consentement de l’utilisateur séparément, dans XAA l’IdP évalue les politiques définies par l’administrateur et délègue l’autorité d’autorisation. Le Resource AS fait confiance à l’assertion de l’IdP sans solliciter l’utilisateur — c’est ce qu’oauth.net décrit comme un accès “without any user interaction” au niveau de la ressource.
Cependant, XAA nécessite l’authentification de l’utilisateur pour amorcer le flux. L’utilisateur doit s’authentifier via OIDC SSO (Étape 1) pour que l’agent obtienne un ID Token comme subject_token pour l’échange de token. Chaque action de l’agent est liée à l’identité et aux permissions d’un utilisateur spécifique authentifié.
La spécification ID-JAG définit une capacité optionnelle (MAY) permettant aux implémentations d’accepter des Refresh Tokens comme subject_token, autorisant les agents à obtenir de nouveaux ID-JAG sans ré-authentifier l’utilisateur. Cela permettrait des opérations véritablement autonomes pour les tâches planifiées ou déclenchées par événement.
Toutefois, cette capacité n’est pas encore documentée dans l’implémentation XAA d’Okta ni sur xaa.dev. Aujourd’hui, le flux XAA d’Okta nécessite un ID Token obtenu d’une authentification utilisateur active comme subject_token. Pour les scénarios nécessitant des opérations en arrière-plan sans présence utilisateur, envisagez de combiner XAA (quand le contexte utilisateur est disponible) avec d’autres patterns comme PSK ou Service Account pour les opérations autonomes.
Le Standard ID-JAG#
ID-JAG (Identity Assertion JWT Authorization Grant) est basé sur plusieurs standards IETF :
- RFC 8693 : OAuth 2.0 Token Exchange
- RFC 7523 : JWT Profile for OAuth 2.0 Client Authentication
- IETF ID-JAG Draft : Spécification Identity Assertion JWT Authorization Grant (draft actif du groupe de travail IETF)
Pour un aperçu complet de Cross App Access et de son intégration dans l’écosystème OAuth, consultez la référence Cross App Access sur OAuth.net.
L’innovation clé est la séparation nette entre identité utilisateur (sub) et identité agent (client_id) en tant que claims distinctes et obligatoires dans le token ID-JAG. L’IdP signe une assertion qui dit “l’utilisateur X a autorisé l’agent Y à agir en son nom pour la ressource Z” — le tout dans un seul JWT vérifiable. En aval, le Resource AS peut émettre des access tokens avec la claim act (selon RFC 8693 §4.4) pour propager cette séparation aux resource servers, permettant une piste d’audit claire entre “pour qui est cette action” et “quel système exécute l’action.”
Structure du Token#
Le flux XAA produit deux tokens distincts. Comprendre la différence est important pour l’implémentation et l’audit.
Le Token ID-JAG (émis par l’IdP)#
L’ID-JAG est un JWT signé émis par l’IdP Authorization Server lors du token exchange (Étape 1). Il atteste l’identité de l’utilisateur et l’autorisation de l’agent à agir en son nom. L’en-tête JWT doit utiliser le type oauth-id-jag+jwt.
Header: { "typ": "oauth-id-jag+jwt", "alg": "RS256" }{
"iss": "https://acme.okta.com",
"sub": "john@example.com",
"aud": "https://crm.example.com/oauth2",
"client_id": "sales-representative-agent",
"jti": "9e43f81b64a33f20116179",
"exp": 1735571612,
"iat": 1735571312,
"resource": "https://crm.example.com/api",
"scope": "orders:read accounts:read",
"auth_time": 1735571200,
"amr": ["mfa", "pwd"]
}| Claim | Statut | Rôle |
|---|---|---|
iss | REQUIRED | Identifiant de l’IdP Authorization Server |
sub | REQUIRED | Identité utilisateur — même identifiant que le SSO |
aud | REQUIRED | Identifiant du Resource Authorization Server |
client_id | REQUIRED | Identité agent — le client OAuth enregistré auprès du Resource AS |
jti | REQUIRED | Identifiant unique du token (prévention du rejeu et corrélation d’audit) |
exp | REQUIRED | Temps d’expiration |
iat | REQUIRED | Temps d’émission |
resource | OPTIONAL | URI du Resource Server cible |
scope | OPTIONAL | Scopes demandés (peuvent être réduits par la politique de l’IdP) |
auth_time | OPTIONAL | Dernière authentification de l’utilisateur |
amr | OPTIONAL | Méthodes d’authentification utilisées (ex. mfa, pwd, hwk) |
L’ID-JAG ne contient pas de claim act. La séparation utilisateur/agent est exprimée via sub (utilisateur) et client_id (agent). La claim act n’apparaît que dans l’access token en aval.
L’Access Token (émis par le Resource AS)#
Le Resource AS valide l’ID-JAG (Étape 2) et émet un access token à portée limitée. Ce token propage la délégation via la claim act (RFC 8693 §4.4), rendant les deux identités visibles pour le resource server :
{
"sub": "john@example.com",
"act": {
"sub": "sales-representative-agent",
"aud": "okta.com"
},
"aud": "crm-orders-api",
"scope": "orders:read accounts:read",
"jti": "s2r3d4x3m6a0q1l",
"iat": 1735571312,
"nbf": 1735571312,
"exp": 1735571468
}| Claim | Rôle | Valeur Audit/Conformité |
|---|---|---|
sub | Identité utilisateur | Répond à : « Quel utilisateur a autorisé cette action ? » |
act.sub | Identité de l’agent | Répond à : « Quel agent a effectué cette action ? » |
aud | Ressource cible | Répond à : « Quel système a été accédé ? » |
scope | Permissions accordées | Répond à : « Quelles opérations ont été autorisées ? » |
jti | ID de transaction | Identifiant unique pour la corrélation entre systèmes |
exp | Expiration | Garantit un accès éphémère ; limite le rayon d’explosion |
Durée de Vie du Token#
La spécification ID-JAG exige les claims exp (expiration) et iat (émis le) dans chaque token, mais elle n’impose pas de durée spécifique. La valeur "expires_in": 300 (5 minutes) qui apparaît dans la spécification est marquée comme RECOMMENDED dans la réponse de token exchange — c’est un exemple, pas une exigence fixe.
En pratique, l’administrateur de l’IdP configure la durée de vie du token en fonction de la posture de sécurité du déploiement. Une durée plus courte (ex. 5 minutes) limite le rayon d’explosion en cas de compromission du token ; une durée plus longue réduit la fréquence des échanges de tokens pour les agents exécutant des workflows multi-étapes. La bonne valeur dépend de votre profil de risque, mais l’intention de conception est claire : les tokens ID-JAG doivent être de courte durée et réémis fréquemment, pas mis en cache pendant des heures.
Un agent exécuté pour un directeur commercial pourrait avoir accès à orders:read, orders:write et accounts:read. Mais lors du traitement d’une tâche spécifique (« lister mes affaires ouvertes »), la requête peut être réduite à orders:read uniquement. La permission effective est toujours l’intersection de ce que l’agent peut faire, de ce que l’utilisateur peut faire, et de ce que cette requête spécifique nécessite.
Bénéfices pour l’Audit et la Conformité#
Avec XAA, les journaux système d’Okta capturent un contexte riche pour chaque événement d’accès, incluant les identités utilisateur et agent, les portées demandées, la ressource cible et un ID de transaction unique pour la corrélation. L’EventType app.oauth2.token.grant.id_jag indique spécifiquement quand un échange ID-JAG a eu lieu, fournissant une piste d’audit claire pour les actions des agents.
Voici un exemple d’une entrée de journal d’événements XAA réelle provenant des journaux système d’Okta :
Entrée complète du journal système Okta pour un échange ID-JAG (cliquer pour développer)
{
"actor": {
"id": "wlpxnnu00000B6vxs1d7",
"type": "PublicClientApp",
"alternateId": "unknown",
"displayName": "Pricing Agent",
"detailEntry": null
},
"client": {
"userAgent": {
"rawUserAgent": "python-requests/2.33.1",
"os": "Unknown",
"browser": "UNKNOWN"
},
"zone": "null",
"device": "Unknown",
"id": null,
"ipAddress": "x.x.x.x",
"geographicalContext": {
"city": "Ashburn",
"state": "Virginia",
"country": "United States",
"postalCode": "20149",
"geolocation": {
"lat": 39.0469,
"lon": -77.4903
}
}
},
"displayMessage": "OAuth 2.0 Identity Assertion Authorization Grant is granted",
"eventType": "app.oauth2.token.grant.id_jag",
"outcome": {
"result": "SUCCESS",
"reason": null
},
"published": "2026-04-16T19:27:49.919Z",
"securityContext": {
"asNumber": 14618,
"asOrg": "amazon.com inc.",
"isp": "amazon.com inc.",
"domain": "amazonaws.com",
"isProxy": false,
"ipDetails": {
"asNumber": 14618,
"asOrg": "amazon.com inc.",
"isp": "amazon.com inc.",
"domain": "amazonaws.com"
}
},
"severity": "INFO",
"debugContext": {
"debugData": {
"clientAuthType": "private_key_jwt",
"grantedScopes": "pricing:margin",
"subjectTokenIssuer": "https://xxx.oktapreview.com",
"subjectTokenType": "urn:ietf:params:oauth:token-type:id_token",
"clientId": "wlpxnnu00000B6vxs1d7",
"responseTime": "213",
"requestedTokenType": "urn:ietf:params:oauth:token-type:id-jag",
"authorizationServerAudience": "https://xxx.oktapreview.com/oauth2/ausxnnacdm60nV7vv1d7",
"requestUri": "/oauth2/v1/token",
"requestedScopes": "pricing:margin",
"tokenExchangeType": "Agent ID Assertion",
"url": "/oauth2/v1/token?",
"managedConnectionId": "mcnxnodu9t2FRZO5R1d7",
"subjectTokenId": "ID.kiJ9Ch3aBer2ftX2CobkLuSSPqBMdMsZaxwRMZQjr44",
"subjectTokenClientId": "0oaxnnekviMmWpyBK2d3",
"requestId": "5eaf3d96ff3dbb684e1099bf8cecdd53",
"dtHash": "96dec87ffaebc55e64ab62eca30303c555d589e0f9686d55827963c51032ef7f",
"threatSuspected": "false",
"grantType": "urn:ietf:params:oauth:grant-type:token-exchange"
}
},
"legacyEventType": null,
"transaction": {
"type": "WEB",
"id": "5eaf3d96ff3dbb684e1099bf8cecdd53",
"detail": {}
},
"uuid": "5b10a39b-39ca-11f1-bbfb-f341db467931",
"version": "0",
"request": {
"ipChain": [
{
"ip": "x.x.x.x",
"geographicalContext": {
"city": "Ashburn",
"state": "Virginia",
"country": "United States",
"postalCode": "20149",
"geolocation": {
"lat": 39.0469,
"lon": -77.4903
}
},
"version": "V4",
"source": null,
"ipDetails": {
"asNumber": 14618,
"asOrg": "amazon.com inc.",
"isp": "amazon.com inc.",
"domain": "amazonaws.com"
}
}
]
},
"target": [
{
"id": "ID.kiJ9Ch3aBer2ftX2CobkLuSSPqBMdMsZaxwRMZQjr44",
"type": "id_token",
"alternateId": null,
"displayName": "ID Token",
"detailEntry": {
"audience": "0oaxnnekviMmWpyBK2d3",
"expires": "2026-04-16T20:07:29.000Z",
"subject": "00uxnn7b13YEcYj2V6a7",
"hash": "iMQM1uCzsH07nFhkRPUNvg"
}
},
{
"id": "00uxnn7b13YEcYj2V6a7",
"type": "User",
"alternateId": "fabio.grasso@example.com",
"displayName": "Fabio Grasso",
"detailEntry": null
},
{
"id": "IDAAG.5ZazR5P-fmm8zuG1CwuqT3EenUx1pFfN00jToEE0s6A",
"type": "id_jag",
"alternateId": null,
"displayName": "Identity Assertion JWT Authorization Grant",
"detailEntry": {
"audience": "https://xxx.oktapreview.com/oauth2/ausxnnacdm60nV7vv1d7",
"expires": "2026-04-16T19:32:49.000Z",
"subject": "00uxnn7b13YEcYj2V6a7",
"scope": "pricing:margin",
"hash": "Tq7wccRtqpRvZvEXKYK9nA"
}
}
]
}Comme vous pouvez le voir, non seulement l’agent ayant effectué la requête (Pricing Agent) mais aussi l’utilisateur ayant autorisé l’action (fabio.grasso@example.com) sont journalisés. Le champ grantedScopes indique les permissions effectives accordées à l’agent pour cette requête, soit l’intersection de ce que l’agent peut faire et de ce à quoi l’utilisateur a droit. La claim jti du token devient le transaction.id dans les journaux, vous permettant de corréler cet événement avec des événements en aval dans les journaux de votre ressource, si celle-ci journalise également l’ID de transaction.
Cas d’Usage XAA#
Voici quelques exemples concrets de l’utilisation de XAA pour sécuriser différents types de ressources :
- API interne via MCP Server — Un agent de support client doit accéder à la base de données interne des commandes pour répondre aux demandes clients.
- Agent enregistré dans l’Okta Universal Directory
- MCP Server protégé par un Okta Custom Authorization Server
- Flux XAA : l’agent échange l’ID Token de l’utilisateur contre un accès limité à
orders:read - Audit : chaque requête journalisée avec l’ID utilisateur, l’ID agent et l’ID de transaction
- SaaS First-Party (ISV-Enabled) — Un agent assistant commercial accédant aux opportunités Salesforce au nom d’un commercial.
- Salesforce implémente la validation ID-JAG
- L’agent présente l’ID-JAG au point de terminaison d’autorisation Salesforce
- Salesforce émet un token à portée limitée pour les données de l’utilisateur uniquement
- Pas d’identifiants statiques ; pas de comptes de service partagés
- Workflows d’agents multi-étapes — Un agent financier exécute un workflow d’approbation :
- Étape 1 : Lire la note de frais (portée
read:expenses) - Étape 2 : Vérifier la disponibilité budgétaire (portée
read:budgets) - Étape 3 : Soumettre l’approbation (portée
write:approvals) - Chaque étape peut demander des portées différentes. Si l’agent est compromis en cours de workflow, la révocation arrête uniquement la session de cet utilisateur sans affecter les autres.
- Étape 1 : Lire la note de frais (portée
XAA est entièrement fonctionnel aujourd’hui pour les Okta Custom Authorization Servers (type de connexion : “Authorization Server”) et les MCP Servers (type de connexion : “MCP Server”). L’adoption ISV pour les intégrations SaaS tierces est actuellement en cours. Les principaux fournisseurs travaillent activement sur le support ID-JAG.
Commencez à construire sur XAA maintenant pour être prêt à étendre aux intégrations SaaS dès que les ISVs auront complété leurs implémentations. En attendant, utilisez STS (type de connexion : “Application”) pour les SaaS tiers qui supportent OAuth mais pas encore ID-JAG.
Tester XAA : Le Playground xaa.dev#
Okta propose un environnement de test interactif sur xaa.dev où vous pouvez expérimenter les flux XAA sans infrastructure à configurer6.
Fonctionnalités :
- Tests dans le navigateur (pas de Docker ni de configuration locale)
- Composants préconfigurés : Requesting App, Resource App, IdP
- Démarrage en moins de 60 secondes
- Enregistrement de vos propres clients personnalisés pour les tests
Le playground inclut un exemple de flux où « Bob Tables » crée et gère des tâches via un agent IA, illustrant l’échange ID-JAG complet.
ID-JAG et XAA : Une Note sur la Terminologie#
Vous avez probablement croisé les deux termes — « ID-JAG » et « XAA » — utilisés de façon quasi interchangeable dans la documentation, les articles de blog et les conférences. Ils sont étroitement liés, mais pas identiques.
Imaginez que l’on appelle n’importe quel essuie-tout « Sopalin » quelle que soit la marque : le produit dominant finit par désigner toute la catégorie. C’est un peu ce qui se passe ici.
ID-JAG (Identity Assertion JWT Authorization Grant) est l’extension OAuth en cours de standardisation à l’IETF. Elle définit précisément comment les fournisseurs d’identité émettent des tokens d’assertion que les applications peuvent échanger contre des tokens d’accès. N’importe quel IdP peut implémenter ID-JAG — c’est un standard ouvert, et la spécification appartient à toute l’industrie.
XAA (Cross-App Access) est le nom commercial d’Okta pour leur implémentation d’ID-JAG. Okta a été un moteur clé à la fois de l’effort de standardisation IETF et de l’adoption précoce dans l’industrie — leur investissement en ingénierie et leur advocacy pour les développeurs ont fait de « XAA » le terme que beaucoup rencontrent en premier, et celui qui tend à s’imposer comme raccourci pour l’extension elle-même.
La distinction pratique compte : XAA est une implémentation d’un standard ouvert. Lorsque vous lisez la documentation Okta, « XAA » désigne spécifiquement le produit Okta. Lorsque vous lisez un draft IETF ou un guide d’intégration tiers, « ID-JAG » désigne la spécification sous-jacente que toute organisation peut implémenter.
Limitations de XAA#
Adoption ISV en cours : XAA est GA côté Okta, mais les intégrations SaaS tierces nécessitent le support des ISVs. Les principaux fournisseurs implémentent activement ID-JAG ; construire sur XAA maintenant garantit que vous serez prêt quand ils livreront.
Durée de vie du token vs. sessions longues : Les tokens sont intentionnellement de courte durée (la durée est configurable par l’administrateur de l’IdP, pas fixée par la spécification). Les agents exécutant des workflows multi-étapes doivent ré-échanger les tokens à expiration. C’est délibéré (limite le rayon d’explosion) mais nécessite que les agents gèrent le rafraîchissement des tokens de manière appropriée.
Non adapté pour : Les agents qui doivent fonctionner hors ligne ou mettre des identifiants en cache indéfiniment. Pour ces scénarios, envisagez STS avec une gestion attentive du cycle de vie des identifiants.
Secure Token Service (STS)#
Secure Token Service (STS) permet aux agents d’accéder aux applications SaaS tierces qui supportent OAuth mais n’ont pas encore adopté XAA. Okta agit comme un courtier sécurisé, stockant les tokens consentis par l’utilisateur dans Okta Privileged Access (OPA) et fournissant un accès fédéré à courte durée au moment de l’exécution.
Quand Utiliser STS#
- SaaS tiers avec support OAuth mais sans support ID-JAG (par exemple aujourd’hui : GitHub, Google Workspace, Slack)
- Le contexte au niveau utilisateur est requis pour l’audit et la conformité
Vérifiez régulièrement avec vos éditeurs SaaS leur roadmap pour le support ID-JAG. STS est un pont, pas une destination. L’objectif est de migrer vers XAA dès que l’éditeur le supporte.
Comment Fonctionne STS#
sequenceDiagram
autonumber
actor User
participant Client as 🤖 Client
(AI Agent)
box rgba(243, 242, 247,0.3) Okta Cloud
participant IdP as 🔐 IdP AS
(Okta Org AS)
participant Vault as 🔑 OPA
(Token Vault)
end
participant SaaS as 📱 Third-Party SaaS
Note over User, SaaS: Phase 1 — Consentement unique (initié par l'utilisateur)
Note over User, SaaS: Étape 1 : Authentification SSO
User->>Client: Login via SSO (OIDC)
Client->>IdP: OIDC authentication
IdP-->>Client: ID Token (sub: user@example.com)
Note over User, SaaS: Étape 2 : Consentement OAuth
Client->>IdP: Request managed connection token
IdP-->>Client: Consent URL (SaaS OAuth)
Client-->>User: Redirect to SaaS consent
User->>SaaS: Login and approve access
Note over User, SaaS: Étape 3 : Mise en Coffre-Fort des Tokens
SaaS-->>IdP: Authorization Code (callback)
IdP->>SaaS: Exchange code for tokens
SaaS-->>IdP: Access + Refresh Tokens
IdP->>Vault: Store tokens (bound to user context)
Note over Client, SaaS: Phase 2 — Accès runtime (agent autonome, RFC 8693)
Note over Client, SaaS: Étape 4 : Échange de Token (RFC 8693)
Client->>IdP: Token Exchange Request
Note right of Client: grant_type:token-exchange
subject_token: (vaulted user token)
actor: workload identity
audience: Third-Party SaaS
auth: private_key_jwt
IdP->>IdP: Validate managed connection policy
IdP->>Vault: Retrieve user-consented tokens
Vault-->>IdP: Access + Refresh Tokens
IdP->>SaaS: Refresh token if expired
SaaS-->>IdP: Fresh Access Token
IdP-->>Client: Short-lived federated token
Note left of IdP: scope: connection-scoped
token_type: Bearer
expires_in: short-lived
Note over Client, SaaS: Étape 5 : Appel API
Client->>SaaS: API call with token
SaaS-->>Client: Response
Décomposition étape par étape#
- Authentification utilisateur (SSO) : L’utilisateur se connecte via le Client en OIDC. Okta émet un ID Token contenant l’identité utilisateur (
sub: user@example.com). - Redirection vers le consentement : Le Client demande un token de managed connection. Okta renvoie une URL de consentement ; le Client redirige l’utilisateur vers l’écran de consentement OAuth standard du SaaS.
- Approbation utilisateur : L’utilisateur se connecte au SaaS tiers et approuve les scopes demandés. Le SaaS renvoie un code d’autorisation à l’endpoint callback d’Okta.
- Mise en coffre-fort des tokens : Okta échange le code d’autorisation contre des tokens d’accès et de rafraîchissement et les stocke dans Okta Privileged Access (OPA), liés au contexte d’identité de l’utilisateur.
- Accès runtime (agent autonome — aucune session utilisateur active requise) : L’agent s’authentifie auprès d’Okta avec son identité de workload (
private_key_jwt) et demande l’accès via la managed connection policy. - Récupération des tokens : Okta récupère les tokens stockés dans OPA, les rafraîchit auprès du SaaS si expirés, et émet un token fédéré à courte durée pour l’agent.
- Appel API : L’agent appelle le SaaS tiers avec le token à courte durée. Les identifiants utilisateur ne touchent jamais l’agent.
L’Utilisateur apparaît dans la Phase 1 car STS nécessite le consentement explicite de l’utilisateur — l’utilisateur doit s’authentifier auprès du SaaS tiers et approuver les scopes OAuth. Il s’agit d’une opération unique. Une fois le consentement accordé et les tokens mis en coffre-fort, la Phase 2 fonctionne de manière entièrement autonome : l’agent récupère et utilise les tokens sans aucune interaction utilisateur. L’utilisateur peut même ne pas être en ligne lorsque l’agent accède au SaaS.
Cas d’Usage STS#
- GitHub — Un agent assistant de développement lit des dépôts et crée des pull requests au nom des développeurs. Le développeur consent une fois via l’écran OAuth de GitHub ; Okta met en coffre-fort les tokens résultants. Au moment de l’exécution, l’agent reçoit un token fédéré à courte durée pour appeler l’API GitHub — il ne détient jamais d’identifiants GitHub à longue durée.
- Google Workspace — Un agent de planification gère des événements de calendrier et rédige des emails pour un utilisateur. Le contexte utilisateur est préservé grâce au flux de consentement, de sorte que les journaux d’audit de Google capturent quel utilisateur a autorisé les actions de l’agent.
- Jira/Confluence — Un agent de gestion de projet crée des tickets à partir de conversations Slack et met à jour des pages de documentation. L’agent s’authentifie via le token émis et géré par Okta, sans jamais stocker directement des identifiants Atlassian.
Différence Clé avec XAA#
- Flux de consentement : STS requiert que l’utilisateur passe par l’écran de consentement OAuth du tiers ; Okta stocke et gère ensuite ces tokens au nom de l’agent. XAA contourne entièrement l’écran de consentement. La délégation se fait au moment de l’enregistrement de l’agent dans Okta.
- Piste d’audit : STS capture le consentement utilisateur et l’accès agent dans les journaux Okta, mais le service tiers ne voit peut-être que l’identité de l’agent. XAA fournit le contexte utilisateur+agent complet à la ressource.
- Durée de vie du token : Le token fédéré émis à l’agent est à courte durée (minutes) pour limiter le risque, mais les tokens d’accès/rafraîchissement sous-jacents dans Okta peuvent avoir des durées de vie plus longues selon les politiques du service tiers.
- Révocation : Révoquer l’accès nécessite de supprimer l’entrée du coffre-fort dans Okta, ce qui peut affecter tous les agents utilisant cette connexion. Pas de révocation par utilisateur au sein du service tiers.
- Réduction de portée : L’agent reçoit les portées auxquelles l’utilisateur a consenti lors du flux OAuth. Okta ne peut pas réduire dynamiquement les portées par requête comme XAA.
Contrairement à Pre-Shared Key, STS préserve le contexte utilisateur grâce au flux de consentement. Les journaux d’audit capturent à la fois l’utilisateur qui a consenti et l’agent qui a accédé à la ressource.
STS est explicitement un pattern de transition. Dès qu’un ISV ou un éditeur SaaS livrera le support ID-JAG, vous pourrez mettre à niveau cette connexion de STS vers XAA sans réarchitecturer. En attendant, STS vous apporte le contexte au niveau utilisateur que Pre-Shared Key et Service Account ne peuvent tout simplement pas fournir.
Pre-Shared Key (PSK) ou Secret en Coffre-Fort#
Pre-Shared Key (PSK) stocke des identifiants statiques (clés API, tokens bearer, secrets webhook) dans Okta Privileged Access (OPA). L’agent récupère les secrets au moment de l’exécution plutôt que de les intégrer dans le code ou la configuration.
Quand Utiliser Pre-Shared Key#
- APIs REST legacy ne supportant que l’authentification par clé API
- Points de terminaison webhook nécessitant des tokens bearer
- Intégrations tierces avec authentification par token statique
- Services en phase initiale qui ajouteront éventuellement OAuth
Comment Fonctionne Pre-Shared Key#
sequenceDiagram
autonumber
actor Admin as Admin
participant Client as 🤖 Client
(AI Agent)
box rgba(243, 242, 247,0.3) Okta Cloud
participant IdP as 🔐 IdP AS
(Okta Org AS)
participant Vault as 🔑 OPA
(Secret Vault)
end
participant RS as 📦 Resource Server
(Protected API)
Note over Admin, Vault: Phase 1 — Configuration (initiée par l'admin)
Admin->>Vault: Create & vault secret (API key)
Admin->>IdP: Create managed connection on agent (type: Secret)
Note over Client, RS: Phase 2 — Accès runtime (agent autonome)
Client->>IdP: Authenticate (workload identity)
Note right of Client: private_key_jwt
managed connection policy
IdP->>IdP: Validate managed connection policy
IdP->>Vault: Retrieve vaulted secret
Vault-->>IdP: API key / bearer token
IdP-->>Client: Release secret
Client->>RS: API call with secret
RS-->>Client: Response
Décomposition étape par étape#
- L’administrateur met le secret en coffre-fort : Un administrateur stocke la clé API ou le token bearer dans Okta Privileged Access et crée une connexion gérée sur l’agent (type : Secret)
- L’agent s’authentifie : Au moment de l’exécution, l’agent s’authentifie à Okta avec son identité de principal de charge de travail
- Vérification de politique : Okta valide l’identité de l’agent et vérifie la politique de connexion gérée
- Secret libéré : Okta libère l’identifiant mis en coffre-fort à l’agent
- Accès direct à la ressource : L’agent utilise l’identifiant statique pour appeler la ressource en aval directement — sans échange de token, sans contexte utilisateur
Quand c’est possible (c’est-à-dire pour les services SaaS supportés), configurez le coffre-fort pour faire pivoter automatiquement les identifiants. Cela réduit le risque en cas de compromission d’un identifiant, mais nécessite que le service en aval supporte les mises à jour d’identifiants sans interruption de service.
Limitations de Pre-Shared Key#
- Pas de contexte utilisateur : La ressource ne voit que l’identité de l’agent, pas l’utilisateur
- Pas de réduction de portée : L’agent dispose de l’accès complet accordé à l’identifiant
- Piste d’audit limitée : Les journaux montrent l’accès de l’agent, sans attribution utilisateur
Pre-Shared Key a une piste d’audit limitée et aucun contexte utilisateur. Planifiez la migration vers XAA ou STS dès que les services en aval ajoutent le support OAuth. Ce pattern doit être traité comme temporaire pour les intégrations legacy.
Service Account#
Service Account utilise des identifiants nom d’utilisateur et mot de passe liés à une identité de service partagée. C’est le pattern legacy dont Okta recommande explicitement de migrer.
Comment Fonctionne Service Account#
sequenceDiagram
autonumber
actor Admin as Admin
participant ClientA as 🤖 Client A
(AI Agent)
participant ClientB as 🤖 Client B
(AI Agent)
box rgba(243, 242, 247,0.3) Okta Cloud
participant IdP as 🔐 IdP AS
(Okta Org AS)
participant Vault as 🔑 OPA
(Credential Vault)
end
participant RS as 📦 Resource Server
(Protected API)
Note over Admin, RS: Phase 1 — Configuration (admin-initiated)
Admin->>Vault: Create service account (svc_agent@example)
Admin->>ClientA: Register with managed connection
Admin->>ClientB: Register with managed connection
Note over ClientA, RS: Phase 2 — Runtime Access (agent-autonomous)
ClientA->>IdP: Request credentials
ClientB->>IdP: Request credentials
Note right of ClientA: private_key_jwt
managed connection
IdP->>Vault: Retrieve vaulted credentials
Vault-->>IdP: Username/Password (svc_agent@example)
IdP-->>ClientA: Username/Password
IdP-->>ClientB: Username/Password
ClientA->>RS: Authenticate as svc_agent@example
ClientB->>RS: Authenticate as svc_agent@example
Note over RS: Les deux apparaissent avec la même identité !
Décomposition étape par étape#
- L’administrateur provisionne le compte de service : Un administrateur crée un compte de service dans OPA (Credential Vault) et enregistre les connexions gérées sur un ou plusieurs agents
- Les agents demandent des identifiants : Au moment de l’exécution, chaque agent s’authentifie auprès de l’IdP AS avec son identité de workload (
private_key_jwt) et demande les identifiants du compte de service via la connexion gérée - Okta libère le nom d’utilisateur/mot de passe : L’IdP AS récupère les identifiants stockés dans OPA, valide l’identité de l’agent, vérifie la politique et transmet les identifiants partagés
- L’agent s’authentifie à la ressource : L’agent se connecte au Resource Server en tant que compte de service — indiscernable de tout autre agent utilisant les mêmes identifiants
Limitations des Service Accounts#
Les Service Accounts présentent quatre lacunes de sécurité critiques :
- Agents invisibles : Plusieurs agents partagent une identité unique, rendant impossible de savoir lequel a effectué une action
- Permissions excessives : Les comptes de service portent généralement des privilèges larges et statiques qui dépassent largement ce qu’une tâche unique nécessite
- Attribution utilisateur manquante : Les audits de conformité ne peuvent pas répondre à « quel utilisateur a déclenché cet accès aux données ? »
- Révocation tout ou rien : Désactiver le compte de service coupe l’accès à tous les agents et systèmes qui en dépendent
Les Service Accounts ne sont pas aussi sécurisés que les types de ressources authorization server ou vaulted secret. Les nouvelles intégrations ne devraient jamais adopter ce pattern par défaut.
Quand Service Account est Inévitable#
- Systèmes legacy nécessitant une authentification nom d’utilisateur/mot de passe (bases de données on-prem, mainframes, services LDAP)
- Traitements par lots sans contexte utilisateur final
- Systèmes n’ayant pas adopté de méthode d’authentification moderne
Service Account n’est acceptable que pour les processus batch sans contexte utilisateur, avec un plan de fin de vie documenté.
Les deux patterns manquent de contexte utilisateur et de réduction de portée, mais diffèrent dans le type d’identifiant stocké et la posture de sécurité :
PSK met en coffre-fort un identifiant natif machine (clé API) qui est généralement unique par intégration, de sorte que la rotation et la révocation restent chirurgicales. Les identifiants sont limités à une intégration, vous pouvez donc avoir plusieurs PSKs pour différents agents, garantissant au moins une attribution au niveau de l’agent (audit) et une isolation (pour la révocation). Okta Privileged Access peut faire pivoter automatiquement les PSKs si le service en aval le supporte, ce qui est un gain de sécurité considérable.
Service Account emprunte un identifiant à forme humaine (nom d’utilisateur/mot de passe) pour usurper une identité partagée : plusieurs agents partagent la même connexion, ce qui est précisément ce qui brise l’attribution par agent et impose une révocation tout ou rien. Les mots de passe ont généralement une longue durée de vie et nécessitent une rotation manuelle, ce qui constitue un risque en cas de compromission. Les comptes de service sont souvent sur-provisionnés avec des permissions larges pour éviter de casser les agents dépendants, ce qui amplifie davantage le risque.
C’est pourquoi passer de Service Account à PSK est la première étape défendable sur l’échelle de migration, même si aucun des deux patterns ne porte de contexte utilisateur.
Recommandations Stratégiques#
De la Théorie à la Pratique : Configurer les Patterns d’Accès dans Okta#
Dans l’Okta Universal Directory, vous pouvez enregistrer des agents IA comme identités de charge de travail et créer des Managed Connections qui définissent comment ils accèdent aux ressources en aval. Chaque type de connexion correspond à l’un des patterns d’accès abordés ci-dessus.
| Liste des Agents IA | Détail d’un Agent IA |
|---|---|
![]() | ![]() |
Quand vous créez une connexion gérée, vous verrez cinq types de ressources. Ils correspondent aux quatre patterns d’accès couverts dans cet article :

| Type de Connexion | Pattern d’Accès | Ce qu’il Fait |
|---|---|---|
| Authorization Server | XAA (Cross App Access) | L’agent obtient des tokens à portée limitée depuis un Okta Custom Authorization Server via l’échange ID-JAG |
| Secret | Pre-Shared Key (PSK) | L’agent récupère une clé API ou un token bearer mis en coffre-fort depuis Okta Privileged Access |
| Service Account | Service Account | L’agent récupère les identifiants nom d’utilisateur/mot de passe d’une identité de service mise en coffre-fort dans Okta Privileged Access |
| Application | STS (Secure Token Service) | L’agent accède à une app OIN ou un serveur de ressources personnalisé via un échange de tokens OAuth émis et gérés par Okta |
| MCP Server | XAA (Cross App Access) | Même échange ID-JAG que Authorization Server, spécialisé pour la surface protocole MCP |
Le type de connexion MCP Server n’est pas un pattern d’accès séparé : c’est XAA appliqué spécifiquement aux serveurs Model Context Protocol. Le même modèle de délégation ID-JAG, la même structure de token (sub + act.sub), et le même renforcement des politiques s’appliquent. Okta fournit un type de connexion dédié pour simplifier la configuration spécifique à MCP.
Aperçu de la Configuration XAA#
Implémenter XAA nécessite :
- Enregistrer l’agent dans l’Okta Universal Directory comme principal de charge de travail
- Créer une Managed Connection et sélectionner “Authorization Server” (pour les APIs personnalisées) ou “MCP Server” (pour les points de terminaison MCP). Les deux utilisent le même échange ID-JAG en interne.
- Configurer le Custom Authorization Server protégeant votre ressource
- Définir des politiques RBAC qui évaluent à la fois les attributs utilisateur et agent
Exemple de logique de politique, pour s’assurer que l’agent ne peut accéder aux données de vente que quand l’utilisateur est membre de l’équipe commerciale :
IF (act.sub == "sales-representative-agent")
AND (sub IN groups["sales-team"])
AND (requested_scope IN ["sales:read", "accounts:read"])
THEN issue_token_with_scope
ELSE denyIl s’agit d’un exemple en pseudo-code. Dans la console d’administration Okta, les politiques d’accès du Custom Authorization Server utilisent un modèle politique + règle — pas un langage de script. Pour suivre l’exemple, vous pouvez :
- Créer une Politique d’Accès assignée à l’agent IA (c’est-à-dire
sales-representative-agent). Cela limite implicitement la politique à cet agent spécifique (act.sub). - Créer une Règle dans cette politique :
- Type de grant :
JWT Bearer(le grant d’échange ID-JAG) - Éligibilité utilisateur : Utilisateurs membres du groupe :
sales-team— cela garantit que seuls les membres de l’équipe commerciale peuvent déléguer l’accès via cet agent - Portées : Liste blanche de
orders:readetaccounts:read— l’agent ne peut pas demander des portées plus larges même si l’utilisateur en dispose - Durée de vie du token : 5 minutes (éphémère)
- Évaluation : Les politiques et règles sont évaluées par ordre de priorité. La première correspondance gagne. Si aucune règle ne correspond (par exemple, un utilisateur hors
sales-teamtente d’utiliser cet agent), la requête est refusée.
- Type de grant :
Le résultat : l’agent ne peut accéder aux données de vente que quand l’utilisateur derrière la requête est membre de l’équipe commerciale. Les permissions effectives sont l’intersection de la liste blanche de portées de la politique, de l’appartenance au groupe de l’utilisateur, et de la connexion gérée de l’agent.
Configuration STS#
Dans la console d’administration Okta, vous configurez STS en créant une connexion gérée avec le type de ressource “Application”, en sélectionnant une intégration OIN app ou un serveur de ressources personnalisé7. Okta fait alors office de courtier pour l’échange de tokens OAuth entre l’agent et le service tiers.
Configuration PSK#
Dans la console d’administration Okta, vous configurez PSK en créant une connexion gérée avec le type de ressource “Secret”. La clé API ou le token bearer doit d’abord être stocké dans Okta Privileged Access ; la connexion gérée fait ensuite référence à ce secret mis en coffre-fort. Au moment de l’exécution, l’agent récupère l’identifiant à la demande — il n’est jamais codé en dur dans le code ou la configuration de l’agent.
Configuration Service Account#
Dans la console d’administration Okta, vous configurez une connexion Service Account en créant une connexion gérée avec le type de ressource “Service Account”, en la liant à une identité de service stockée dans Okta Privileged Access. Comme plusieurs agents peuvent référencer le même compte de service, traitez-le comme un dernier recours et documentez un plan de fin de vie avant de le déployer.
Conclusions#
Et Maintenant ?#
Vous disposez maintenant du toolkit au niveau protocole pour chaque pattern d’Okta for AI Agents. Deux étapes naturelles :
- Retour à la vue stratégique : relisez la Partie 2 — Patterns d’Accès avec les détails d’implémentation frais à l’esprit. Le cadre de décision et l’échelle de migration prennent beaucoup plus de sens une fois que vous avez vu les claims des tokens et les diagrammes de séquence.
- En avant vers la conformité : dans la Partie 4 — Conformité EU AI Act je mappe chaque pattern aux exigences réglementaires (EU AI Act, NIST AI RMF, NIS2, DORA), en montrant comment les champs d’audit que vous venez d’apprendre à lire se traduisent directement en preuves de conformité.
Essayer en Live#
Explorez le playground XAA interactif sur xaa.dev — sans configuration requise. Créez des agents, effectuez des échanges ID-JAG et inspectez les tokens résultants directement dans votre navigateur.
Ressources de Référence#
- Cross App Access Documentation — Guide de configuration officiel Okta
- XAA.dev Documentation — Documentation du playground interactif
- Cross App Access Introduction — Introduction technique
- XAA Developer Playground — Tutoriel pratique
- Building Resource Apps — Guide d’implémentation
- AI Agent Token Exchange Guide — Guide pas à pas pour développeurs
- Secure AI agent access to resources — Okta Help Center
Rejoignez la Discussion#
Quel pattern implémentez-vous en premier ? Rencontrez-vous des blocages sur l’échange ID-JAG ou les policies des managed connections ? Laissez un mot dans les commentaires ci-dessous ou contactez-moi sur LinkedIn.
Identity JWT Authorization Grant, IETF OAuth Working Group, 2025 ↩︎
NIST SP 800-63-4: Digital Identity Guidelines, NIST, 2024 ↩︎
EU Artificial Intelligence Act, European Union, 2024 ↩︎
NIS2 Directive, European Commission, 2024 ↩︎
DORA: Digital Operational Resilience Act, European Commission, 2024 ↩︎
XAA Developer Playground, Okta Developer Blog, January 2026 ↩︎
Secure AI agent access to resources, Okta Help Center ↩︎


