ArticleAutorisation et fédération

Qu'est-ce qu'OAuth 2.0 ?

Le cadre d'autorisation du web : comment une application obtient un accès limité à une API au nom d'un utilisateur, sans jamais connaître son mot de passe.

Nom complet
The OAuth 2.0 Authorization Framework
Publié par
IETF, 2012
Étendu par
OpenID Connect, PAR, mTLS
Dans TOSIAM
Serveur d’autorisation, un par royaume
Sur cette page

OAuth 2.0 en bref#

OAuth 2.0 est un protocole d’autorisation. Il permet à une application d’accéder à une ressource protégée (une API, des fichiers, un agenda) au nom d’un utilisateur, avec son accord, sans que l’application ait besoin de son mot de passe.

L’application ne reçoit pas les identifiants de l’utilisateur : elle reçoit un jeton d’accès (access token), une clé temporaire qui ouvre seulement certaines portes, pendant un temps limité. L’utilisateur peut la retirer à tout moment, sans changer de mot de passe.

Quand une application de facturation vous demande l’autorisation « de lire votre agenda » et que vous l’acceptez sur la page de votre fournisseur, c’est OAuth 2.0 qui fonctionne en coulisse.

Pourquoi OAuth 2.0 existe#

Avant OAuth, une application qui voulait lire les données d’un utilisateur chez un autre service lui demandait tout simplement son identifiant et son mot de passe, puis se connectait à sa place. Cette pratique cumulait les défauts :

  • l’application obtenait un accès total au compte, alors qu’elle n’avait besoin que d’une petite partie des données ;
  • le seul moyen de lui retirer l’accès était de changer de mot de passe, ce qui coupait aussi toutes les autres applications ;
  • chaque application stockait des mots de passe, et la fuite d’une seule suffisait à compromettre les comptes ;
  • l’authentification forte devenait impossible : l’application ne sait pas répondre à un second facteur.

OAuth 2.0 remplace le partage du mot de passe par une délégation : l’utilisateur s’authentifie chez le service qui détient son compte, accepte une demande précise, et l’application reçoit un jeton limité à cette demande.

Les acteurs#

La norme définit quatre rôles.

Faites défiler le tableau
RôleNom OAuth 2.0Exemple
La personne qui possède les données et donne son accordPropriétaire de la ressource (Resource Owner)Claire, qui utilise l’application de notes de frais
L’application qui veut accéder aux donnéesClientL’application de notes de frais
Le service qui authentifie l’utilisateur et délivre les jetonsServeur d’autorisation (Authorization Server)TOSIAM
L’API qui détient les donnéesServeur de ressources (Resource Server)L’API comptable, api.example.fr

Le terme « client » désigne ici l’application, et non l’utilisateur. On distingue deux familles de clients :

  • les clients confidentiels, qui tournent sur un serveur et peuvent garder un secret (application web classique, service en arrière-plan) ;
  • les clients publics, qui s’exécutent chez l’utilisateur et ne peuvent rien cacher (application mobile, application monopage dans le navigateur).

Comment se déroule une autorisation#

Le parcours recommandé pour une application utilisée par une personne est le flux Authorization Code avec PKCE. Le navigateur ne transporte qu’un code à usage unique ; les jetons circulent directement entre l’application et le serveur d’autorisation.

  1. Utilisateur vers Application Demande à importer ses données
  2. Application vers Utilisateur Redirige vers /authorize avec scope, state et code_challenge
  3. Utilisateur vers TOSIAM Suit la redirection
  4. TOSIAM Authentifie l’utilisateur et recueille son accord
  5. TOSIAM vers Utilisateur Redirige vers l’application avec un code à usage unique
  6. Utilisateur vers Application Transmet le code et le state
  7. Application vers TOSIAM Échange le code contre des jetons, avec le code_verifier
  8. TOSIAM vers Application Renvoie l’access token et, si prévu, un refresh token
  9. Application vers API Appelle l’API avec Authorization: Bearer …
  10. API Vérifie le jeton et le scope, puis répond
Flux Authorization Code avec PKCE, puis appel de l’API avec le jeton d’accès.

La demande d’autorisation est une simple URL :

http
GET /tosiam/oauth2/clients/authorize?response_type=code
    &client_id=notes-de-frais
    &redirect_uri=https://app.example.fr/callback
    &scope=comptes:lecture
    &state=af0ifjsldkj
    &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
    &code_challenge_method=S256 HTTP/1.1
Host: login.example.fr

Quelques paramètres méritent qu’on s’y arrête :

  • redirect_uri est l’adresse où le serveur renvoie le code. Elle doit correspondre exactement à une adresse déclarée pour ce client, sinon le serveur refuse la demande.
  • scope décrit ce que l’application demande. C’est la portée du futur jeton.
  • state est une valeur aléatoire que l’application retrouve au retour : elle protège contre les attaques CSRF.
  • code_challenge et code_verifier (PKCE) lient le code à l’application qui l’a demandé. Un code intercepté ne sert à rien sans le code_verifier, que l’application garde pour elle.

Les jetons#

OAuth 2.0 manipule deux jetons principaux.

L’access token est présenté à l’API à chaque appel, le plus souvent dans l’en-tête Authorization: Bearer. Sa durée de vie est courte (une heure est une valeur courante). La norme ne fixe pas son format : ce peut être une chaîne opaque, que l’API fait vérifier par le serveur d’autorisation (endpoint d’introspection, RFC 7662), ou un JWT signé, que l’API vérifie elle-même.

Le refresh token permet à l’application d’obtenir un nouvel access token quand le précédent expire, sans redemander à l’utilisateur de se connecter. Il ne va jamais à l’API : il n’est présenté qu’au serveur d’autorisation. Il vit plus longtemps et doit être protégé en conséquence.

json· Réponse de l'endpoint de jeton
{
  "access_token": "c2F0LmV4YW1wbGUuYWNjZXNzLnRva2Vu",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "cmVmcmVzaC5leGFtcGxlLnRva2Vu",
  "scope": "comptes:lecture"
}

Un jeton bearer fonctionne comme un billet de spectacle : celui qui le présente entre, sans autre vérification. S’il est volé, il est utilisable par le voleur jusqu’à son expiration. D’où l’intérêt des jetons courts, de leur révocation (RFC 7009) et des jetons liés à un certificat (mTLS).

Scopes et consentement#

Un scope est une permission nommée : comptes:lecture, agenda, profile. L’application demande des scopes, l’utilisateur les accepte ou non, et le jeton émis porte les scopes accordés. L’API vérifie ensuite que le jeton contient le scope requis pour chaque opération.

La norme ne définit aucun scope : chaque serveur d’autorisation et chaque API choisissent les leurs. OpenID Connect ajoute quelques scopes standard, dont openid, profile et email.

Les autres grants#

Le moyen d’obtenir un jeton s’appelle un grant. RFC 6749 en définit quatre, et d’autres spécifications en ont ajouté depuis.

Faites défiler le tableau
GrantUsageStatut
Authorization CodeApplication utilisée par une personne, via un navigateurRecommandé, avec PKCE
Client CredentialsService qui agit pour son propre compte, sans utilisateurRecommandé pour les échanges entre machines
Refresh TokenRenouvellement d’un access token expiréRecommandé
Device Authorization (RFC 8628)Appareil sans clavier ni navigateur : téléviseur, outil en ligne de commandeRecommandé pour ce cas
ImplicitAncienne méthode pour les applications monopages : le jeton revient dans l’URLDéconseillé
Resource Owner PasswordL’application collecte le mot de passe et l’envoie au serveurDéconseillé

Deux grants de RFC 6749 sont aujourd’hui déconseillés par les bonnes pratiques de sécurité OAuth (RFC 9700). Le flux Implicit expose le jeton dans l’URL et l’historique du navigateur. Le grant Password fait revenir le problème qu’OAuth devait résoudre : l’application voit le mot de passe.

OAuth 2.0 n’est pas un protocole d’authentification#

Un access token dit « le porteur de ce jeton peut lire les comptes », pas « l’utilisateur connecté est Claire ». Il est destiné à l’API, et l’application n’est pas censée l’interpréter. Utiliser OAuth 2.0 seul pour connecter des utilisateurs conduit à des failles connues, comme accepter un jeton émis pour une autre application.

Pour savoir qui est l’utilisateur, il faut OpenID Connect, qui ajoute à OAuth 2.0 un jeton d’identité destiné à l’application.

Bonnes pratiques#

  • Utilisez le flux Authorization Code avec PKCE pour toutes les applications utilisées par des personnes, y compris les clients confidentiels.
  • N’utilisez plus les grants Implicit et Password dans les nouveaux projets.
  • Déclarez des URL de retour exactes, sans caractère générique, et envoyez toujours un state.
  • Demandez le minimum de scopes, et limitez chaque client aux grants dont il a réellement besoin.
  • Gardez des access tokens courts ; protégez les refresh tokens comme des secrets et révoquez-les quand l’utilisateur se déconnecte.
  • Pour les clients confidentiels exposés à des risques élevés, préférez une authentification par clé (private_key_jwt) ou par certificat (mTLS) à un secret partagé.
  • Envoyez les paramètres sensibles par PAR plutôt que dans l’URL du navigateur.

OAuth 2.0 dans TOSIAM#

TOSIAM est un serveur d’autorisation OAuth 2.0. Le service OAuth2 Provider s’active par royaume ; chaque royaume a donc ses propres clients, scopes, clés et réglages. L’émetteur est l’adresse /oauth2 du serveur, suivie du nom du royaume pour un sous-royaume, par exemple https://login.example.fr/tosiam/oauth2/clients. Les endpoints s’ajoutent à cette adresse :

Faites défiler le tableau
EndpointChemin
Autorisation/authorize
Jeton/access_token
Introspection/introspect
Révocation/token/revoke
Requêtes poussées (PAR)/par
Autorisation d’appareil/device/code, /device/user
Authentification par canal arrière (CIBA)/bc-authorize

Les clients. Chaque application est déclarée comme un agent OAuth 2.0 du royaume, confidentiel ou public. Sa fiche fixe ses URL de retour, ses scopes, la liste des grants qu’elle a le droit d’utiliser et sa méthode d’authentification à l’endpoint de jeton : client_secret_basic (par défaut), client_secret_post, private_key_jwt, tls_client_auth ou self_signed_tls_client_auth. Les applications peuvent aussi s’enregistrer elles-mêmes par l’enregistrement dynamique (/connect/register), qui n’est pas ouvert sans contrôle par défaut.

Les grants. Outre Authorization Code et Refresh Token, TOSIAM accepte Client Credentials, Password, Device Authorization, CIBA, Token Exchange (RFC 8693), ainsi que les assertions SAML 2.0 et JWT (RFC 7522 et 7523). Le détail de chaque grant figure dans la page Grant types.

PKCE. Le paramètre code_verifier peut être rendu obligatoire pour tout le royaume (réglage « Paramètre de vérificateur de code obligatoire » du fournisseur) ou client par client. Quand une demande contient un code_challenge, TOSIAM exige de toute façon le code_verifier correspondant à l’échange du code.

Les jetons. Par défaut, les access tokens sont des références opaques conservées dans le Core Token Store ; l’option « Utiliser des jetons d’accès et de rafraîchissement sans état » les remplace par des JWT signés, vérifiables sans appeler TOSIAM. Les durées de vie par défaut sont de 120 secondes pour un code d’autorisation, une heure pour un access token et sept jours pour un refresh token. La page Tokens compare les deux modèles.

L’authentification et le consentement. L’utilisateur s’authentifie par les mécanismes de TOSIAM : un graphe d’authentification peut exiger une passkey, un code TOTP ou une analyse de risque avant qu’un code ne soit délivré. TOSIAM demande ensuite l’accord de l’utilisateur pour les scopes ; un royaume peut autoriser certains clients à se passer de cet écran, ce qui est utile pour les applications internes.

Pour aller plus loin#

  • RFC 6749, The OAuth 2.0 Authorization Framework
  • RFC 6750, l’utilisation des jetons bearer
  • RFC 7636, PKCE
  • RFC 9700, les bonnes pratiques de sécurité OAuth 2.0

Mis à jour le