Web services

Construisez une API HTTP pour votre site.

Elgg fournit un framework puissant pour la création de services web. Cela permet aux développeurs d’exposer des fonctionnalités à d’autres sites Web et applications de bureau, ainsi que des intégrations avec des applications web tierces. Bien que nous appelions l’API RESTful, il s’agit en fait d’un hybride REST/RPC similaire aux API fournies par des sites comme Flickr et Twitter.

Pour créer une API pour votre site Elgg, vous devez effectuer 4 choses :

  • activer le plugin web services

  • exposer des méthodes

  • mettre en place l’API d’authentification

  • mettre en place l’authentification utilisateur

De plus, vous pouvez contrôler quels types d’authentification sont disponibles sur votre site. Cela sera également traité.

Sécurité

Il est essentiel que les services web soient utilisés via des protocoles sécurisés. N’activez pas les services web si votre site n’est pas servi par HTTPS. Ceci est particulièrement important si vous autorisez l’authentification par clef d’API uniquement.

Si vous utilisez des outils tiers qui exposent des méthodes d’API, assurez-vous d’effectuer un audit de sécurité approfondi. Vous pouvez vouloir vous assurer que l’authentification API est requise pour TOUTES les méthodes, même si elles nécessitent l’authentification de l’utilisateur. Les méthodes qui ne nécessitent pas d’authentification API peuvent être facilement utilisées pour spammer votre site.

Assurez-vous que la validité des clefs d’API est limitée et fournissez à vos clients API des mécanismes pour renouveler leurs clefs.

Exposer des méthodes

La fonction à utiliser pour exposer une méthode est elgg_ws_expose_function(). Par exemple, supposons que vous souhaitez exposer une fonction qui renvoie du texte à l’application appelante. La fonction pourrait ressembler à ceci

function my_echo($string) {
    return $string;
}

Puisque nous fournissons cette fonction pour permettre aux développeurs de tester leurs clients de l’API, nous n’aurons besoin ni d’authentification API ni d’authentification utilisateur. Cet appel enregistre la fonction avec le framework API des services web :

elgg_ws_expose_function(
        "test.echo",
        "my_echo",
        [
                "string" => [
                        'type' => 'string',
                ]
        ],
        'A testing method which echos back a string',
        'GET',
        false,
        false
);

Si vous ajoutez ce code à un plugin, puis accédez à http://votresite.com/services/api/rest/json/?method=system.api.list, vous devez maintenant voir votre méthode test.echo répertoriée comme un appel API. En outre, pour tester la méthode exposée à partir d’un navigateur web, vous pouvez accéder à l’URL: http://votresite.com/services/api/rest/json/?method=test.echo&string=testing et vous devriez voir les données JSON comme ceci :

{"status":0,"result":"testing"}

Les plugins peuvent filtrer la sortie des méthodes d’API individuelles en enregistrant un gestionnaire pour le hook plugin 'rest:output',$method.

Formats de réponse

JSON est le format par défaut, mais il est possible de récupérer du XML et du PHP sérialisé en activant le plugin data_views et en remplaçant json par xml ou php dans les URL ci-dessus.

Vous pouvez également ajouter des formats de réponse supplémentaires en définissant de nouveaux types de vues.

Paramètres

Les paramètres attendus par chaque méthode doivent être répertoriés comme un tableau associatif, où la clef représente le nom du paramètre, et la valeur contient un tableau avec des champs type, default et required.

Les valeurs soumises avec la requête auprès de d’API pour chaque paramètre doivent correspondre au type déclaré. L’API renverra une exception en cas d’échec de la validation.

Les types de paramètres reconnus sont :

  • integer (ou int)

  • boolean (ou bool)

  • string

  • float

  • array

Les types non reconnus lancent une exception d’API.

Vous pouvez utiliser des champs supplémentaires pour décrire votre paramètre, par exemple description.

elgg_ws_expose_function(
        'test.greet',
        'my_greeting',
        [
                'name' => [
                        'type' => 'string',
                        'required' => true,
                        'description' => 'Name of the person to be greeted by the API',
                ],
                'greeting' => [
                        'type' => 'string',
                        'required' => false,
                        'default' => 'Hello',
                        'description' => 'Greeting to be used, e.g. "Good day" or "Hi"',
                ],
        ],
        'A testing method which greets the user with a custom greeting',
        'GET',
        false,
        false
);

Note

Si un paramètre manquant n’a pas de valeur par défaut, l’argument sera null. Avant Elgg v2.1, un bogue provoquait le décalage vers la gauche des arguments ultérieurs dans ce cas.

Recevoir des paramètres en tant que tableau associatif

Si vous avez d’un grand nombre de paramètres de méthode, vous pouvez forcer le script d’exécution à invoquer la fonction de rappel avec un seul argument qui contient un tableau associatif de paires de paramètre => valeur (au lieu que chaque paramètre soit un argument distinct). Pour ce faire, définissez $assoc sur true dans elgg_ws_expose_function().

function greet_me($values) {
        $name = elgg_extract('name', $values);
        $greeting = elgg_extract('greeting', $values, 'Hello');
        return "$greeting, $name";
}

elgg_ws_expose_function(
        "test.greet",
        "greet_me",
        [
                "name" => [
                        'type' => 'string',
                ],
                "greeting" => [
                        'type' => 'string',
                        'default' => 'Hello',
                        'required' => false,
                ],
        ],
        'A testing method which echos a greeting',
        'GET',
        false,
        false,
        true // $assoc makes the callback receive an associative array
);

Note

Si un paramètre manquant n’a pas de valeur par défaut, null sera utilisé.

API d’authentification

Vous pouvez souhaiter contrôler l’accès à certaines des fonctions que vous exposez. Peut-être que vous exposez des fonctions afin d’intégrer Elgg avec une autre plate-forme opensource sur le même serveur. Dans ce cas, vous souhaitez seulement permettre à cette autre application d’accéder à ces méthodes. Une autre possibilité est que vous souhaitez limiter ce à quoi des développeurs externes ont accès via votre API. Ou peut-être voulez-vous limiter le nombre d’appels qu’un développeur peut passer auprès de votre API en une seule journée.

Dans tous ces cas, vous pouvez utiliser les fonctions d’authentification de l’API d’Elgg pour contrôler l’accès. Elgg fournit deux méthodes intégrées pour effectuer l’authentification auprès de l’API : la première basée sur la clef, et la signature HMAC. Vous pouvez également ajouter vos propres méthodes d’authentification. L’approche basée sur les clefs est très similaire à ce que font Google, Flickr, ou Twitter. Les développeurs peuvent demander une clef (une chaîne aléatoire) et transmettre cette clef avec tous les appels nécessitant l’authentification auprès de l’API. Les clefs sont stockées dans la base de données et si un appel API est effectué sans clef ou ave une mauvaise clef, l’appel est refusé et un message d’erreur est renvoyé.

Authentification par clef

À titre d’exemple, écrivons une fonction qui renvoie le nombre d’utilisateurs qui ont consulté le site au cours des dernières x minutes.

function count_active_users($minutes=10) {
    $seconds = 60 * $minutes;
    $count = count(find_active_users($seconds, 9999));
    return $count;
}

Maintenant, nous allons l’exposer et faire du nombre de minutes un paramètre facultatif :

elgg_ws_expose_function(
        "users.active",
        "count_active_users",
        [
                "minutes" => [
                        'type' => 'int',
                        'required' => false,
                ],
        ],
        'Number of users who have used the site in the past x minutes',
        'GET',
        true,
        false
);

Cette fonction est maintenant disponible et si vous cochez system.api.list, vous verrez qu’elle nécessite l’authentification auprès de l’API. Si vous atteignez la méthode avec un navigateur Web, elle renvoie un message d’erreur concernant l’échec de l’authentification API. Pour tester cette méthode, vous avez besoin d’une clef API. Heureusement, il existe un plugin appelé apiadmin qui crée des clefs pour vous. Il est disponible dans le répertoire des plugins de Elgg. Il renvoie une clef publique et privée et vous utiliserez la clef publique pour ce type d’authentification API. Prenez une clef, puis effectuez une demande GET avec votre navigateur sur cette méthode API en passant dans la chaîne la clef comme paramètre api_key. Cela pourrait ressembler à quelque chose comme ceci : http://votresite.com/services/api/rest/xml/?method=users.active&api_key=1140321cb56c71710c38feefdf72bc462938f59f.

Authentification par signature

Le Authentification HMAC est similaire à ce qui est utilisé avec OAuth ou le service S3 d’Amazon. Il s’agit d’utiliser à la fois clef publique et clef privée. Si vous voulez vous assurer que les appels API proviennent du développeur dont vous pensez qu’ils viennent et que vous voulez vous assurer que les données ne sont pas altérées pendant la transmission, vous devriez utiliser cette méthode d’authentification. Soyez conscient que cela demande beaucoup plus de travail et que cela pourrait décourager des développeurs quand il existe d’autres qui n’utilisent qu’une simple authentification basée sur les clefs.

Authentification utilisateur

Jusqu’à présent, vous avez permis aux développeurs d’extraire des données de votre site Elgg. Maintenant, nous allons passer à pousser des données dans Elgg. Dans ce cas, cela va être fait par un utilisateur. Par exemple vous pouvez avoir créé une application de bureau qui permet à vos utilisateurs de poster sur le fil sans aller sur le site. Vous devez exposer une méthode pour afficher sur le fil et vous devez vous assurer qu’un utilisateur ne peut pas publier à l’aide du compte de quelqu’un d’autre. Elgg fournit une approche basée sur des jetons pour l’authentification utilisateur. Cela permet à un utilisateur de soumettre son nom d’utilisateur et son mot de passe en échange d’un jeton utilisant la méthode auth.gettoken. Ce jeton peut ensuite être utilisé pendant un certain temps comme paramètre auth_token pour authentifier tous les appels à l’API, jusqu’à-ce qu’il expire. Si vous ne voulez pas que vos utilisateurs fassent confiance à leurs mots de passe pour des applications tierces, vous pouvez également étendre la capacité actuelle d’utiliser une approche comme OAuth.

Écrivons notre fonction d’affichage du fil :

function my_post_to_wire($text) {

    $text = substr($text, 0, 140);

    $access = ACCESS_PUBLIC;

    // returns guid of wire post
    return thewire_save_post($text, $access, "api");
}

Exposer cette fonction est la même chose qu’auparavant, sauf que nous avons besoin de l’authentification de l’utilisateur et nous allons faire cela via des requêtes POST plutôt que des requêtes HTTP.

elgg_ws_expose_function(
        "thewire.post",
        "my_post_to_wire",
        [
                "text" => [
                        'type' => 'string',
                ],
        ],
        'Post to the wire. 140 characters or less',
        'POST',
        true,
        true
);

Veuillez noter que vous ne pourrez pas tester cela à l’aide d’un navigateur Web comme vous l’avez fait avec les autres méthodes. Vous devez écrire du code client pour ce faire.

Créer votre propre API

Dès que vous vous sentirez à l’aise avec l’API du framework de web services Elgg, vous voudrez prendre du recul et concevoir votre API. Quel genre de données essayez-vous d’exposer ? Qui ou qu’est-ce qui seront les utilisateurs d’API ? Comment voulez-vous qu’ils aient accès aux clés d’authentification ? Comment allez-vous documenter votre API ? N’oubliez pas de jeter un œil aux API créées par les sites Web populaires 2.0 pour l’inspiration. Si vous recherchez des développeurs tiers pour créer des applications à l’aide de votre API, vous voudrez probablement fournir un ou plusieurs clients dans un langage spécifique.

Déterminer l’authentification disponible

L’API des services Web d’Elgg utilise un type d’architecture de pluggable authentication module (PAM) (module d’authentification insérable) pour gérer comment les utilisateurs et les développeurs sont authentifiés. Cela vous donne la flexibilité d’ajouter et de supprimer des modules d’authentification. Vous ne voulez pas utiliser l’authentification utilisateur par défaut PAM, mais préférez utiliser OAuth ? Vous pouvez le faire.

La première étape consiste à enregistrer une fonction de rappel pour le hook de plugin rest, init :

register_plugin_hook('rest', 'init', 'rest_plugin_setup_pams');

Ensuite, dans la fonction de rappel, vous enregistrez les PAMs que vous souhaitez utiliser :

function rest_plugin_setup_pams() {
    // user token can also be used for user authentication
    register_pam_handler('pam_auth_usertoken');

    // simple API key check
    register_pam_handler('api_auth_key', "sufficient", "api");

    // override the default pams
    return true;
}

Lors des tests, vous trouverez peut-être utile d’enregistrer le PAM pam_auth_session afin que vous puissiez facilement tester vos méthodes à partir du navigateur. Veillez à ne pas utiliser ce PAM sur un site de production, car il pourrait ouvrir vos utilisateurs à une attaque CSRF.