OAuth : l'authentification universelle

mieux protéger une application internet

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com
Grâce à la connexion à un réseau social notre application peut facilement gagner de nouveaux utilisateurs. Une ouverture au monde qui a été rendue accessible via l'uniformisation de la méthode d'authentification, appelée OAuth. Grâce à ce protocole le développeur peut écrire le code d'authentification commun pour les web services majeurs (Google, Yahoo, Twitter...), faciliter son travail et maximiser les coûts de production.

L'article abordera d'abord l'origine de l'OAuth. Ensuite il expliquera le principe de ses deux cas d'utilisation. A la fin un exemple pratique d'implémentation chez Yahoo montrera comment intégrer OAuth dans son application.

OAuth est un protocole né d'une limitation de l'OpenID. Blaine Cook, mécontent du fait que l'OpenID oblige les utilisateurs à partager leurs données (logins et mots de passe), décide de faire évoluer les choses. Il entame alors une discussion avec Chris Messina au sujet de l'implémentation d'un standard libre. Il doit ressembler beaucoup aux protocoles d'authentification de FlickrAuth, Google AuthSub et Yahoo! BBAuth. Il a ensuite rencontré les créateurs de l'OpenID. En 2007, leur rencontre donne naissance à la création d'un groupe de travail, OpenAuth Group. L'objectif de cette équipe consiste à élaborer un standard commun d'authentification pour les web services.

Le flux d'authentification OAuth 1.0
Les concepteurs du protocole se sont inspirés du flux d'authentification du FlickrAuth. La communication se déroule entre 2 ou 3 participants.

Dans le cas des 2 participants, on parle d'un 2-legged OAuth. L'échange se déroule entre le client et le serveur. Le flux se présente ainsi :

CLIENT SERVEUR
Le serveur attribue au client des données d'accès. Il s'agit plus précisément d'une clé client (consumer key) et une clé secrète (secret).
Le client envoie une requête au serveur contenant les données d'accès attribués précédemment.
Si les données d'accès sont correctes, le serveur renvoie au client les informations demandées.


Dans 3-legged OAuth participent 3 personnes. Aux serveur et clients se joint l'internaute. Il décide à travers son navigateur si le client peut accéder à ses données privées. Le flux d'échange est plus complexe à élaborer :

CLIENT SERVEUR INTERNAUTE
Le serveur attribue au client des données d'accès. Il s'agit plus précisément d'une clé client (consumer key) et une clé secrète (secret).
Le client envoie une requête au serveur contenant les données d'accès attribués précédemment.
Le serveur décide si les données sont correctes. Si c'est le cas, il envoie une réponse contentant les paramètres suivants : oauth_token, oauth_token_secret et oauth_callback_confirmed.
Le client redirige l'internaute sur le site qui contient la demande d'autorisation
Le serveur redirige l'interaction chez le client en passant deux paramètres : oauth_token et oauth_verifier.L'internaute décide s'il veut faire confiance au client. S'il fait confiance, l'interaction continue.
Le client envoie une requête au serveur pour obtenir un ticket d'accès (access token).
Le serveur valide le paramètre oauth_signature passé par le client. S'il est correct, le serveur renvoie les paramètres que le client devra utiliser lors de ses prochains appels. Il s'agit de : oauth_token, oauth_token_secret.
Le client peut désormais utiliser les paramètres de la réponse précédente pour accéder à des ressources de l'internaute.


Use case : Yahoo OAuth
Pour concrétiser l'article on verra l'implémentation de l'OAuth chez Yahoo. On procédera par les étapes, un peu comme sur la page développeurs de Yahoo. La mini-application va charger la liste des contacts d'un utilisateur Yahoo. On utilisera la signature HMAC-SHA1.


  1. Récupération du ticket de la requête (request token)
    La première étape consiste à récupérer le ticket de la requête. Pour ce faire on devra créer une signature. Elle sera composée d'un base string et d'un signature key.

    Le base string est la concaténation de la méthode d'appel (GET ou POST), de l'URL appelé (sans paramètres) et des paramètres. Ces trois éléments sont liés par un ampersand (&). Ils doivent également être encodés séparément. Voici un tutoriel comment créer un base string pour OAuth.

    Le signature key est la concaténation de la clé secrète de l'utilisateur et du ticket secret. A ce stade-là le dernier paramètre est encore absent. On utilisera donc une chaîne de caractères vide. Un autre tutoriel vous présentera comment créer un signature key pour OAuth.

    La signature utilisée comme paramètre est la concaténation de ces deux éléments, encodée avec l'algorithme HMAC-SHA1 et Base64. Un troisième tutoriel externe à cet article explique exactement comment créer une signature pour OAuth.

    Dans le cas d'une signature générée par HMAC-SHA1, on doit aussi joindre un header avec les paramètres. L'ensemble de la requête se présente ainsi (des paramètres comme la clé consommateur, la clé secrète, le ticket d'accès ont été volontairement renommés) :

    URL : https://api.login.yahoo.com/oauth/v2/get_request_token
    Base signature : GET&https%3A%2F%2Fapi.login.yahoo.com%2Foauth%2Fv2%2Fget_request_token&oauth_callback%3Dhttp%253A%252F%252Fwww.callbacksite.com%252Foauth%252Fnew%252Fyahoo_2.php%26oauth_consumer_key%3DMY_CONSUMER_KEY%26oauth_nonce%3Dafab4%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1326659813%26oauth_version%3D1.0
    Signature key : MY_SECRET_KEY&
    Header : Authorization: OAuth realm="yahooapis.com",oauth_consumer_key="MY_CONSUMER_KEY",oauth_nonce="cea2f66f",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1326659951",oauth_version="1.0",oauth_signature="CREATED_SIGNATURE",oauth_callback="http%3A%2F%2Fwww.callbacksite.com%2Foauth%2Fnew%2Fyahoo_2.php"
    Résultat : Array ( [oauth_token] => response_token [oauth_token_secret] => token_secret [oauth_expires_in] => 3600 [xoauth_request_auth_url] => https://api.login.yahoo.com/oauth/v2/request_auth?oauth_token=toto [oauth_callback_confirmed] => true )

    Une fois le résultat reçu, ils nous reste à rediriger l'internaute vers https://api.login.yahoo.com/oauth/v2/request_auth?oauth_token=toto afin qu'il autorise notre application (CLIENT dans le tableau) à accéder à ses données.

  2. Récupération du ticket d'accès (access token)

    Une fois que le client a accepté de rendre ses données disponibles, notre application doit obtenir un ticket d'accès (access token).

    La procédure est la même que dans la première étape. La différence repose sur les paramètres passés ainsi que sur la génération du base string. On a reçu les paramètres de la part de l'Yahoo. Dans la génération du signature key on ne peut plus passer une chaîne vide en tant que le ticket secret. A sa place on doit utiliser le paramètre oauth_token_secret. L'ensemble des éléments se présente ainsi :

    URL : https://api.login.yahoo.com/oauth/v2/get_token
    Base signature : GET&https%3A%2F%2Fapi.login.yahoo.com%2Foauth%2Fv2%2Fget_request_token&oauth_callback%3Dhttp%253A%252F%252Fwww.callbacksite.com%252Foauth%252Fnew%252Fyahoo_2.php%26oauth_consumer_key%3DMY_CONSUMER_KEY%26oauth_nonce%3Dafab4%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1326659813%26oauth_version%3D1.0
    Signature key : MY_SECRET_KEY&TOKEN_SECRET_KEY
    Header : Authorization: OAuth realm="yahooapis.com",oauth_consumer_key="MY_CONSUMER_KEY",oauth_nonce="555167ce9921ac45b45bbe546d226c85a",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1326662484",oauth_token="TOKEN_FROM_GET",oauth_verifier="VERIFIER_FROM_GET",oauth_version="1.0",oauth_signature="GENERATED_SIGNATURE_ENCODED_%3D"
    Résultat : Array ( [oauth_token] => ACCESS_TOKEN [oauth_token_secret] => SECRET_TOKEN [oauth_expires_in] => 3600 [oauth_session_handle] => SESSION_HANDLE[oauth_authorization_expires_in] => 820821163 [xoauth_yahoo_guid] => YAHOO_USER_ID )

  3. Récupération de la liste des contacts
    Tous les paramètres nécessaires sont à notre disposition. Maintenant il faut refaire la même opération qu'avant (génération d'une signature, l'ajout d'un header), mais avec de nouveaux paramètres.

    Pour créer le signature key on utilisera le paramètre oauth_token_secret reçu à l'étape précédente.

    URL : http://social.yahooapis.com/v1/user/USER_ID/contacts?format=json
    Base signature : GET&http%3A%2F%2Fsocial.yahooapis.com%2Fv1%2Fuser%USER_ID%2Fcontacts&format%3Djson%26oauth_consumer_key%3DCONSUMER_KEY--%26oauth_nonce%3D75ab%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1326742357%26oauth_token%3DA%25OAUTH_TOKEN--%26oauth_version%3D1.0
    Signature key : MY_SECRET_KEY&TOKEN_SECRET_KEY
    Header : Authorization: OAuth realm="yahooapis.com",oauth_consumer_key="CONSUMER_KEY",oauth_nonce="79e03b0e45d525280d35a2aa6dd2",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1326742190",oauth_version="1.0",oauth_signature="ENCODED_SIGNATURE_rW%2FWjK%2FCL29mpL8%3D",oauth_token="ACCESS_TOKEN"
    Résultat : {"contacts":{"start":0,"count":23,"total":23,"uri":"http://social.yahooapis.com/v1/user/USER_ID/contacts","contact":[{"uri":"http://social.yahooapis.com/v1/user/IWAEKWXHNDQAYNAEHSVAAIRNFI/contact/1","created":"2007-06-07T17:38:23Z","updated":"2007-06-07T17:38:23Z","isConnection":false,"id":1,"fields":[{"uri":"http://social.yahooapis.com/v1/user/USER_ID/contact/1/email ......



Ayant rencontré quelques problèmes (le message signature_invalid m'a trop piqué aux yeux), je mets à votre disposition un package. Il contient une petite librairie qui facilite la connexion à l'OAuth de l'Yahoo. Il possède également 4 exemples : 2 pour la méthode HMAC-SHA1 (yahoo_1.php et yahoo_2.php) et 2 pour la méthode plaintext (yahoo_1_plaintext.php et yahoo_2_plaintext.php). Sentez-vous libres à télécharger les exemples d'implémentation de l'OAuth chez Yahoo.

L'article écrit en rythme de:
Slaï - Tout au fond des océans
Bartosz KONIECZNY 16-01-2012 20:47 sécurité des applications web
Un conseil Android

Comment résoudre le problème de «Unknow Android Packaging Problem" » dans Eclipse ?

Une simple manipulation dans le menu Project->Clean devrait aider.