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’authentification de l’API

  • mettre en place l’authentification utilisateur

De plus, vous pourriez vouloir 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

Les méthodes API peuvent être exposées de l’une des deux manières : - en utilisant la section web_services dans le fichier elgg-plugin.php de votre plugin - ou lors de l’événement 'register', 'api_methods'

À titre d’exemple, supposons que vous souhaitiez 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 d’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 :

// as part of the elgg-plugin.php
'web_services' => [
    'test.echo' => [
        'GET' => [ // the HTTP call method (GET|POST)
            'callback' => 'my_echo', // required
            'description' => 'A testing method which echos back a string', // optional, the description of the API method
            'params' => [ // optional, input parameters for the API method
                'string' => ['type' => 'string'],
            ],
            'require_api_auth' => false, // optional, requires API authentication (default: false)
            'require_user_auth' => false, // optional, requires User authentication (default: false)
            'associative' => false, // optional, provide the input params as an array to the callback function (default: false)
        ],
    ],
],

// as part of the 'register', 'api_methods' event
function my_plugin_event_handler(\Elgg\Event $event) {
    $results = $event->getValue();

    $results['test.echo']['GET'] = [
        'callback' => 'my_echo',
        'description' => 'A testing method which echos back a string',
        'params' => [
            'string' => ['type' => 'string'],
        ],
    ];

    return $results;
}

Note

Si aucune description n’est fournie dans la définition de la méthode API, le système vérifiera l’existence de la clé de langage web_services:api_methods:<method>:<http call method>:description

Si vous ajoutez ce code à un plugin puis allez sur http://yoursite.com/services/api/rest/json/?method=system.api.list, vous devriez maintenant voir votre méthode test.echo répertoriée comme un appel API. De plus, pour tester la méthode exposée à partir d’un navigateur Web, vous pouvez accéder à l’URL : http://yoursite.com/services/api/rest/json/?method=test.echo&string=testing et vous devriez voir des données JSON comme celles-ci :

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

Les plugins peuvent filtrer la sortie de méthodes API individuelles en enregistrant un gestionnaire pour l’événement '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 les champs type, default et required.

Les valeurs soumises pour chaque paramètre de la requête API devraient correspondre au type déclaré. L’API renverra une exception si la validation échoue.

Les types de paramètres reconnus sont :

  • integer (ou int)

  • boolean (ou bool) 'false', 0 et '0' seront évalués comme false, le reste sera évalué comme true

  • 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.

// as part of the elgg-plugin.php
'web_services' => [
    'test.greet' => [
        'GET' => [
            'callback' => 'my_greeting',
            'description' => 'A testing method which greets the user with a custom greeting',
            'params' => [
                '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"',
                ],
            ],
        ],
    ],
],

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 sous forme de tableau associatif

Si vous avez 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";
    }

// as part of the elgg-plugin.php
'web_services' => [
    'test.greet' => [
        'GET' => [
            'callback' => 'greet_me',
            'description' => 'A testing method which echos a greeting',
            'params' => [
                'name' => [
                    'type' => 'string',
                ],
                'greeting' => [
                    'type' => 'string',
                    'required' => false,
                    'default' => 'Hello',
                ],
            ],
            'associative' => true,
        ],
    ],
],

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 de 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 avec une mauvaise clef, l’appel est refusé et un message d’erreur est renvoyé.

Authentification par clef

A titre d’exemple, écrivons une fonction qui renvoie le nombre d’utilisateurs qui se sont inscrits sur votre site depuis un certain horodatage.

function count_new_users(int $since) {
    return elgg_count_entities([
        'type' => 'user',
        'created_since' => $since,
    ]);
}

Maintenant, exposons-le et faisons du nombre de minutes un paramètre obligatoire :

    // as part of the elgg-plugin.php
'web_services' => [
    'users.new' => [
        'GET' => [
            'callback' => 'count_new_users',
            'description' => 'Number of users who have used the site in the past x minutes',
            'params' => [
               'since' => [
                    'type' => 'int',
                    'required' => true,
                ],
            ],
            'require_api_auth' => true,
        ],
    ],
],

Cette fonction est maintenant disponible, et si vous cochez system.api.list, vous verrez qu’elle nécessite l’authentification API. Si vous testez la méthode avec un navigateur Web, cela renvoie un message d’erreur concernant l’échec de l’authentification API. Pour tester cette méthode, vous avez besoin d’une clef API. À partir de Elgg 3.2 les clefs API peuvent être générées par le plugin webservices. Il permet de créer une clef publique et privée, et vous devrez utiliser la clef publique pour ce type d’authentification API. Prenez une clef, puis effectuez une requête GET avec votre navigateur sur cette méthode d’API en passant dans la chaîne de paramètre la clef api_key. Cela pourrait ressembler à quelque chose comme ceci: http://yoursite.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 une clef publique et une clef privée. Si vous voulez vous assurer que les appels à l’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 sites 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 comment 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 allez devoir exposer une méthode pour afficher sur le fil et 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 afin d’obtenir en échange un jeton, en 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 de publication sur le Fil :

function my_post_to_wire($text) {

    $text = elgg_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 que nous allons faire cela via des requêtes POST plutôt que des requêtes HTTP.

    // as part of the elgg-plugin.php
'web_services' => [
    'thewire.post' => [
        'POST' => [
            'callback' => 'my_post_to_wire',
            'description' => 'Post to the wire. 140 characters or less',
            'params' => [
               'text' => [
                    'type' => 'string',
                ],
            ],
            'require_api_auth' => true,
            'require_user_auth' => true,
        ],
    ],
],

Veuillez noter que vous ne pourrez pas tester ceci à 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 le framework d’API des web services de Elgg, vous voudrez prendre du recul et concevoir votre API. Quel type de données essayez-vous d’exposer ? Qui ou qu’est-ce qui seront les utilisateurs de l’API ? Comment voulez-vous qu’ils aient accès aux clef 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 attendez que des développeurs tiers créent 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 de Elgg utilise un type d’architecture de module d’authentification enfichable « pluggable authentication module (PAM) » pour gérer la manière dont 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 le PAM gestionnaire d’authentification utilisateur par défaut, mais préférez utiliser OAuth ? Vous pouvez le faire.

La première étape consiste à enregistrer une fonction de rappel pour l’événement 'rest', 'init' :

elgg_register_event_handler('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
    elgg_register_pam_handler(\Elgg\WebServices\PAM\UserToken::class);

    // simple API key check
    elgg_register_pam_handler(\Elgg\WebServices\PAM\APIKey::class, 'sufficient', 'api');
}