Académique Documents
Professionnel Documents
Culture Documents
Table des
matières
Objectifs
3. Les tokens
1. Présentation de JWT
2. La composition du Token
Authentification avec
OAuth 2.0 I
L'authentification basique
L'authentification basique est la plus simple des authentifications ! Elle nécessite un nom d'utilisateur et un mot de
passe. Techniquement :
- le client prend ces deux identifiants et les transforme en une valeur unique, qu'il passe dans la requête
HTTP ;
- à réception de la requête HTTP, le serveur compare la valeur unique et les identifiants qu'il a enregistrés.
Si le nom d'utilisateur et le mot de passe correspondent à ceux d'un utilisateur dans la liste, le serveur
exécute la requête de l'utilisateur. Sinon, il retourne un code de statut spécial (401) pour dire au client que
l'authentification a échoué et que la requête n'a pu être exécutée.
Même si l'authentification basique est un système valide, l'identifiant utilisé pour accéder à l'API est le même que
le compte utilisateur.
Pour résoudre ce problème, il existe une technique : accéder à l'API par une clé unique. La clé est
- généralement une série de lettres et chiffres différents du mot de passe utilisateur que l'application client
utilise.
- Techniquement, Le client s'authentifie au moyen de la clé API. Cette dernière peut être passée en
paramètre de l'URL : http://monsiteweb.com?api_key=my_secret_key ; le serveur sait qu'il peut lui donner
accès aux ressources.
- OAuth est un protocole libre ou framework qui permet d'autoriser un site web, un logiciel ou une
application (dite « consommateur ») à utiliser l'API sécurisée d'un autre site web (dit « fournisseur ») pour
le compte d'un utilisateur. OAuth n'est pas un protocole d'authentification, mais de « délégation
d'autorisation ».
OAuth permet aux utilisateurs de donner, au site ou logiciel « consommateur », l'accès à ses informations
- personnelles qu'il a stockées sur le site « fournisseur » de service ou de données, ceci tout en protégeant
le pseudonyme et le mot de passe des utilisateurs.
>> Par exemple, un site de manipulation de vidéos pourra éditer les vidéos enregistrées sur Dailymotion d'un
utilisateur des deux sites, à sa demande.
>> En avril 2010, la RFC 5849 standardise OAuth 1.0a et en octobre 2012, les RFC 6749 et RFC 6750
standardisent OAuth 2.0.
>> Oauth2.0 se distingue essentiellement de OAuth1.0 par le fait qui utilise le protocole HTTPS/TLS pour les
échanges, et s’avère plus flexible.
OAuth est le standard privilégié quand à la sécurisation de l'accès aux API, nous allons donc l'étudier en détail.
Les rôles dans Oauth
Les rôles dans Oauth
Un utilisateur souhaite importer des données d'une application B dans une application A. La problématique qui se
pose est la suivante : comment faire en sorte que l'application A accède aux données de l'utilisateur stockées dans
l'application B, sans que celui-ci ne communique son identifiant et son mot de passe :
1. L'utilisateur va demander à l'application A de contacter l'application B.
2. Il est redirigé par l'application A vers l'application B et il s'authentifie sur cette dernière.
3. L'application B va alors demander à l'utilisateur s'il autorise ou non l'application A à accéder aux
ressources hébergées dans l'application B. Si l'utilisateur l'autorise, l'application B va envoyer un code
d'autorisation au navigateur web de l'utilisateur.
4. Ce code est ensuite communiqué à l'application A.
5. Dès lors, le code est envoyé de l'application A vers la B pour obtenir en échange un jeton d'accès. Ce jeton
a pour objectif d'éviter de communiquer les codes d'accès de l'utilisateur de l'application B à l'application
A. On gagne ainsi en sécurité et en simplicité.
6. Le jeton d'accès est transmis à l'application A.
7. L'application A peut ainsi demander, via le jeton d'accès, d'accéder aux données de l'application B.
Les tokens
Les tokens
3. Les tokens
La demande d'accès à une ressource protégée via OAuth se traduit par la délivrance d'un token au client. Le
token représente juste une chaîne de caractère unique permettant d'identifier le client et les différentes
informations utiles durant le processus d'autorisation.
Le serveur d'autorisation est en mesure d'en fournir deux types.
- Token d'accès : Access token
Le token d'accès permet au client d'accéder à la ressource protégée. Ce token a une durée de validité limitée et
peut avoir une portée limitée.
Cette notion de portée permet d'accorder un accès limité au client. Ainsi, un utilisateur peut autoriser un client à
accéder à ses ressources qu'en lecture seule.
- Token de rafraîchissement : Refresh token
Le token de rafraîchissement permet au client d'obtenir un nouveau token d'accès une fois que celui-ci a expiré.
Sa durée de validité est aussi limitée mais est beaucoup plus élevée que celle du token d'accès.
Son utilisation permet au client d'obtenir un nouveau token d'accès sans l'intervention du propriétaire de la
ressource protégée.
La gestion des clients
La gestion des clients
Une demande d'autorisation avec OAuth est toujours initiée par un client. Pour tous les clients, il faudra donc les
enregistrer auprès du serveur d'autorisation.
L'enregistrement nécessite au moins trois informations :
- l'identifiant du client (Application Name: le nom de l'application) ;
- Grant Type(s) (les types d'autorisation) qui seront utilisés par le client ; le mot de passe ou la paire de
clés (publique/privée) pour les clients confidentiels ;
- Redirect URI (ou Callback URL) : URI (ou URL) de l'application cliente vers laquelle seront faites les
redirections par le serveur d'autorisation, une fois l'accès aux ressources autorisé (ou bien lorsque l'accès
sera refusé),
Bien que les spécifications de OAuth 2.0 n'excluent pas l'utilisation de clients non-enregistrés, leur utilisation est
au-delà des spécifications du protocole. Nous n'aborderons donc pas ce cas d'usage.
Le serveur d'autorisation délivre en retour un couple client_id/client_secret :
- client_id : chaîne de caractères générée de façon aléatoire qui identifie une application cliente de manière
unique,
- client_secret : chaîne de caractères représentant la clé secrète du client et qui sera utilisée lors de l'appel à
certaines API nécessitant une entête HTTP Authorization.
Petit rappel : les clients dont nous parlons sont des applications écrites par des développeurs, qui veulent
consommer votre API. Ces clients peuvent être confidentiels, externes, ou publics.
La distinction entre ces 3 types de clients dépend de
- la confiance qu'a le Serveur d'Autorisation dans leur capacité à protéger leurs identifiants (s'assurer qu'ils
restent secrets) et ceux des utilisateurs
- la façon dont le Serveur d'Autorisation interagit avec eux.
Il s'agit de clients qui sont développés, déployés, et exploités par la même organisation que celle qui gère les
ressources et le Serveur d'Autorisation. Par exemple, des applications de votre entreprise qui ont besoin d'accéder
à des données gérées par une autre application.
Pour un client confidentiel, le Serveur d'Autorisation a confiance dans les points suivants :
- les identifiants du client sont en sécurité (par exemple un client_id et un client_secret)
- il saura les mettre à jour dans le cas où ils seraient compromis
- il ne conservera pas de données utilisateur de façon non sécurisée (voire pas du tout)
- il ne conservera pas les identifiants des utilisateurs
Clients externes
Les clients externes sont les clients de base des anciennes spécifications OAuth0 et OAuth1. L'exemple canonique
est un site internet hébergé sur un serveur différent (de celui qui héberge votre API) et développé par des
développeurs externes.
Pour un client externe, le Serveur d'Autorisation :
- peut lui faire confiance pour garder ses identifiants secrets
- ne peut pas lui faire confiance pour les mettre à jour rapidement s'ils sont compromis (aucun contrôle sur
le travail des développeurs externes)
- ne peut pas lui faire confiance par rapport aux identifiants des utilisateurs.
Pour ces raisons, dans nos scénarios d'interaction, nous n'exposerons pas les identifiants de l'utilisateur à ce type
de client. Par contre, nous leur autoriserons quelques raccourcis pour récupérer un nouveau token si, dans le passé,
ils en ont déjà obtenu un pour leur utilisateur (par exemple avec des mécanismes de refresh token).
Clients publics
Comme leur nom l'indique, les clients publics sont ceux auxquels nous ferons le moins confiance. Dans cette
catégorie, nous regroupons tous les clients qui ne peuvent pas garantir la sécurité de leurs identifiants (client_id et
client_secret), typiquement des applications mobiles ou des SPA (single-page applications) dont le code source
peut être récupéré.
Pour un client public, le Serveur d'Autorisation :
- ne peut pas lui faire confiance pour garder ses identifiants secrets
- ne peut pas lui faire confiance pour les mettre à jour rapidement s'ils sont compromis
- ne peut pas lui faire confiance par rapport aux identifiants des utilisateurs.
Pour ces raisons, nous utiliserons des techniques pour valider “implicitement” l'identité de l'utilisateur final à
travers ce type de client (tous les détails viendront plus loin dans l'article, ne vous en faites pas !) De plus, les
tokens attribués à ce type de client auront une durée de vie courte, et ne seront pas automatiquement
renouvelables.
Exercice : Activité d'auto-évaluation 1
Exercice : Activité d'auto-évaluation 1
AuOth2
OAuth2
XAML
Open DC
OIDC
Exercice : Différentes techniques d'authentification d'API
Il existe différentes techniques d'authentification d'API telles que:
authentification privée
L'authentification basique
L'authentification Ouverte
L'authentification AuOth
Avec OAuth2 il y a 4 types d'autorisation possibles selon l'emplacement et la nature des entités intervenant dans
l'obtention du token d'accès.
Les scénarios sont illustrés par le flow suivant :
Il doit être utilisé dès que possible et tout particulièrement quand le client est un serveur web. Permet d'obtenir un
token d'accès de longue durée qui pourra être renouvelé via un token de renouvellement (si le serveur
d'autorisation le permet).
Exemple :
Scénario :
- Un site internet quelconque souhaite accéder aux informations de votre profil Google.
- Vous êtes redirigé par le client (le site internet) vers le serveur d'autorisation (Google).
- Si vous autorisez l'accès, le serveur d'autorisation (Google) envoie un code d'autorisation au site internet.
- Ce code est échangé (entre le site internet et Google) par un token d'accès de façon transparente pour
vous.
- Le site internet peut donc maintenant utiliser ce token d'accès pour accéder aux données de votre profil
par le serveur de ressources (Google).
Vous n'accèderez jamais au token d'accès, il sera stocké par le site internet (en session par exemple). Google
envoie également d'autres informations en dehors du token d'accès comme la durée de validité du token d'accès et
un token de renouvellement par exemple mais celui-ci n'est pas obligatoire.
C'est le scénario idéal et le plus sûr car le token d'accès n'est pas transmis côté client (votre navigateur web dans
notre exemple).
Diagramme de séquence :
L'autorisation implicite (Implicit Grant)
L'autorisation implicite (Implicit Grant)
Il doit être utilisé quand l'application se trouve côté client (typiquement une application Javascript). Il ne permet
pas d'obtenir de token de renouvellement.
Exemple :
Scénario :
Diagramme de séquence :
Avec ce type d'autorisation, les identifiants (et donc le mot de passe) sont envoyés au client et ensuite au serveur
d'autorisation. Il est donc impératif qu'il y ait une confiance absolue entre ces 2 entités. Il est donc principalement
utilisé lorsque le client a été développé par la même autorité que celle fournissant le serveur d'autorisation. On
pourrait par exemple imaginer un site web example.com voulant accéder à des ressources protégées de son propre
sous-domaine api.example.com. L'utilisateur ne serait donc pas surpris de renseigner son mot de passe sur le site
example.com puisque son compte a été créé sur ce même site.
Exemple :
- Détenteur des données (Resource Owner) : vous ayant un compte sur le site acme.com de la société Acme
- Serveur de ressources (Resource Server) : la société Acme exposant son API à api.acme.com
- Client (Client Application) : le site internet acme.com de la société Acme
- Serveur d'autorisation (Authorization Server) : un serveur de la société Acme
Scénario :
1. La société Acme fait les choses bien et a pensé à mettre à disposition à des applications tierces une API
RESTful exposant tout plein de méthodes pratiques pour récupérer des données diverses et variées de ses
utilisateurs.
2. Cette société se dit qu'il serait pratique d'utiliser sa propre API pour éviter de réinventer la roue et de
maintenir du code à plusieurs endroits.
3. Elle a donc besoin d'un token d'accès pour appeler les méthodes de son API.
4. Pour cela elle vous demande de renseigner vos identifiants de connexion via un formulaire HTML
classique tel que vous le faites habituellement.
5. L'application côté serveur (le site acme.com) va échanger vos identifiants contre un token d'accès auprès
du serveur d'autorisation (si vos identifiants sont valides bien évidemment).
6. L'application peut donc maintenant utiliser ce token d'accès auprès du serveur de ressources
(api.acme.com).
Diagramme de séquence :
Il doit être utilisé lorsque le client est lui-même le détenteur des données. Il n'y a pas d'autorisation à obtenir de la
part de l'utilisateur final.
Exemple :
Scénario :
1. Un site internet quelconque stocke des fichiers de toute sorte sur Google Cloud Storage.
2. Le site internet doit passer par l'API Google pour récupérer ou modifier des fichiers et doit donc
s'authentifier auprès du serveur d'autorisation.
3. Une fois authentifié, le site internet obtient un token d'accès qu'il peut désormais utiliser auprès du serveur
de ressources (Google Cloud Storage).
Ici, l'utilisateur final n'intervient pas et n'a dons pas à donner son accord pour accéder au serveur de ressources.
Diagramme de séquence :
Exercice : Activité d'auto-évaluation 2
Exercice : Activité d'auto-évaluation 2
Open Authentication
Open authentification
Open Autorisation
Open Authorization
Exercice : Les différents scénarios d'autorisation de Oauth 2.0
Les différents scénarios d'autorisation de Oauth 2.0 sont :
Implicit Grant
Le JWT (Json Web Token)
Le JWT (Json Web Token)
Présentation de JWT
Présentation de JWT
1. Présentation de JWT
JWT ou JSON Web Token est un standard ouvert décrit dans la RFC 7519 qui permet l'authentification d'un
utilisateur à l'aide d'un jeton (token) signé.
Le principe est le suivant :
- Lors du premier échange, le client envoie son couple login/mot de passe au serveur;
- Si le couple est valide, le serveur génère un token et l'envoie au client. Ce token permettra d'authentifier
l'utilisateur lors des prochains échanges;
- Le client stocke ensuite le token en local;
- Le token est renvoyé, par le client, pour chaque appel à l'API (via l'en-tête HTTP « Authorization »)
permettant ainsi d'authentifier l'utilisateur.
Ex de token :
“eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2NvZGVoZXJvZXMuZnIiLCJpYXQiOjE1
MjEzMDk2MDAsImV4cCI6MTUyMTMxMzIwMCwiYXVkIjoiaHR"
2. La composition du Token
Le Header
La première partie du JWT est le header. Il s'agit d'un objet JSON encodé en base64 qui représente l'en-tête du
token.
Il est composé de deux parties :
- Le type du token;
- L'algorithme utilisé pour la signature.
Avec
l'exemple “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2NvZGVoZXJvZXMuZnIiLCJpYXQiOjE1MjEzM
Dk2MDAsImV4cCI6MTUyMTMxMzIwMCwiYXVkIjoiaHR0cHM6Ly9zaXRlY2xpZW50LmZyIiwic3ViIjoiMTI0Iiwicm9sZSI6InVzZXIifQ"
le header est “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9“. Si nous le décodons, nous obtenons :
{
"typ":"JWT",
"alg":"HS256"
}
Le Payload
La seconde partie du JWT est le payload. Il s'agit tout comme le header, d'un objet JSON encodé en base64 qui
représente cette fois-ci le corps du token. C'est dans cette partie que l'on mettra les informations de l'utilisateur
(identifiant, rôle, etc.) ou toute autre information utile au serveur. Le standard définit trois types de propriétés
(appelées claims) :
- Propriétés réservées : Il s'agit de noms réservés définis par la spécification. On y retrouve notamment :
- “iss” (Issuer) : Permet d'identifier le serveur ou le système qui a émis le token;
- “sub” (Subject) : Il s'agit généralement de l'identifiant de l'utilisateur que le token représente;
- “aud” (Audience) : Il s'agit généralement de l'application ou du site qui reçoit le token;
- “iat” (Issued At) : Il s'agit de la date de génération du token;
- “exp” (Expiration Time) : Il s'agit de la date d'expiration du token.
- Propriétés publiques : Il s'agit de noms normalisés tels que “email”, “name”, “locale”, etc. La liste
complète est disponible à cette adresse;
- Propriétés privées : Il s'agit de propriétés que vous définissez vous-même pour répondre aux besoins de
votre application.
Dans notre exemple de JWT, le payload est :
eyJpc3MiOiJodHRwczovL2NvZGVoZXJvZXMuZnIiLCJpYXQiOjE1MjEzMDk2MDAsImV4cCI6MTUyMTMxM
zIwMCwiYXVkIjoiaHR0cHM6Ly9zaXRlY2xpZW50LmZyIiwic3ViIjoiMTI0Iiwicm9sZSI6InVzZXIifQ
Si nous décodons le payload précédent, nous obtenons :
1 //Payload decodé
2{
3 "iss":"https://codeheroes.fr",
4 "iat":1521309600,
5 "exp":1521313200,
6 "aud":"https://siteclient.fr",
7 "sub":"124",
8 "role":"user"
9}
La Signature
La dernière partie est la signature du token. Il s'agit d'un hash des deux premières parties du token réalisé en
utilisant l'algorithme qui est précisé dans le header.
Elle est donc effectuée en utilisant l'algorithme de signature (défini dans le header) à partir :
- du header au format base64 url encodé,
- du payload au format base64 url encodé,
- de la clé privée du serveur d'autorisation.
Dans notre exemple de token ci-dessus, l'algorithme utilisé est HS256 (HMAC-SHA-256), la signature est donc
créée de cette manière :
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),
'secret')
L'algorithme utilise une clé secrète (détenue par le serveur), utilisée pour signer les tokens mais également
s'assurer de la validité de ceux-ci en vérifiant leur signature.
De ce fait, si un utilisateur malveillant modifie le contenu du token, la signature ne sera plus correcte et le jeton
sera ainsi rejeté.
Dans notre exemple ci-dessus, si l'utilisateur change son rôle en “admin” la signature est bien modifiée :
- Signature du token avec le rôle “user” : Lml5MSnQKGhTxTtkM92sAEXxQEDvOYPtVZWphciwOiM
- Signature du token avec le rôle “admin” : bOSIz8-3jCRQJI4MrSh86T0EVNS_ZeY6cphSaGybZ1Y
Il est également possible d'utiliser d'autres types d'algorithmes pour la création de la signature (comme RSA-
SHA256 par exemple).
Je vous invite à aller sur le site https://jwt.io pour tester vos JWT.
Expiration d'un token
Expiration d'un token
La clé d'API seule n'est pas utilisable, elle permet uniquement d'identifier une application donc dans le cas où un
utilisateur malveillant dérobe une clé d'API, celui-ci ne pourra rien faire sans la clé secrète qui permet, elle de
garantir la preuve de l'identité de l'application via la signature des requêtes.
! La clé secrète ne doit donc jamais être transmise dans une requête, l'application doit sauvegarder celle-ci
de manière sécurisée.
Quelques exemples de requêtes/réponses
Quelques exemples de requêtes/réponses
5. Quelques exemples de requêtes/réponses
Demande de jetons
Token Request :
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
La demande de token est donc effectuée en passant l'authorization code
(code=SplxlOBeZQQYbYS6WxSbIA), l'URI de redirection (redirect_uri) et bien sûr il faut préciser
au serveur d'autorisation que le type d'autorisation fournie est un code
(grant_type=authorization_code). Au niveau des entêtes HTTP, l'API POST /token impose de
positionner les entêtes suivantes :
- Content-Type : le type de contenu,
- Authorization : les credentials d'authentification. Ici, il s'agit d'une authentification basique (Basic)
où la valeur correspond à la chaîne client_id:client_secret encodée en base64.
Token Response
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma:no-cache
{
"access_token" : "2YotnFZFEjr1zCsicMWpAA",
"token_type" : "bearer",
"expires_in" : 3600,
"scope" : "openid profile email",
"id_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Les données sont renvoyées sous forme d'un flux JSON contenant un jeton d'accès (access_token) ainsi que
son type (token_type), sa durée de vie avant expiration (expires_in) et son scope. Un jeton d'identité en
JWT a également été généré (id_token).
un protocole ouvert qui permet l'authentification d'un utilisateur à l'aide d'un jeton (token) signé
un protocole privé qui permet l'authentification d'un utilisateur à l'aide d'un jeton (token) signé
un standard ouvert qui permet l'authentification d'un utilisateur à l'aide d'un jeton signé
un e architecture ouvert qui permet l'authentification d'un utilisateur à l'aide d'un token signé
Solutions des exercices
Solutions des exercices
AuOth2
OAuth2
XAML
Open DC
OIDC
Exercice : Différentes techniques d'authentification d'API
Il existe différentes techniques d'authentification d'API telles que:
authentification privée
L'authentification basique
L'authentification Ouverte
L'authentification AuOth
Open Authentication
Open authentification
Open Autorisation
Open Authorization
Exercice : Les différents scénarios d'autorisation de Oauth 2.0
Les différents scénarios d'autorisation de Oauth 2.0 sont :
Implicit Grant
un protocole ouvert qui permet l'authentification d'un utilisateur à l'aide d'un jeton (token) signé
un protocole privé qui permet l'authentification d'un utilisateur à l'aide d'un jeton (token) signé
un standard ouvert qui permet l'authentification d'un utilisateur à l'aide d'un jeton signé
un e architecture ouvert qui permet l'authentification d'un utilisateur à l'aide d'un token signé