SAML, OAuth 2.0, OpenID Connect : ce que chaque protocole prouve, et ce qu'il ne décide pas


À retenir

  • SAML 2.0, OAuth 2.0 et OpenID Connect ne répondent pas à la même question. SAML et OpenID Connect transportent la preuve d’une authentification et des attributs ; OAuth 2.0 transporte une autorisation déléguée à une application.
  • OAuth 2.0 n’est pas un protocole d’authentification. L’utiliser comme tel est l’une des confusions les plus fréquentes et les plus coûteuses en sécurité.
  • Aucun des trois ne décide d’un droit métier. Ils transportent, au mieux, une copie d’un droit décidé ailleurs. La question de gouvernance est donc : où ce droit est-il décidé, et où est-il revu ?
  • Le paysage a bougé depuis 2012 : la RFC 9700 (janvier 2025) proscrit ou déconseille plusieurs usages d’OAuth 2.0 encore présents dans les applications. OAuth 2.1 reste un projet de l’IETF au 3 octobre 2026.
  • Le choix d’un protocole se fait par application, à partir de ce dont elle a besoin (authentifier un utilisateur, appeler une API pour lui, les deux), pas à partir de l’ancienneté du standard.

Introduction

Les comparatifs entre SAML, OAuth et OpenID Connect se ressemblent presque tous : SAML serait l’ancien protocole XML des entreprises, OpenID Connect son successeur moderne en JSON, et OAuth la brique d’autorisation de l’ensemble. Ce résumé n’est pas faux, mais il fait passer à côté de l’essentiel. Il compare les protocoles par leur format et leur âge, alors que la question utile est ailleurs : qu’est-ce que chaque message prouve, à qui, et qu’est-ce qu’il ne décide pas ?

Pour un projet IAM, cette question a des conséquences très concrètes. Elle détermine si une application sait réellement qui est connecté, si les droits transmis dans un jeton sont gouvernés quelque part, et ce qui se passe quand un collaborateur quitte l’organisation alors que ses sessions sont encore ouvertes. Cet article reprend les trois protocoles sous cet angle, en s’appuyant sur leurs spécifications, et s’adresse aux architectes, chefs de projet IAM et responsables applicatifs qui doivent choisir ou auditer une intégration.

Les trois en une phrase

  • SAML 2.0 (Security Assertion Markup Language) : un fournisseur d’identité émet, à destination d’une application précise, une assertion XML signée qui atteste qu’un utilisateur s’est authentifié et qui porte des attributs le concernant.
  • OAuth 2.0 : un serveur d’autorisation délivre à une application cliente un jeton d’accès qui lui permet d’appeler une ressource, pour le compte d’un utilisateur ou pour elle-même, dans des limites données.
  • OpenID Connect : une couche d’identité ajoutée à OAuth 2.0, qui délivre à l’application un jeton d’identité (ID Token) attestant l’authentification de l’utilisateur.

SAML 2.0 : une assertion adressée à une application

SAML 2.0 est un standard OASIS approuvé en mars 2005. Son cas d’usage dominant est l’authentification unique (SSO) dans un navigateur : l’utilisateur veut accéder à une application (le fournisseur de service), celle-ci le renvoie vers le fournisseur d’identité, qui l’authentifie puis renvoie au fournisseur de service une assertion signée.

Cette assertion contient en général deux choses distinctes, qu’il est utile de séparer mentalement. La première est une déclaration d’authentification : tel utilisateur s’est authentifié, à tel moment, selon tel contexte. La seconde est une déclaration d’attributs : son identifiant, son adresse électronique, son service, et souvent ses groupes ou ses rôles. L’application s’appuie sur la première pour ouvrir une session, et sur la seconde pour personnaliser l’accès, parfois pour décider de ce que l’utilisateur peut faire.

La force de SAML est sa maturité : relations de confiance établies par échange de métadonnées, signature des assertions, support très large dans les applications d’entreprise et les services en ligne. Sa limite tient à son périmètre : SAML a été conçu pour faire entrer un utilisateur dans une application web, pas pour permettre à cette application d’appeler une API en son nom, ni pour les applications mobiles natives.

En pratique, un flux SAML Web Browser SSO (profil POST, initié par le fournisseur de service) se déroule ainsi :

sequenceDiagram
    autonumber
    actor User as Utilisateur
    participant Browser as Navigateur
    participant SP as Fournisseur de service<br/>(application)
    participant IdP as Fournisseur d'identité
    User->>Browser: Accède à l'application
    Browser->>SP: GET /ressource-protegee
    SP-->>Browser: 302 vers IdP + SAML AuthnRequest
    Browser->>IdP: AuthnRequest
    IdP->>User: Formulaire d'authentification
    User->>IdP: Credentials + MFA
    IdP-->>Browser: Form POST avec SAML Response signée
    Browser->>SP: POST /acs (SAML Response)
    SP->>SP: Vérifie signature, audience, conditions
    SP-->>Browser: 302 vers la ressource + cookie de session
    Browser->>SP: GET /ressource-protegee (avec cookie)
    SP-->>User: Contenu

Le point à retenir : l’assertion est adressée au fournisseur de service (champ AudienceRestriction), signée par le fournisseur d’identité, et transportée via le navigateur. Elle n’autorise pas à appeler une API — elle ouvre une session.

OAuth 2.0 : une délégation, pas une identité

La RFC 6749, publiée en octobre 2012, définit OAuth 2.0 comme un cadre d’autorisation qui permet à une application tierce d’obtenir un accès limité à un service HTTP, soit pour le compte d’un propriétaire de ressource, soit pour son propre compte. Le mot important est « délégation » : l’utilisateur, ou une politique, autorise une application à agir dans certaines limites.

Le jeton d’accès que reçoit l’application est, selon la RFC, une chaîne qui représente une autorisation délivrée au client, souvent opaque pour ce dernier. Il est destiné à la ressource, pas à l’application qui le porte. Une application qui reçoit un jeton d’accès sait qu’elle peut appeler une API ; elle ne dispose pas, par ce seul jeton, d’une preuve normalisée de l’identité de la personne qui l’utilise.

C’est là que naît la confusion la plus répandue : se servir d’OAuth 2.0 pour « connecter un utilisateur ». Le schéma est tentant (l’utilisateur s’est bien authentifié auprès du serveur d’autorisation pour délivrer le jeton) mais il est fragile. Rien, dans OAuth 2.0 seul, ne garantit à l’application que le jeton qu’on lui présente a été émis pour elle et non pour une autre application. Un jeton obtenu légitimement par une application tierce peut alors servir à ouvrir une session dans la vôtre. C’est précisément ce manque qu’OpenID Connect comble.

Le cas d’usage d’OAuth 2.0 sans utilisateur mérite aussi d’être nommé : une application qui appelle une API pour son propre compte, par exemple un traitement planifié. Il s’agit alors d’une identité non humaine, avec ses propres enjeux de responsabilité et de durée de vie, traités dans l’article sur les identités non humaines et les agents IA.

Voici le flux Authorization Code avec PKCE, aujourd’hui recommandé pour toutes les applications publiques (SPA, mobile) et de plus en plus pour les applications confidentielles :

sequenceDiagram
    autonumber
    actor User as Utilisateur
    participant Client as Application cliente
    participant AS as Serveur d'autorisation
    participant RS as API (serveur de ressources)
    Client->>Client: Génère code_verifier + code_challenge (SHA-256)
    Client->>User: Redirige vers AS avec code_challenge
    User->>AS: Authentification + consentement
    AS-->>Client: Redirige avec authorization_code (usage unique)
    Client->>AS: POST /token (code + code_verifier)
    AS->>AS: Vérifie que SHA-256(verifier) == challenge
    AS-->>Client: access_token (+ refresh_token)
    Client->>RS: GET /api/ressource (Authorization: Bearer <token>)
    RS->>RS: Valide le jeton (introspection ou JWT)
    RS-->>Client: Ressource

Le jeton d’accès est destiné à l’API, pas à l’application qui le porte. L’application sait qu’elle peut appeler une API ; elle ne tient pas, de ce seul jeton, une preuve d’identité de l’utilisateur.

OpenID Connect : une couche d’identité au-dessus d’OAuth 2.0

La spécification OpenID Connect Core 1.0 se présente comme une couche d’identité simple au-dessus d’OAuth 2.0, qui permet à une application de vérifier l’identité de l’utilisateur à partir de l’authentification réalisée par le serveur d’autorisation. Elle a été publiée par la Fondation OpenID, puis reprise à l’ISO sous la référence ISO/IEC 26131:2024 (octobre 2024), dans sa version intégrant le second jeu d’errata.

L’apport central est l’ID Token : un jeton JSON signé, destiné à l’application elle-même. Il porte obligatoirement l’émetteur (iss), l’identifiant stable de l’utilisateur chez cet émetteur (sub), le ou les destinataires (aud, qui doit contenir l’identifiant de l’application), la date d’expiration (exp) et la date d’émission (iat). Le champ aud règle exactement le problème décrit plus haut : une application qui vérifie qu’elle figure dans l’audience du jeton refuse un jeton émis pour une autre.

Deux champs optionnels intéressent directement la sécurité : acr, qui désigne le contexte d’authentification atteint, et amr, qui liste les méthodes utilisées. Ce sont eux qui permettent à une application d’exiger, pour une opération sensible, un niveau d’authentification supérieur à celui de la session courante. Encore faut-il que l’application les lise ; en pratique, beaucoup se contentent de la présence d’un jeton valide.

OpenID Connect hérite enfin de tout OAuth 2.0 : la même application peut recevoir un ID Token pour savoir qui est connecté et un jeton d’accès pour appeler une API au nom de cet utilisateur. C’est cette double capacité, et non une supériorité de principe, qui le rend naturel pour les applications mobiles et les architectures fondées sur des API.

Le même flux Authorization Code, complété par le scope: openid et un ID Token, devient un flux OpenID Connect :

sequenceDiagram
    autonumber
    actor User as Utilisateur
    participant Client as Application
    participant OP as OpenID Provider<br/>(= AS + IdP)
    participant API as API
    Client->>User: Redirige vers OP (scope=openid profile + nonce)
    User->>OP: Authentification + consentement
    OP-->>Client: Redirige avec authorization_code
    Client->>OP: POST /token
    OP-->>Client: id_token (JWT signé) + access_token
    Client->>Client: Valide iss, aud, exp, nonce, signature
    Client->>Client: Ouvre la session (sub, acr, amr)
    Client->>API: Appel avec access_token
    API-->>Client: Ressource

Deux jetons, deux usages. L’ID Token prouve à l’application qui est connecté (vérification de aud : refuser un jeton émis pour une autre application). L’access_token lui permet d’appeler l’API au nom de cet utilisateur. C’est cette double capacité qui rend OIDC naturel pour les SPA et les applications mobiles.

Comparatif synthétique

CritèreSAML 2.0OAuth 2.0OpenID Connect
Question traitéeQui s’est authentifié, avec quels attributs ?Que peut faire cette application, pour qui ?Qui s’est authentifié, avec quels attributs ? (plus la délégation OAuth)
RéférenceOASIS, mars 2005RFC 6749 (octobre 2012), mise à jour par la RFC 9700 (janvier 2025)OpenID Connect Core 1.0 ; ISO/IEC 26131:2024
Objet émisAssertion XML signéeJeton d’accès (format non imposé)ID Token (JWT signé) et jeton d’accès
Destinataire de l’objetL’application (fournisseur de service)La ressource (API)L’application (ID Token) ; la ressource (jeton d’accès)
Preuve d’authentificationOuiNonOui
Appel d’API au nom de l’utilisateurNon prévuOuiOui
Usage dominantSSO web d’entrepriseDélégation d’accès aux APISSO web et mobile, applications appelant des API
Décide d’un droit métierNonNonNon

La dernière ligne est volontairement identique pour les trois colonnes. C’est le sujet de la section suivante.

Ce que le jeton ne décide pas : le droit

Un jeton ou une assertion transporte des informations sur un utilisateur. Il ne décide pas de ce que cet utilisateur a le droit de faire dans l’application. Quand un fournisseur d’identité ajoute dans un jeton la liste des groupes de l’utilisateur, il recopie l’état d’un annuaire à un instant donné. La décision d’accorder ces groupes a été prise ailleurs, ou n’a été prise par personne.

Les spécifications le reconnaissent. La RFC 9068 (octobre 2021), qui définit un format de jeton d’accès au format JWT, constate que de nombreux systèmes y placent des informations d’autorisation qui dépassent la délégation OAuth : appartenance à des rôles et à des groupes, droits attribués à l’utilisateur. Elle recommande dans ce cas de reprendre les attributs groups, roles et entitlements du schéma SCIM (RFC 7643). Autrement dit, le jeton devient un canal de transport des habilitations. La norme ne dit rien, et n’a pas à dire, sur la manière dont ces habilitations sont décidées, approuvées et revues.

Dans ma pratique, c’est ici que se loge l’angle mort le plus fréquent entre Access Management et gouvernance. Lors de l’intégration d’une application au SSO, l’équipe projet a besoin que l’utilisateur arrive avec un rôle applicatif. Le chemin le plus court consiste à créer un groupe dans l’annuaire, à l’envoyer dans l’assertion ou le jeton, et à laisser l’application en déduire les droits. Le droit existe désormais en trois endroits : un groupe d’annuaire, une règle de correspondance dans la configuration de la fédération, et un comportement dans l’application. Aucun des trois n’est, en général, rattaché à un propriétaire métier ni inclus dans les campagnes de revue. L’outil de gouvernance voit un groupe technique ; il ne sait pas que ce groupe ouvre un droit d’administration dans une application SaaS. Le résultat est une habilitation parallèle, parfaitement fonctionnelle et invisible. La question à poser à chaque intégration n’est pas « quel protocole ? » mais « quel attribut porte un droit, et qui le revoit ? ».

La conséquence pratique est simple à formuler. Chaque attribut transmis par une fédération qui conditionne un droit dans l’application doit être traité comme une habilitation à part entière : rattaché à un propriétaire, documenté dans le modèle d’autorisation, et inclus dans les revues d’habilitations. C’est une bonne pratique, pas une exigence des protocoles, mais c’est la seule manière de ne pas créer à chaque intégration un circuit d’attribution des droits hors de la gouvernance des identités.

Le scope n’est pas une habilitation

Le même glissement se produit avec les scopes OAuth. Un scope délimite ce qu’une application cliente est autorisée à demander pour le compte d’un utilisateur : lire son agenda, consulter ses factures. La RFC 6749 précise d’ailleurs que le serveur d’autorisation peut ignorer tout ou partie du scope demandé, selon sa politique ou les instructions de l’utilisateur. Le scope est la mesure de la délégation, pas celle du droit.

Ce que l’on observe en projet, c’est une API qui vérifie la présence du scope factures:lecture dans le jeton et s’arrête là. Elle répond alors à la question « cette application a-t-elle le droit de demander des factures ? » et jamais à « cet utilisateur a-t-il le droit de voir ces factures-là ? ». Tant que le scope n’est délivré qu’à des utilisateurs qui ont le droit, le défaut ne se voit pas. Il apparaît le jour où une nouvelle application cliente obtient le même scope pour une population plus large, ou le jour où l’on délègue ce scope à un agent. Contrairement à une idée répandue, enrichir les scopes jusqu’à ce qu’ils ressemblent à des droits métier ne règle pas le problème : on finit avec des centaines de scopes, qui reproduisent l’explosion des rôles dans un endroit où personne ne les gouverne. Le scope borne l’application ; le droit de l’utilisateur doit être vérifié par la ressource, à partir d’une source gouvernée.

Les textes vont dans ce sens. La RFC 9068 indique que, lorsque le jeton porte des informations d’autorisation, le serveur de ressources devrait les utiliser en combinaison avec toute autre information contextuelle disponible pour décider d’accepter ou de rejeter l’appel. Pour les cas où la délégation elle-même doit être fine (un virement d’un montant donné vers un bénéficiaire donné), la RFC 9396 (mai 2023, Rich Authorization Requests) ajoute un paramètre structuré, authorization_details, qui dépasse la granularité des scopes. Elle affine ce que l’application est autorisée à demander ; elle ne remplace pas la vérification du droit de l’utilisateur.

Ce qui a changé depuis 2012

OAuth 2.0 a été publié en 2012, à une époque où les applications à page unique et les applications mobiles étaient moins répandues et où plusieurs attaques n’étaient pas documentées. La RFC 9700, publiée en janvier 2025 comme Best Current Practice (BCP 240), met à jour la RFC 6749 et en tire les conséquences. Quatre points concernent directement les applications existantes :

  • Le flux implicite (jeton d’accès renvoyé directement dans la réponse d’autorisation) : les clients ne devraient pas l’utiliser, sauf à empêcher l’injection de jetons dans cette réponse. C’est un « SHOULD NOT » au sens de l’IETF, pas une interdiction absolue, mais l’intention est claire.
  • Le flux par mot de passe du propriétaire (l’application recueille directement l’identifiant et le mot de passe de l’utilisateur) : il ne doit pas être utilisé. C’est cette fois un « MUST NOT ».
  • PKCE (RFC 7636), mécanisme qui lie la demande d’autorisation à l’échange du code : les clients publics doivent l’utiliser, et les serveurs d’autorisation doivent le prendre en charge.
  • Les jetons liés à leur émetteur (sender-constrained), par TLS mutuel (RFC 8705) ou par DPoP (RFC 9449) : ils sont recommandés, pour qu’un jeton volé ne puisse pas être rejoué par un tiers.

OAuth 2.1, souvent cité comme s’il était acquis, consolide ces pratiques dans un texte unique. Au 3 octobre 2026, c’est un Internet-Draft de l’IETF (version -16, datée du 3 septembre 2026), pas une RFC ; le jalon du groupe de travail prévoit sa transmission à l’IESG en décembre 2026. Pour un audit ou un cahier des charges, la référence opposable aujourd’hui est donc la RFC 9700, et non OAuth 2.1.

Dans un projet, ces évolutions se traduisent par un inventaire très concret : quelles applications utilisent encore le flux implicite ou le flux par mot de passe, quels clients publics n’utilisent pas PKCE. Ce sont des questions qu’un auditeur peut poser, et dont la réponse se trouve dans la configuration du serveur d’autorisation.

Ce que l’auditeur et le praticien regardent

Au-delà du choix du protocole, trois sujets reviennent quand on examine une architecture de fédération avec un œil de gouvernance.

L’inventaire des relations de confiance. Chaque application intégrée au SSO est une relation de confiance : des métadonnées SAML ou un client OpenID Connect enregistré, avec des attributs libérés et des règles de correspondance. Une organisation devrait pouvoir dire, pour chaque relation, qui en est responsable, quels attributs elle reçoit et lesquels conditionnent un droit. En pratique, cet inventaire est rarement tenu à jour au-delà de la console du fournisseur d’identité.

Le départ et la durée des sessions. Désactiver un compte dans l’annuaire n’invalide pas automatiquement ce qui a déjà été émis. Une session ouverte dans une application à partir d’une assertion SAML vit selon les règles de cette application. Un jeton de rafraîchissement OAuth reste utilisable jusqu’à son expiration ou sa révocation (RFC 7009), selon la configuration du serveur d’autorisation. Le traitement du départ, décrit dans l’article sur le cycle de vie des identités, doit donc couvrir aussi la révocation des sessions et des jetons, et pas seulement la désactivation du compte. Une bonne pratique consiste à aligner la durée de vie des jetons de rafraîchissement sur le délai de retrait des accès que l’organisation s’est fixé.

La création de comptes à la volée. Beaucoup d’applications créent un compte local à la première connexion fédérée, à partir des attributs reçus. C’est pratique, mais ce compte échappe ensuite au provisioning et au déprovisioning : il ne disparaît pas quand l’utilisateur part, il ne fait que cesser d’être utilisé. Pour les applications qui conservent des données ou des droits locaux, un provisioning explicite (par SCIM ou par connecteur) reste nécessaire, en plus de la fédération.

Comment choisir

Le bon point de départ est le besoin de l’application, pas le protocole :

  • L’application doit seulement savoir qui est connecté, dans un navigateur, et la prend déjà en charge en SAML : SAML 2.0 convient. Une migration vers OpenID Connect n’apporte rien par elle-même.
  • L’application doit appeler des API au nom de l’utilisateur, ou c’est une application mobile ou à page unique : OpenID Connect, qui combine preuve d’identité et délégation OAuth, est le choix cohérent.
  • Un service appelle une API pour son propre compte, sans utilisateur : OAuth 2.0 avec authentification du client, en traitant ce client comme une identité non humaine gouvernée.
  • Dans tous les cas, le choix du protocole ne dispense pas de décider où les droits sont attribués et revus. C’est la question qu’un projet IAM doit trancher à chaque intégration.

FAQ

OAuth 2.0 est-il un protocole d’authentification ? Non. OAuth 2.0 (RFC 6749) est un cadre d’autorisation déléguée : il permet à une application d’obtenir un accès limité à une ressource, pour le compte d’un utilisateur ou pour elle-même. Il ne fournit pas à l’application une preuve normalisée de l’identité de l’utilisateur. C’est OpenID Connect, construit au-dessus d’OAuth 2.0, qui ajoute cette preuve sous la forme d’un jeton d’identité (ID Token).

Quelle différence entre SAML et OpenID Connect ? Les deux permettent à une application de recevoir d’un fournisseur d’identité la preuve qu’un utilisateur s’est authentifié, avec des attributs le concernant. SAML 2.0 (OASIS, 2005) utilise des assertions XML et vise principalement l’authentification unique dans un navigateur. OpenID Connect utilise des jetons JSON signés et hérite des mécanismes d’OAuth 2.0, ce qui le rend plus naturel pour les applications mobiles et les appels d’API.

Faut-il migrer ses applications SAML vers OpenID Connect ? Pas par principe. SAML 2.0 reste un standard en vigueur et largement déployé pour l’authentification unique des applications web. Une migration se justifie quand l’application a besoin de ce qu’OAuth 2.0 apporte en plus, typiquement des appels d’API au nom de l’utilisateur ou un client mobile, pas parce que le protocole serait plus récent.

Un scope OAuth est-il une habilitation ? Non. Un scope délimite ce qu’une application cliente est autorisée à demander pour le compte de l’utilisateur. Il ne dit pas si l’utilisateur détient le droit métier correspondant. Le serveur qui expose la ressource doit continuer à vérifier ce droit, en combinant le jeton avec les autres informations dont il dispose.

OAuth 2.1 est-il publié ? Pas à la date de rédaction. Au 3 octobre 2026, OAuth 2.1 est un Internet-Draft de l’IETF (version -16 du 3 septembre 2026), pas une RFC. Les pratiques qu’il consolide sont en revanche déjà formalisées dans la RFC 9700 (janvier 2025), qui met à jour la RFC 6749.

Conclusion

SAML, OAuth 2.0 et OpenID Connect sont souvent comparés comme trois générations d’un même outil. Ils répondent en réalité à des questions différentes : prouver une authentification à une application, ou déléguer un accès à une ressource. Aucun ne décide d’un droit ; ils transportent des informations que d’autres processus ont produites. Pour démarrer concrètement, le plus utile est de reprendre l’inventaire des applications fédérées et, pour chacune, d’identifier les attributs ou scopes qui conditionnent un droit, puis de vérifier qu’ils ont un propriétaire et qu’ils sont revus. Le choix du protocole vient ensuite, application par application.

Sources

Pages consultées le 3 octobre 2026.