OAuth/Pour les développeurs

This page is a translated version of the page OAuth/For Developers and the translation is 99% complete.
Outdated translations are marked like this.

Cette page explique comment développer des applications pouvant s'intégrer à un wiki en utilisant Extension:OAuth (une extension qui transforme MediaWiki en serveur OAuth) pour demander la permission de manière sécurisée pour agir au nom de l'utilisateur.

Si vous développez un robot ou une application similaire qui utilise toujours le même compte vous pouvez préférer les consommateurs exclusifs.

OAuth en résumé

OAuth permet à une application de demander l'autorisation d'un utilisateur pour agir en utilisant le compte wiki de cet utilisateur, sans connaître son mot de passe, et sans pouvoir faire tout ce que l'utilisateur pouvait faire (par exemple, l'application pourrait être capable de modifier des articles mais ne pas les supprimer, de sorte que même les utilisateurs ayant des droits étendus peuvent utiliser en toute sécurité les outils activés par OAuth).

Cela se produit via le protocole OAuth 2.0 ou OAuth 1.0a et se compose de trois étapes :

  1. Le développeur doit enregistrer l'application (souvent appelée le consommateur dans la terminologie OAuth) sur le wiki, éventuellement passer par une sorte de processus d'examen, et recevoir les informations d'identification.
  2. Quand l'utilisateur souhaite utiliser l'application celle-ci doit initier un processus d'autorisation. Cela impliquera le renvoi de l'utilisateur sur une page spéciale du wiki, qui affichera un dialogue concernant l'autorisation. Si l'utilisateur accepte, l'application recevra un autre ensemble d'identifiants (qui sont spécifiques à cet utilisateur et peuvent être révoqués par l'utilisator à tout moment).
  3. Lorsque l'application veut faire une action (une demande à l'API) au nom de l'utilisateur, elle peut combiner les informations d'identification reçues aux étapes 1 et 2 pour signer la requête.

OAuth est une norme ouverte largement utilisée (vous pouvez la voir sur des sites comme Google ou Facebook ou GitHub, par exemple lorsque vous utilisez des comptes sur ces sites pour vous connecter ailleurs).

OAuth ne doit pas être confondu avec :
  • OATH (une famille de protocoles d'authentification à deux facteurs, connue habituellement comme Entrez les six nombres que vous voyez sur votre application mobile, maintenant activée sur les sites Wikimedia)
  • OpenID Connect (un protocole d'authentification basé sur OAuth 2.0, que l'extension OAuth de MediaWiki prend encharge partiellement).

Pour un aperçu un peu plus étendu sur OAuth 1.0a, voir ce diaporama.

OAuth en détails

L'enregistrement est essentiellement le même pour OAuth 1.0a et OAuth 2, la différence étant que quelques champs de formulaire sont présents. Les autres parties diffèrent de manière significative en fonction de la version de OAuth. Généralement, OAuth 2 est recommandé s'il est disponible dans votre environnement.

Enregistrement

Pour enregistrer une nouvelle application OAuth, soumettez le formulaire à Special:OAuthConsumerRegistration/propose. Essayez de donner suffisamment d'informations à propos de l'application pour que les administrateurs et les utilisateurs puissent décider si elle est digne de confiance. Les URL des endroits où on trouve plus d'informations (comme l'application elle-même, le code source ou la documentation sur le wiki) peuvent être utiles. Pour les applications OAuth à utiliser dans les projets Wikimedia, voir les règles des applications.

En plus des descriptions, les champs ont les significations suivantes :

  • This consumer is for use only by ‎<user>: indique si vous utilisez les consommateurs exclusifs (qui ne nécessite pas d'être revu ni autorisé, mais qui n'est utilisable que par vous-même).
  • callback URL (ne concerne pas les consommateurs exclusifs): URL où l'utilisateur est renvoyé après que l'autorisation correspondante a été vérifiée. (C'est une couche supplémentaire de sécurité contre un attaquant qui essaie de voler les informations durant l'autorisation). Si l'option utiliser en tant que préfixe est activée, l'URL doit commencer par cette valeur (le contrôle est fait pour s'assurer d'avoir ajouté au moins un / après le nom de domaine), sinon la correspondance doit être exacte. Si vous développez ou testez sur votre machine locale, indiquez Localhost dans ce champ (e.g. http://localhost:8080/).
  • Applicable project (pour les fermes de wikis uniquement): le ou les projets sur lesquels votre application sera utilisée. Vous pouvez limiter l'application à un seul wiki ou la faire fonctionner partout.
  • Types of grants / Applicable grants: autorisations requises par votre application (soyez conservateur). Les autorisations réelles sont un ET logique entre celles-ci et les droits actuels de l'utilisateur. Actuellement, l'utilisateur doit autoriser les autorisations groupées, et non les autorisations individuelles (T59505).
  • Allowed IP ranges: spécification facultative des intervalles d'adresses IP que vous utilisez, quand les requêtes OAuth qui ne correspondent pas à celles-ci sont rejetées. C'est une couche supplémentaire de sécurité contre un attaquant qui vole les informations de votre application et essaie de les utiliser. C'est l'un des quelques paramètres que vous pourrez modifier plus tard.
  • Public RSA key (OAuth 1.0a uniquement): clé publique utilisée par votre application demande pour signer les requêtes. Vous pouvez laisser cela vide (ce que fait la plupart des applications) pour utiliser un mécanisme de partage de secrets légèrement plus simple à la place. C'est l'un des quelques paramètres que vous pourrez modifier ultérieurement. Après l'enregistrement, vous recevrez les informations nécessaires pour utiliser OAuth. Vous pourrez l'utiliser immédiatement avec votre propre compte utilisateur (ceci est fait pour les tests); les autres ne pourront l'utiliser qu'une fois qu'il sera approuvé par un administrateur.

Si vous changez d'avis, vous pouvez désactiver l'application sous m:Special:OAuthConsumerRegistration/list. La liste des applications (approuvées et autres) est publique et disponible sur Special:OAuthListConsumers.

OAuth 1.0a

Autorisation

 
Dialogue d'autorisation affiché aux utilisateurs

Lors de l'enregistrement de l'application, vous recevez deux informations d'identification : le jeton de l'application (identifiant public pour l'application) et le code le secret de l'application (une sorte de mot de passe).

Pour pouvoir identifier un utilisateur ou faire des demandes d'API en son nom, vous devez obtenir un autre ensemble de identifiants (ceux-ci étant spécifiques à cet utilisateur) : le jeton d'accès et le code secret d'accès.[1]

Pour les obtenir, vous devez passer par le processus d'autorisation, qui consiste en trois étapes :[2]

  1. Obtenir un jeton de requête du wiki en envoyant une requête GET sur Special:OAuth/initiate, signée avec la clé et le code secret de l'application, avec l'URL de rappel (où l'utilisateur sera redirigé si l'autorisation réussit) passés dans le paramètre oauth_callback de la requête (si vous avez défini une URL constante à l'enregistrement, la valeur du paramètre doit être oob).[3] Si cela fonctionne, la réponse sera un objet JSON avec les champs token (le jeton de la requête) et key (le code secret de la requête). (si ce n'est pas le cas, il aura un champ error).
  2. Demander à l'utilisateur d'autoriser l'application en les envoyant à Special:OAuth/authorize, avec le jeton de l'application et le jeton de la requête passés dans les paramètres de la requête (respectivement oauth_consumer_key et oauth_token).[4] L'utilisateur verra un dialogue sur l'autorisation avec quelques informations de base sur l'application et la liste des droits et pourra décider d'autoriser ou d'annuler.
  3. Si l'utilisateur choisit d'autoriser, il sera redirigé vers l'URL de rappel que vous avez fournie (à l'enregistrement, ou comme paramètre d'URL à l'étape 1). Le paramètre de requête oauth_verifier contiendra le code de vérification que vous pouvez utiliser pour échanger le jeton de la requête avec son code secret contre le jeton d'accès avec son code secret. Pour ce faire, envoyez une demande à Special:OAuth/token[3] qui inclut le paramètre de oauth_verifier que vous venez de recevoir et qui est signé avec le jeton de l'appliction et son code secret et le jeton de la requête et son code secret. La réponse contiendra le jeton d'accès et son code secret (dans le même format que celui du jeton de la requête et son code secret de l'étape 1).

Le jeton d'accès et son code secret sont ce dont vous aurez besoin pour signer les requêtes à l'API. Le jeton de la requête et le code secret ne sont plus utiles et peuvent être effacés. Le jeton d'accès restera valable indéfiniment, à moins que l'utilisateur ne le révoque. (Si vous préférez ne pas le stocker, vous pouvez néanmoins répéter simplement le processus d'autorisation à tout moment).

Les applications qui ne nécessitent qu'un nombre minimum de droits (elles ont été enregistrées avec Vérification uniquement de l'identité de l'utilisateur) peuvent utiliser /authenticate au lieu de /authorize à l'étape 2. Cela fonctionne de la même manière, mais l'utilisateur ne verra le dialogue d'autorisation que s'il n'a pas autorisé cette application auparavant; autrement, l'autorisation réussira silencieusement.

Il est probable que le langage ou l'environnement que vous utilisez ait une bibliothèque qui prenne en charge cette procédure, donc vous n'avez pas à l'implémenter manuellement — chaque étape sera un seul appel de fonction. Voir ci-dessous pour les exemples.

Faire des requêtes au nom de l'utilisateur

Pour bénéficier de l'autorisation, les requêtes doivent être signées avec le jeton et le code secret de l'application et le jeton et le code secret de l'accès. En cas de succès, le wiki traite la requête comme si elle avait été faite par l'utilisateur qui a donné l'autorisation. Seules les requêtes à l'API peuvent être faites via OAuth, à une seule exception (voir la section suivante). Certains modules de l'API qui n'auraient pas de sens avec OAuth (comme la connexion et la déconnexion), ou qui permettraient l'escalade des privilèges (comme l'API centralauthtoken), sont désactivés.

Les applications enregistrées comme Vérification uniquement de l'identité de l'utilisateur ne peuvent pas utiliser l'API du tout.

Identifier l'utilisateur

L'extension OAuth contient un protocole personnalisé (semblable à OpenID Connect) pour authentifier l'utilisateur. Pour utiliser cela, envoyez une requête OAuth signée à Special:OAuth/identify :[3] la réponse va être un JWT (JSON Web Token – objet JSON signé) comprenant le nom de l'utilisateur, son ID centralisé (sous la clé sub) et différentes autres informations (telles que les groupes utilisateur auxquels il appartient et s'il est bloqué; également son adresse courriel si l'application a été enregistrée avec le bon type de privilège). Ceci est plus sûr que d'utiliser l'API (par exemple le module userinfo) pour l'authentification, et qui pourrait être sujet à des attaques par les 'hommes du milieu; utilisez toujours cela si vous avez besoin d'identifier un utilisateur ! Assurez-vous également de valider correctement le JWT (il existe beaucoup de bibliothèques qui peuvent vous aider à cela). Vous devez vérifier chacun des éléments suivants : l'émetteur (iss) correspond au nom de domaine du wiki, le public (aud) correspond à votre clé de votre application, l'heure d'émission (iat) se trouve dans le passé et est raisonnablement proche de l'heure actuelle, l'heure d'expiration (exp) est dans le futur, le nonce (nonce) correspond à celui que vous avez envoyé dans la requête.

Signer les requêtes

Les étapes 1 et 3 du processus d'authorisation nécessitent de signer la requête ; de même les requêtes à l'API et Special:OAuth/identify doivent être signées. Le processus de signature est détaillé dans la section 9 de la spécification OAuth, mais il est fastidieux à mettre en œuvre à la main mais de nombreuses bibliothèques sont disponibles. Vous trouverez des exemples de code et un aperçu sur la manière de le faire manuellement dans la documentation du consommateur exclusif . (Ceci permet de signer avec le jeton et le code secret du consommateur, et le jeton d'accès et le code secret. Modifier le cas échéant pour signer avec le jeton et le code secret du consommateur et le jeton et le code secret de la requête (autorisation étape 3) ou uniquement le jeton et le code secret du consommateur (autorisation étape 1).)

OAuth 2

Autorisation

Lorsque vous enregistrez l'application, vous recevez deux informations d'identification : la clé de l'application cliente (un ID public de l'application, appelé aussi l'ID client ou la clé consommateur) et le mot de passe de l'application cliente (un mot de passe confidentiel). Pour identifier un utilisateur ou pour faire des requêtes à l'API en son nom, vous devez obtenir d'autres informations (spécifiques à l'utilisateur) : le jeton d'accès. Pour l'obtenir vous devez exécuter la séquence de code d'autorisation OAuth 2 qui se compose de deux étapes :[5]

  1. Demandez à l'utilisateur d'autoriser l'application en leur envoyant à oauth2/authorize sur le point d'accès REST du wiki (généralement rest.php), avec response_type=code et la clé consommateur (également appelée clé de l'application cliente) en tant que client_id, éventuellement un state si vous le souhaitez, et optionnellement redirect_uri (si oui, il doit être le même que celui de la requête de l'application). Si votre consommateur n'est pas confidentiel, vous devrez également inclure un défi de code PKCE (code_challenge et code_challenge_method=S256).[6] L'utilisateur verra un dialogue de l'autorisation avec quelques informations de base sur la demande et la liste des droits et pourra décider d'autoriser ou d'annuler.
  2. Si l'utilisateur a choisi d'autoriser, il sera redirigé vers l'URL de rappel que vous avez fournie (à l'enregistrement, ou en tant que paramètre d'URL de l'étape 1). Le paramètre de requête code contiendra le code d'autorisation que vous pouvez utiliser pour récupérer le jeton d'accès. Pour ce faire, envoyez une requête POST à oauth2/access_token sur le point d'accès REST du wiki (généralement rest.php), comprenant grant_type=authorization_code, le paramètre code que vous venez de recevoir, l'authentification de votre client (générativement client_id et pour les clients confidentiels, client_secret), redirect_uri si et seulement si vous l'avez spécifié dans la étape précédente (la valeur étant la même pour les deux), et si non confidentielle, les PKCE code_verifier et code_challenge_method. La réponse contiendra le jeton d'accès et un jeton de rafraîchissement.

Le jeton d'accès est ce dont vous aurez besoin pour envoyer les futures requêtes à l'API. Le jeton de rafraîchissement peut être utilisé pour demander un nouveau jeton d'accès si le jeton d'accès original a expiré. Si vous préférez ne pas stocker les deux jetons, vous pouvez simplement répéter le processus d'autorisation à tout moment. (Notez que les clients non confidentiels ne peuvent actuellement utiliser les jetons de rafraîchissement qu'en utilisant leurs clés secrètes de client, et pas en utilisant seulement leur ID de client, voir T323855).

Il est probable que la langue ou l'environnement que vous utilisez aura une bibliothèque pour prendre en charge cette procédure, vous n'aurez donc pas à l'implémenter manuellement - chaque étape sera un seul appel de fonction. Voir ci-dessous pour les exemples.

Faire des requêtes au nom de l'utilisateur

Pour tirer parti de l'autorisation, les requêtes doivent inclure le jeton d'accès. En cas de succès, le wiki traite la requête comme si elle avait été faite par l'utilisateur qui a donné l'autorisation. Seules les requêtes à l'API peuvent être faites via OAuth 2. Certains modules de l'API qui n'auraient pas de sens avec OAuth (comme la connexion et la déconnexion), ou qui permettraient l'escalade des privilèges (comme l'API centralauthtoken), sont désactivés. Si le jeton d'accès est utilisé pour obtenir un jeton CSRF ou d'autres jetons, le jeton d'accès doit toujours être passé (en tant qu'entête) avec les requêtes qui utilisent ces jetons.

Les applications qui ne nécessitent qu'un nombre minimum de droits (elles ont été enregistrées avec Vérification uniquement de l'identité de l'utilisateur) ne peuvent pas utiliser l'API du tout.

Les requêtes à l'API comprenant rest.php/oauth2/resource/profile doivent être authentifiées avec une entête d'autorisation HTTP contenant le jeton d'accès, comme

Authorization: Bearer abcde....6789

Identifier l'utilisateur

L'extension OAuth comprend une implémentation quelque peu incomplète d'OpenID Connect pour authentifier l'utilisateur.[7] Pour utiliser cela, envoyez une demande OAuth GET authentifiée à l'API oauth2/resource/profile (implémentation de MediaWiki de ce que les spécifications OIDC appellent le point d'accès UserInfo) sur le point d'accès REST du wiki (généralement rest.php); la réponse comprendra le nom de l'utilisateur et diverses autres informations. Notez que la requête GET doit utiliser l'entête HTTP Authorization, et non pas un jeton de chaîne de requête.

  • sub (id centralisé de l'utilisateur)
  • username
  • editcount
  • confirmed_email
  • blocked
  • registered
  • groups
  • rights
  • realname (uniquement si l'utilisateur a donné l'autorisation)
  • email (uniquement si l'utilisateur a donné l'autorisation)

Configurer l'environnement de développement

Vous pouvez enregistrer une application OAuth sur meta bêta et tester votre code avec.

Si vous souhaitez améliorer l'extension elle-même, ou déboguer les problèmes de protocole en détails, OAuth est disponible dans l'environnement de développement MediaWiki-Vagrant . Ajoutez le rôle oauth, et votre wiki locale pourra autoriser les applications OAuth.

$ vagrant roles enable oauth
$ vagrant provision

Une fois que le code commence à être prêt, vous pouvez enregistrer une application OAuth sur le wiki réel. Vous pourrez la tester avec le même compte utilisateur utilisé pour vous inscrire, avant même qu'elle ne soit relue par les administrateurs.

Si vous créez une application pour des projets Wikimedia, pensez à les héberger sur Wikimedia Toolforge, une forge d'outils gratuite et une plateforme d'hébergement pour les services relatifs à Wikimedia.

Bénéfices sécuritaires et compromis

  • A la différence des authentifications basées sur un mot de passe, le protocole OAuth 1.0 empêche toute attaque de l'homme du milieu même si le wiki ne nécessite pas HTTPS : toutes les interactions entre MediaWiki et l'application sont signées soit avec un code secret partagé (en utilisant HMAC-SHA1), ou une clé publique (RSA). Cependant, certains étapes nécessitent encore HTTPS (pour obtenir le code secret partagé dans la deuxième étape de l'autorisation lorsque l'on n'utilise pas RSA et lors de l'enregistrement de l'application). OAuth 2.0 n'inclut pas la signature mais ils s'appuie sur HTTPS pour la sécurité.
  • Les actions via OAuth se déroulent sous le nom de l'utilisateur mais elles sont marquées également du nom de l'application de sorte à ce que les applications boîteuses puissent être identifiées. Si nécessaire, les administrateurs de Wiki peuvent révoquer les autorisations de l'application (et ainsi empêcher toute action supplémentaire).
  • L'utilisateur peut révoquer l'autorisation de l'application d'utiliser son compte spécifique s'il n'aime pas son fonctionnement ou ne lui fait plus confiance. Contrairement à un changement du mot de passe, cela ne perturbe pas l'utilisateur.
  • Des applications suffisamment flexibles pourraient permettre aux utilisateurs de contourner les blocages d'adresse IP (puisque MediaWiki verra l'adresse IP du serveur d'application, et pas celle de l'utilisateur). Cela peut être géré de la même manière que les proxies, en faisant confiance aux entêtes XFF définis par l'application (voir T159889 pour certaines limitations).
  • Le code secret de la demande doit être gardé secret. Soumettre à la gestion des sources, ou rendre le code accessible à l'utilisateur (comme une application mobile ou une application de bureau; même si elle est masquée) nuit au modèle de sécurité et entraînera la désactivation forcée de l'application par les administrateurs. Des exceptions sont faites par exemple pour les applications démontrant l'utilisation de OAuth, si elles sont explicitement étiquetées comme telles et demandent des droits limités.

Bibliothèques

PHP

Python

Ruby

Rust

Node.js

  • passport-mediawiki-oauth - Stratégie MediaWiki pour l'environnement auth Passeport (utilisable sans effort comme middleware avec Express JS et les environnements similaires)
  • oauth-fetch-json - bibliothèque pour signer les requêtes OAuth

Go

Java

Exemple de code

Client PHP sans utiliser de bibliothèque

OAuth Hello World – application de démonstration facile à comprendre et écrite en PHP sans aucune bibliothèque.

Client PHP en mode ligne de commande avec clés RSA et utilisant oauthclient-php

Application PHP qui utilise les classes de la base de code de l'extension OAuth.

A FAIRE : convertir ceci pour utiliser actuellement oauthclient-php ! probablement un ensemble de déclarations use.


Avant de commencer :

$ openssl genrsa -out appkey.pem 4096
$ openssl rsa -in appkey.pem -pubout > appkey.pub
code source PHP
<?php

if ( PHP_SAPI !== 'cli' ) {
	die( "CLI-only test script\n" );
}

/**
 * Un client de base pour les tests généraux
 */

function wfDebugLog( $method, $msg) {
	//echo "[$method] $msg\n";
}


require 'OAuth.php';
require 'MWOAuthSignatureMethod.php';

$consumerKey = '';
#$consumerSecret = ''; // pas utile puisque nous utilisons RSA, sauf pour valider l'identité de l'appel

$privateKey = file_get_contents( 'appkey.pem' );

$baseurl = 'http://<wiki>/wiki/Special:OAuth';
$endpoint_req = $baseurl . '/initiate?format=json&oauth_callback=oob'; // format=json rend le PHP un peu plus facile
$endpoint_acc = $baseurl . '/token?format=json';
$endpoint_id = $baseurl . '/identify';

$c = new OAuthConsumer( $consumerKey, $privateKey );

// s'assurer de signer le titre et le format
$parsed = parse_url( $endpoint_req );
$extraSignedParams = array();
parse_str($parsed['query'], $extraSignedParams);
$extraSignedParams['title'] = 'Special:OAuth/initiate';

$init_req = OAuthRequest::from_consumer_and_token(
	$c,                // OAuthConsumer pour votre application
	NULL,              // Jeton utilisateur, NULL pour les appels à initier
	"GET",             // méthode http
	$endpoint_req,     // URL du point d'accès (c'est signé)
	$extraSignedParams // paramètres supplémentaires à signer (doit inclure le titre)
);

$rsa_method = new MWOAuthSignatureMethod_RSA_SHA1( new OAuthDataStore(), $privateKey );
$init_req->sign_request(
	$rsa_method, // OAuthSignatureMethod
	$c,          // OAuthConsumer de votre application
	NULL         // Jeton utilisateur, NULL pour les appels à initier
);

echo "Getting request token with: $init_req\n";

$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, (string) $init_req ); // Passer OAuth dans les paramètres du GET
curl_setopt( $ch, CURLOPT_HTTPGET, true );
curl_setopt( $ch, CURLOPT_HEADER, false );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
$data = curl_exec( $ch );

if( !$data ) {
	'Curl error: ' . curl_error( $ch );
}

echo "Returned: $data\n\n";


$requestToken = json_decode( $data );
print "Visit $baseurl/authorize?oauth_token={$requestToken->key}&oauth_consumer_key=$consumerKey\n";

// JETON D'ACCES
print "Enter the verification code:\n";
$fh = fopen( "php://stdin", "r" );
$line = fgets( $fh );

$rc = new OAuthToken( $requestToken->key, $requestToken->secret );
$parsed = parse_url( $endpoint_acc );
parse_str($parsed['query'], $params);
$params['oauth_verifier'] = trim($line);
$params['title'] = 'Special:OAuth/token';

$acc_req = OAuthRequest::from_consumer_and_token(
	$c,
	$rc,
	"GET",
	$endpoint_acc,
	$params
);
$acc_req->sign_request($rsa_method, $c, $rc);

echo "Calling: $acc_req\n";

unset( $ch );
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $endpoint_acc );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array( $acc_req->to_header() ) ); // Initialiser l'entête de l'autorisation
$data = curl_exec( $ch );
if( !$data ) {
	'Curl error: ' . curl_error( $ch );
}

echo "Returned: $data\n\n";
$acc = json_decode( $data );
$accessToken = new OAuthToken( $acc->key, $acc->secret );

/**
 * Appel non-sécurisé à l'API pour obtenir des informations sur l'utilisateur. 
 * Un MITM peut falsifier une réponse du serveur, alors ne vous fiez pas à cela pour l'identité !
 */
$apiurl = 'http://<wiki>/w/api.php';
$apiParams = array(
	'action' => 'query',
	'meta' => 'userinfo',
	'uiprop' => 'rights',
	'format' => 'json',
);

$api_req = OAuthRequest::from_consumer_and_token(
	$c,           // Consumer
	$accessToken, // User Access Token
	"GET",        // HTTP Method
	$apiurl,      // Endpoint url
	$apiParams    // Extra signed parameters
);
$api_req->sign_request( $rsa_method, $c, $accessToken );

$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $apiurl . "?" . http_build_query( $apiParams ) );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array( $api_req->to_header() ) ); // Entête d'autorisation nécessaire pour l'API
$data = curl_exec( $ch );
if( !$data ) {
	'Curl error: ' . curl_error( $ch );
}
echo "Returned: $data\n\n";


/**
 * Obtenir l'identité de l'utilisateur en toute sécurité
 */
$consumerSecret = '';

$extraSignedParams = array(
	'title' => 'Special:OAuth/identify'
);

$req = OAuthRequest::from_consumer_and_token(
	$c,
	$accessToken,
	"GET",
	$endpoint_id,
	$extraSignedParams
);
$req->sign_request( $rsa_method, $c, $accessToken );

echo "Calling:  '$endpoint_id'\nHeader: {$req->to_header()}\n\n";

$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $endpoint_id );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array( $req->to_header() ) );
$data = curl_exec( $ch );
if( !$data ) {
	'Curl error: ' . curl_error( $ch );
}

$identity = JWT::decode( $data, $consumerSecret );

// Valider le JWT
if ( !validateJWT( $identity, $consumerKey, $req->get_parameter( 'oauth_nonce' ) ) ) {
	print "The JWT did not validate";
} else {
	print "We got a valid JWT, describing the user as:\n";
	print " * Username: {$identity->username}\n";
	print " * User's current groups: " . implode( ',', $identity->groups ) . "\n";
	print " * User's current rights: " . implode( ',', $identity->rights ) . "\n";
}


/**
 * Valider un JWT, pour s'assurer que ce n'est pas une réponse, une parodie, etc.
 * @param $identity le JWT décodé
 * @param $consumerKey la clé de votre application
 * @param $nonce nonce envoyé avec votre requête et qui sera renvoyé
 */
function validateJWT( $identity, $consumerKey, $nonce ) {

	$expectedConnonicalServer = 'http://<wiki>';

	// Vérifier que l'émetteur est celui que nous espérions (le serveur envoie $wgCanonicalServer)
	if ( $identity->iss !== $expectedConnonicalServer ) {
		print "Invalid Issuer";
		return false;
	}

	// Vérifier que nous sommes le public prévu
	if ( $identity->aud !== $consumerKey ) {
		print "Invalid Audience";
		return false;
	}

	// Vérifier que nous sommes dans le délai de validité du jeton.
	// émis le (iat) doit être dans le passé,
	// l'expiration (exp) doit être dans le futur.
	$now = time();
	if ( $identity->iat > $now || $identity->exp < $now ) {
		print "Invalid Time";
		return false;
	}

	// Vérifier que nous n'avons pas déjà vu ce nonce, ce qui indiquerait une attaque répétée
	if ( $identity->nonce !== $nonce ) {
		print "Invalid Nonce";
		return false;
	}

	return true;
}

Client Python en mode ligne de commande utilisant mwoauth

code source Python
from mwoauth import ConsumerToken, Handshaker
import requests
from requests_oauthlib import OAuth1
from six.moves import input  # Pour la compatibilité avec Python 2 et 3

# Construire un "consommateur" à partir de la clé/code secret fournis par MediaWiki
import config  # Vous devrez fournir ceci

# créer un fichier 'config.py' sur un chemin connu de Python (ex: le répertoire de ce script),
# avec le contenu suivant (sans les caractères '#' !)
# consumer_key = "jeton consommateur obtenu à l'enregistrement de l'application"
# consumer_secret = "jeton secret obtenu à l'enregistrement de votre application"

#Par exemple :
#consumer_key = "20bc67da5081a30c736340c493f60d14"
#consumer_secret = "af4313371bb2fb38e81fe7d300080085f52849f9"

consumer_token = ConsumerToken(config.consumer_key, config.consumer_secret)

# Construire la confirmation avec l'URI du wiki et le consommateur
handshaker = Handshaker("https://en.wikipedia.org/w/index.php",
                        consumer_token)

# Etape 1: initialisation -- demander à  MediaWiki les clé/code secret temporaires pour l'utilisateur
redirect, request_token = handshaker.initiate()

# Etape 2: autorisation -- rediriger l'utilisateur sur MediaWiki pour confirmer l'autorisation
print("Point your browser to: %s" % redirect)  #
response_qs = input("Response query string: ")

# Etape 3: terminaison -- obtenir les clé/code secret autorisés pour le "propriétaire de la ressource"
access_token = handshaker.complete(request_token, response_qs)

# Construire un objet auth avec le consommateur et les jetons d'accès
auth1 = OAuth1(consumer_token.key,
               client_secret=consumer_token.secret,
               resource_owner_key=access_token.key,
               resource_owner_secret=access_token.secret)

# Accéder maintenant à l'API au nom de l'utilisateur
print("Reading top 10 watchlist items")
response = requests.get(
    "https://en.wikipedia.org/w/api.php",
    params={
        'action': "query",
        'list': "watchlist",
        'wllimit': 10,
        'wlprop': "title|comment",
        'format': "json"
    },
    auth=auth1
)
for item in response.json()['query']['watchlist']:
    print("{title}\t{comment}".format(**item))

Tutoriel Python Toolforge utilisant mwoauth

Voir : wikitech:Help:Toolforge/My first Flask OAuth tool

Client Go en mode ligne de commande utilisant mrjones/auth (OAuth 1.0)

Avant de commencer :

$ go get github.com/mrjones/oauth
code source Go
package main

import (
	"fmt"
	"os"
	"github.com/mrjones/oauth"
	"io/ioutil"
	"strconv"
)

func main() {

	var consumerKey string = ""
	var consumerSecret string = ""

	if len(consumerKey) == 0 || len(consumerSecret) == 0 {
		os.Exit(1)
	}

	c := oauth.NewConsumer(
		consumerKey,
		consumerSecret,
		oauth.ServiceProvider{
			RequestTokenUrl:   "http://<wiki>/wiki/index.php/Special:OAuth/initiate",
			AuthorizeTokenUrl: "http://<wiki>/wiki/index.php/Special:OAuth/authorize",
			AccessTokenUrl:    "http://<wiki>/wiki/index.php/Special:OAuth/token",
		})

	c.Debug(true)

	c.AdditionalParams = map[string]string{
		"title":   "Special:OAuth/initiate",
	}

	c.AdditionalAuthorizationUrlParams = map[string]string{
		"oauth_consumer_key": consumerKey,
	}

	requestToken, url, err := c.GetRequestTokenAndUrl("oob")
	if err != nil {
		fmt.Println( err )
	}

	fmt.Println( "Got token " + requestToken.Token )

	fmt.Println("(1) Go to: " + url)
	fmt.Println("(2) Grant access, you should get back a verification code.")
	fmt.Println("(3) Enter that verification code here: ")

	verificationCode := ""
	fmt.Scanln(&verificationCode)

	c.AdditionalParams = map[string]string{
		"title":   "Special:OAuth/token",
	}

	accessToken, err := c.AuthorizeToken(requestToken, verificationCode)
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println( "Got access token " + accessToken.Token )

	c.AdditionalParams = map[string]string{}

	response, err := c.Get(
		"http://<wiki>/wiki/api.php",
		map[string]string{
			"action": "query",
			"meta": "userinfo",
			"uiprop": "rights",
			"format": "json",
		},
		accessToken)

	if err != nil {
		fmt.Println(err)
	}

	fmt.Println( "\tResponse Status: '" + response.Status + "'\n" )
	fmt.Println( "\tResponse Code: " + strconv.Itoa(response.StatusCode) + "\n" )
	bytes, _ := ioutil.ReadAll(response.Body)
	fmt.Println( "\tResponse Body: " + string(bytes) + "\n" )

}

Applications JavaScript utilisant OAuth 2

Applications complètes utilisant OAuth

Notes

  1. Avec une clé RSA, les informations sont légèrement différentes. Il est supposé que les personnes qui choisissent d'utiliser une clé RSA savent ce qu'elles font, donc ce tutoriel supposera que vous avez choisi l'option non RSA.
  2. On l'appelle parfois le flux OAuth à trois pattes. Dans certaines circonstances, une alternative plus simple et à une étape (OAuth à une jambe) est également disponible. Voir les consommateurs exclusifs pour cela.
  3. 3.0 3.1 3.2 Suite au bogue T59500 vous devez actuellement utiliser une URL peu jolie telle que en.wikipedia.org/w/index.php?title=Special:OAuth/initiate.
  4. A cause du bogue T74186 vous devez utiliser une URL jolie ici, telle que en.wikipedia.org/wiki/Special:OAuth/authorize. Un peu gênant, nous le savons.
  5. Ce processus OAuth est quelques fois dit à trois jambes. Dans certaines circonstances une alternative plus simple en une étape (appelée OAuth à une jambe) est également disponible. Voir les consommateurs exclusifs pour cela.
  6. PKCE — Proof Key for Code Exchange
  7. Voir T254063 pour les détails.