API OpenFlyers

Révision de 16 avril 2021 à 16:43 par Acoppey (discuter | contributions) (Script client : authorization code)

Aller à : navigation, rechercher

Présentation

L'objet de cette page est de décrire :

L'ancien module checkIdent.php est prévu être désactivé au 31/12/2021.

Ancien module d'identification checkIdent.php

Ce chapitre explique comment vérifier qu'un couple identifiant/mot de passe envoyé, par vos propres scripts, est conforme à la base de données d'OpenFlyers.

Le script retourne une valeur indiquant si la connexion, avec des identifiants données, a réussi et son état. Un cookie OpenFlyers est aussi retourné, permettant de gérer une session utilisateur sur votre site, en utilisant le compte utilisateur OpenFlyers de l'utilisateur connecté.

Comment ça marche

Si votre plateforme OpenFlyers se situe sur le lien https://openflyers.com/nom-plateforme/, envoyez simplement une requête POST sur le lien https://openflyers.com/nom-plateforme/checkIdent.php avec comme paramètres les variables login et rawPassword.

Attention: Le mot de passe nécessite d'être chiffré en MD5 (cf. la ligne $postData dans le script PHP).

Valeurs de retour possibles

Le script retourne un chiffre parmi les suivant :

  • 0 : OK
  • 1 : OK mais plusieurs profils disponibles. OpenFlyers sélectionne automatiquement le meilleur profil.
  • 2 : Expiré mais autorisé
  • 3 : Expiré mais autorisé, avec un profil expiré
  • 4 : Abonnement expiré, refusé
  • 5 : Mauvais identifiants, refusé
  • 6 : IP ou identifiants bloqués, refusé
  • 7 : Aucun identifiant donné, ils sont demandés
  • 8 : Authentification réussie mais avec des contrats non signés, bloquant tant qu'il reste des contrats à signer. Pour signer les contrats se connecter sur la plateforme OpenFlyers avec le compte bloqué puis signer les contrats à la connexion.
  • 9 : L'abonnement à la plateforme est périmé, le couple identifiant/mot de passe n'est pas vérifié, accès refusé

Nous vous recommandons de considérer un code de retour entre 0 et 2 comme bon et mauvais entre 3 et 8.

Attention: Vous devez filtrer les identifiants de connexion libres (sans droits) puisque pour OpenFlyers, ils correspondent à des accès autorisés !!!

JavaScript

Si vous utilisez votre propre formulaire d'authentification, utilisez la fonction javascript submit_pwd() située dans \javascript\submitPwd.js .

Exemple de code PHP

Voici un exemple de code PHP permettant d'envoyer une requête POST :

// PHP 5.6 is required
// OpenSSL 1.0.1 is required
function httpPostRequest($host, $path, $postData) {
    $result= "";
 
    $request = "POST $path HTTP/1.1\n".
    "Host: $host\n".
    (isset($referer) ? "Referer: $referer\n" : "").
    "Content-type: Application/x-www-form-urlencoded\n".
    "Content-length: ".strlen($postData)."\n".
    "Connection: close\n\n".
    $postData."\n";
 
    // Some debug informations:
    print("<pre>Request:\n".htmlentities($request)."</pre>");
 
    if ($fp = fsockopen($host, 443, $errno, $errstr, 3)) {
        // Set cryptology method
        // @link http://php.net/manual/en/function.stream-socket-enable-crypto.php
        if (!defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
            die('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT IS REQUIRED');
        }
        $cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
        // Activate encryption while authenticating
        stream_socket_enable_crypto($fp, true, $cryptoMethod);
        if (fputs($fp, $request)) {
            while(! feof($fp)) {
                $result.= fgets($fp, 128);
            }
            // Deactivate encryption once authenticating done
            stream_socket_enable_crypto($fp, false);
            fclose($fp);
            //print($result);
            return $result;
        }
    }
}
 
$postData   = 'login=jbond&rawPassword='.md5('007');
$rawContent = httpPostRequest('openflyers.com','https://openflyers.com/plateform-name/checkIdent.php',$postData);
 
list($header, $content) = explode("\r\n\r\n", $rawContent, 2);
list($byteQty, $realContent, $dummy) = explode("\r\n", $content, 3);
 
// the answer is in $realContent

OAuth2

OpenFlyers possède une API OAuth2 qu'il est possible d'utiliser.

OAuth2 est un protocole d'autorisation. Ce protocole permet à un utilisateur de donner un accès à certaines de ses données sur une application à une autre application tierce. Les principaux avantages de ce protocole comparé au partage d'identifiant et mot de passe sont les suivants :

  • Gestion des droits plus granuleuse.
  • Préservation de la confidentialité des mots de passe.
  • Possibilité pour l'utilisateur de révoquer les droits sans changer de mot de passe.
  • Possibilité pour l'utilisateur de révoquer les droits d'un ou plusieurs clients indépendamment.
  • Le changement de mot de passe ne coupe pas l'accès aux données par les clients.

Un exemple d'utilisation typique : une application tierce souhaite utiliser l'API d'un service web pour interagir avec des données de l'utilisateur. L'application tierce effectue une demande d'autorisation auprès du service. L'utilisateur s'authentifie auprès du service et approuve la demande. L'application tierce obtient un jeton et peu maintenant accèder aux données du l'utilisateur via l'API.

Un exemple d'utilisation en tant que solution SSO : quand quelqu'un se connecte à un service avec son compte Google, il donne accès à ses informations de profil Google au service tiers. Le service tiers utilise ces informations de profil comme identification, et utilise l'authentification effectuée par Google pour sa plateforme.

Préparation

Pour utiliser l'API OAuth2, il faut enregistrer un client OAuth2 auprès d'OpenFlyers. Pour ceci, il faut suivre les étapes suivantes :

  • Créer un nouveau profil. Ce profil permet de gérer les droits du client OAuth2.
    • Choisir un nom explicite, par exemple "Client oauth rapports".
  • Sélectionner les droits à assigner à ce profil. Ces droits limitent les données auxquelles le client OAuth2 a accès.
    • Sélectionner les rapports accessibles par le profil précédemment créé.
  • Créer un nouvel utilisateur. Cet utilisateur est virtuel et représente le serveur sur lequel fonctionne le client OAuth2.
    • Des identifiant et nom explicites sont recommandés (exemple : "serv1_oauth_client")


/*Work In Progress : front-end non implémenté*/

  • Créer un nouveau client OAuth2.
    • Il est recommandé de choisir un nom reconnaissable par les utilisateurs comme étant l'organisation utilisant l'API OAuth2.
    • Sélectionner le mécanisme d'autorisation utilisé par le client :
      • Pour utiliser OAuth2 comme solution SSO ou accéder à des données de l'utilisateur, choisir authorization_code.
      • Pour utiliser OAuth2 sans utilisateur ou dans un contexte d'automatisme, choisir client_credentials.
Un couple ID/passphrase est généré. La passphrase n'est communiquée qu'une seule fois. Elle doit être sauvegardée en lieu sûr et rester confidentielle.

Client OAuth2

Une fois le client configuré sur OpenFlyers, il faut un client pour communiquer avec le serveur d'autorisation et l'API.

Plusieurs bibliothèques simplifiant la création d'un client sont disponibles.

Des scripts client basiques écrits en php sont aussi fournis pour les mécanismes authorization_code et client_credentials

Authorization code

Ce flux OAuth2 se déroule en plusieurs étapes :

  • Le client redirige le navigateur de l'utilisateur vers l'URL d'autorisation.
  • Le navigateur de l'utilisateur est redirigé vers l'URL fourni durant la demande ou l'enregistrement du client.
  • Le client récupère un code d'autorisation via la redirection précédente, et échange ce code contre un jeton d'accès auprès du serveur d'autorisation.
  • Le client peut utiliser ce code d'accès :
    • Comme preuve d'authentification pour une solution SSO (Single Sign-On).
    • Pour accéder à des données sur le serveur distant en utilisant l'API.


   +-----------+                   +------+                +-----------+                  +-------------+                  +-----------+
   |Utilisateur|                   |Client|                |Navigateur |                  |   Serveur   |                  |  Serveur  |
   +-----+-----+                   +--+---+                +-----+-----+                  |Autorisation |                  | Ressources|
         |                            |                          |                        +------+------+                  +-----+-----+
         |                            |                          |                               |                               |
         |                            |                   Demande|d'autorisation                 |                               |
         |                            +------------------------->+------------------------------>|                               |
         |                            |                          |                               |                               |
         |                            |Authentification + Formulaire d'autorisation              |                               |
         |<---------------------------+--------------------------+<------------------------------+                               |
         |                            |                          |                               |                               |
         |                            |      Autorisation        |                               |                               |
         +----------------------------+------------------------->+------------------------------>|                               |
         |                            |                          |                               |                               |
         |                            |                      Code|d'autorisation                 |                               |
         |                            |<-------------------------+<------------------------------+                               |
         |                            |                          |                               |                               |
         |                            |                Demande de|token                          |                               |
         |                            +--------------------------+------------------------------>|                               |
         |                            |                          |                               |                               |
         |                            |                 Access (+|Refresh) token                 |                               |
         |                            |<-------------------------+-------------------------------+                               |
         |                            |                          |                               |                               |
         |                            |                          |       Requête vers API        |                               |
         |                            +--------------------------+-------------------------------+------------------------------>|
         |                            |                          |                               |                               |
         |                            |                          |                               |                               |
         |                            |                          |                               |<------------------------------+
         |                            |                          |                               |  Vérification d'autorisation  |
         |                            |                          |                               +------------------------------>|
         |                            |                          |                               |                               |
         |                            |                          |      Données/Réponse          |                               |
         |                            |<-------------------------+-------------------------------+-------------------------------+
         |                            |                          |                               |                               |


Générer les codes pour PKCE

Pour faire fonctionner le client OAuth2, il faut générer deux codes pour l'extension PKCE :

  • Un code_verifier échangé pendant la demande de jeton d'accès.
  • Un code_challenge dérivé du code_verifier et échangé pendant la demande d'autorisation.
Générer le code_verifier
function generateCodeVerifier($length = 128): string
{
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';
    $outputCode = '';
 
    for ($i = 0; $i < $length; $i++) {
        $index      = random_int(0, strlen($characters) - 1);
        $outputCode .= $characters[$index];
    }
 
    return $outputCode;
}

Cette fonction permet de générer un code_verifier avec une longueur donnée. Le code_verifier doit avoir une longueur entre 43 et 128 caractères.

Générer le code_challenge
function computeCodeChallenge(string $codeVerifier): string
{
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');
}

Cette fonction génère le code_challenge à partir du code_verifier fourni.


1. Demande d'autorisation

Pour initier la demande d'autorisation, rediriger le navigateur de l'utilisateur vers l'URL : GET https://openflyers.com/nom-de-plateforme/oauth/authorize.php.

Il faut également envoyer les paramètres suivants :

Nom Type Description
client_id string L'identifiant client_id reçu pendant l'enregistrement du client.
response_type string Le type de réponse envoyée par le serveur. Doit utiliser la valeur "code" (sans guillements) pour ce mécanisme.
redirect_uri string L'URL vers lequel l'utilisateur est redirigé après la demande d'autorisation.
scope string Liste des droits demandés par le client, séparés par des espaces.
state string Chaîne de caractère aléatoire utilisée pour éviter les attaques CSRF. Fortement Recommandé
code_challenge string Code nécessaire pour le fonctionnement de l'extension PKCE.
code_challenge_method string Méthode utilisée pour générer le code_challenge. Ici, la valeur est "S256".

2. Demande de jeton d'accès

Après avoir répondu à la demande, l'utilisateur est redirigé vers l'URL fourni avec la demande ou l'enregistrement du client. Si la demande est acceptée, un code temporaire : code est fourni, ainsi que le paramètre state fourni pendant la demande avec la même valeur. Si la demande est refusée, un code d'erreur est renvoyé.

Si le paramètre state a une valeur différente de celle envoyée avec la demande, c'est peut-être une tentative d'attaque et il faut refuser la réponse.

Echanger ce code contre un jeton d'accès via l'URL : POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php

Les paramètres suivants sont également nécessaires :

Nom Type Description
client_id string L'identifiant client_id reçu pendant l'enregistrement du client.
client_secret string La passphrase client_secret reçue pendant l'enregistrement du client.
code string Le code temporaire code reçu dans la réponse à la demande d'autorisation.
grant_type string Le mécanisme d'autorisation utilisé. Ici, sa valeur doit être "authorization_code" (sans guillements)
redirect_uri string L'URL de redirection fourni pendant la demande d'autorisation.
code_verifier string Le code_verifier utilisé pour générer le code_challenge de la demande d'autorisation.

Si la requête est correcte, un jeton d'accès access_token est fourni en réponse dans un objet au format json.

{
  "token_type": "Bearer",
  "expires_in": 3600,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw"
}

Script client : authorization code

Voici un exemple basique d'un client OAuth2 pour le mécanisme authorization_code.

Fichier de configuration config.authcode.json :

{
  "client_id": "",
  "client_secret": "",
  "authorize_uri": "https://openflyers.com/nom-de-plateforme/oauth/authorize.php",
  "token_uri": "https://openflyers.com/nom-de-plateforme/oauth/access_token.php",
  "resource_uri": "https://openflyers.com/nom-de-plateforme/oauth/resource.php",
  "auth_cert": "/path/to/tls/cert",
  "auth_key": "/path/to/tls/private/key",
  "sign_cert": "/path/to/signing/cert",
  "sign_key": "/path/to/signing/key"
}

Ce fichier de configuration doit si situer au même niveau que le script php dans le système de fichiers.

Script php :

<?php
 
$config            = json_decode(file_get_contents('config.authcode.json'), true);
$GLOBALS['config'] = $config;
 
//Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
$port     = ($protocol == 'https://' && $_SERVER['SERVER_PORT'] == 443)
            || ($protocol == 'http://' && $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];
 
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];
$GLOBALS['baseURL'] = $baseURL;
//Session cookies are used to store information necessary for the authorization code flow
session_start();
 
/**
 * This function is used to make api calls to the RS
 *
 * @param       $url
 * @param       $post
 * @param array $headers
 *
 * @return mixed
 */
function apiRequest($url, $post = false, $headers = array())
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, true);
 
    $method = 'get';
 
    if ($post) {
        $method   = 'post';
        $postData = http_build_query($post);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
 
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));
    }
 
    $urlComponents = parse_url($url);
 
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];
    $headersToSign['Host']             = $urlComponents['host'];
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');
 
    // generating the signature header
    $keyId                = str_replace("\n", '', file_get_contents($GLOBALS['config']['sign_cert']));
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);
 
    $headers['Accept']     = 'application/json';
    $headers['User-Agent'] = $GLOBALS['baseURL'];
    unset($headersToSign['(request-target)']);
    $headers               += $headersToSign;
 
    if (isset($_SESSION['access_token'])) {
        $headers['Authorization'] = 'Bearer ' . $_SESSION['access_token'];
    }
 
    // formatting the headers
    $httpFormattedHeaders = [];
    foreach ($headers as $key => $value) {
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);
    }
 
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
 
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
    curl_setopt($ch, CURLOPT_SSLCERT, file_get_contents($GLOBALS['config']['auth_cert']));
    curl_setopt($ch, CURLOPT_SSLKEY, file_get_contents($GLOBALS['config']['auth_key']));
 
    $response = curl_exec($ch);
 
    list($responseHeaders, $responseBody) = explode("\r\n\r\n", $response, 2);
 
    return json_decode($responseBody, true);
}
 
/**
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key
 *
 * @param array  $headersToSign the headers to sign, in the $key => $value format
 * @param string $certificate   the certificate linked to the used private key
 * @param string $privateKey    the private key used to sign the headers
 *
 * @return string the full signature header line
 */
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string
{
    // generating the signing string and header list
    $headers         = '';
    $signatureString = '';
    foreach ($headersToSign as $key => $value) {
        $normalizedHeaderKey = trim(strtolower($key));
        $headers             .= $normalizedHeaderKey . ' ';
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . "\n";
    }
    $headers         = trim($headers);
    $signatureString = trim($signatureString);
 
    // signing the signing string
    $signature = '';
    openssl_sign($signatureString, $signature, $privateKey, 'RSA-SHA256');
    $signature = base64_encode($signature);
 
    // compiling the header line
    return "keyId=\"$certificate\",algorithm=\"rsa-sha256\",headers=\"$headers\",signature=\"$signature\"";
}
 
/**
 * This function takes a code_verifier and outputs the corresponding code_challenge
 *
 * @param string $codeVerifier the generated code_verifier
 *
 * @return string the computed code_challenge
 */
function computeCodeChallenge(string $codeVerifier): string
{
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');
}
 
/**
 * This function takes an optional string length and outputs a random code_verifier string
 *
 * @param int $length the length of the output code_verifier. Default = 128
 *
 * @return string the code_verifier
 * @throws Exception
 */
function generateCodeVerifier($length = 128): string
{
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';
    $outputCode = '';
 
    for ($i = 0; $i < $length; $i++) {
        $index      = random_int(0, strlen($characters) - 1);
        $outputCode .= $characters[$index];
    }
 
    return $outputCode;
}
 
/**
 * This function calculates the entropy of a given string
 *
 * @param string $string  the string for which to calculate the entropy
 * @param string $charset a string with all the usable characters. Default = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~
 *
 * @return float|int
 */
function computeEntropy(string $string, string $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~')
{
    $chars = str_split($charset);
    $probs = [];
 
    foreach ($chars as $char) {
        $probs[$char] = floatval(substr_count($string, $char)) / strlen($string);
    }
 
    $sum = 0.0;
    foreach ($probs as $prob) {
        $sum += $prob != 0 ? $prob * log($prob, 2) : 0.0;
    }
 
    return -$sum;
}
 
/**
 * This function calculates the ideal (maximum) entropy for a string of a given length
 *
 * @param int $length length of the string. Default = 128
 *
 * @return float|int
 */
function idealEntropy(int $length = 128)
{
    $prob = 1.0 / $length;
 
    return -1.0 * $length * $prob * log($prob, 2);
}
 
/**
 * This function is used to initiate the authentication code flow.
 *
 * @param string $clientID     the client's ID
 * @param string $redirectURL  the URL where to redirect after auth
 * @param string $authorizeURL the target URL to request authorization
 *
 * @throws Exception
 */
function login(string $clientID, string $redirectURL, string $authorizeURL): void
{
    unset($_SESSION['access_token']);
 
//This unguessable string is used to prevent csrf attacks
    $_SESSION['state'] = bin2hex(random_bytes(16));
 
//Generate code_verifier and code_challenge for PKCE    
    $_SESSION['code_verifier']  = generateCodeVerifier();
    $_SESSION['code_challenge'] = computeCodeChallenge($_SESSION['code_verifier']);
 
//required parameters for the redirection, redirect_uri is where the browser should be redirected
// when the user grants (or denies) access, scope are the authorizations (rights) requested
    $params = [
        'response_type'         => 'code',
        'client_id'             => $clientID,
        'redirect_uri'          => $redirectURL,
        'scope'                 => 'test_data',
        'state'                 => $_SESSION['state'],
        'code_challenge'        => $_SESSION['code_challenge'],
        'code_challenge_method' => 'S256'
    ];
 
//redirecting the browser to the AS authorization endpoint to obtain the authorization code
    header('Location: ' . $authorizeURL . '?' . http_build_query($params));
}
 
/**
 * This function deletes the access token from the session
 *
 * @param string $baseURL
 */
function logout(string $baseURL): void
{
    unset($_SESSION['access_token']);
 
    header('Location: ' . $baseURL);
}
 
function displayMenuLoggedIn(): void
{
    echo '<h3>Logged In</h3>';
    echo '<p><a href="?action=repos">View Repos</a></p>';
    echo '<p><a href="?action=logout">Log Out</a></p>';
}
 
function displayMenuLoggedOut(): void
{
    echo '<h3>Not logged in</h3>';
    echo '<p><a href="?action=login">Log In</a></p>';
}
 
echo '<h2><a href="/">Home</a></h2>';
 
//display client "home" page
if (!isset($_GET['action'])) {
    if (!empty($_SESSION['access_token'])) {
        displayMenuLoggedIn();
    } else {
        displayMenuLoggedOut();
    }
}
 
if (isset($_GET['action'])) {
    switch ($_GET['action']) {
        case 'login':
            login($config['client_id'], $baseURL, $config['authorize_uri']);
            break;
        case 'logout':
            logout($baseURL);
            break;
        case 'repos':
            //call to the RS
            $resources = apiRequest($config['resource_uri'] . 'resource');
            echo json_encode($resources);
            echo '<ul>';
            foreach ($resources as $resource) {
                echo '<li>' . $resource['name'] . '</li>';
            }
            echo '</ul>';
    }
    die();
}
 
//Once the browser has been redirected to the AS to ask for the user's authorization, assuming it has been granted,
// the browser will get back here with a "code" parameter in the query string
if (isset($_GET['code'])) {
//The AS MUST redirect the browser here with the exact same state parameter we sent it before, so we check if it is indeed the same
// to detect if the oauth flow has been tampered with
    if (!isset($_GET['state']) || $_SESSION['state'] != $_GET['state']) {
        header('Location: ' . $baseURL . '?error=invalid_state');
        die();
    }
 
//We communicate directly with the AS to exchange the code received against an access token.
// The id/secret pair is send to authenticate the client, the redirect_uri is sent to verify the code's validity
    $token = apiRequest(
        $config['token_uri'],
        [
            'grant_type'    => 'authorization_code',
            'client_id'     => $config['client_id'],
            'client_secret' => empty($config['client_secret']) ? null : $config['client_secret'],
            'redirect_uri'  => $baseURL,
            'code'          => $_GET['code'],
            'code_verifier' => $_SESSION['code_verifier']
        ]
    );
 
//We store the access token in the session so the user is "connected"
    $_SESSION['access_token'] = $token['access_token'];
 
//We redirect the user's browser to the "home" page
    header('Location: ' . $baseURL);
}
 
Ce script n'est qu'un exemple basique conçu pour montrer le fonctionnement du mécanisme et tester l'implémentation d'un serveur, il n'a pas été testé extensivement. Il est conseillé d'utiliser une solution qui a fait ses preuves dans un environnement de production.

Client credentials

Ce mécanisme d'autorisation est adapté pour l'automatisation. Il se déroule comme suivant :

  • Le client effectue la demande de jeton d'accès au serveur d'autorisation en fournissant ses identifiants.
  • Le serveur authentifie le client avec les identifiants fournis et renvoie un jeton d'accès.
  • Le client utilise ce jeton d'accès pour accéder à des données via l'API.


   +------+                       +-------------+                  +-----------+
   |Client|                       |   Serveur   |                  |  Serveur  |
   +--+---+                       |Autorisation |                  | Ressources|
      |                           +------+------+                  +-----+-----+
      |        Authentification          |                               |
      |         + Demande token          |                               |
      +--------------------------------->|                               |
      |                                  |                               |
      |    Access (+ Refresh) token      |                               |
      |<---------------------------------+                               |
      |                                  |                               |
      |                      Requête vers|API                            |
      +----------------------------------+------------------------------>|
      |                                  |                               |
      |                                  |                               |
      |                                  |<------------------------------+
      |                                  |  Vérification d'autorisation  |
      |                                  +------------------------------>|
      |                                  |                               |
      |                         Données /|Réponse                        |
      |<---------------------------------+-------------------------------+
      |                                  |                               |


Demande de jeton d'accès

Pour obtenir un jeton d'accès, il faut effectuer la requête suivante : POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php

Les paramètres suivants sont nécessaires :

Nom Type Description
client_id string L'identifiant client_id reçu pendant l'enregistrement du client.
client_secret string La passphrase client_secret reçue pendant l'enregistrement du client.
grant_type string Le mécanisme d'autorisation utilisé. Ici, la valeur doit être "client_credentials" (sans guillements).
scope string Liste des droits demandés par le client, séparé par des espaces.

Si la requête est correcte, un jeton d'accès access_token est fourni en réponse dans un objet au format json.

{
  "token_type": "Bearer",
  "expires_in": 3600,
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw"
}

Script client : client credentials

Voici un exemple basique d'un client OAuth2 pour le mécanisme authorization_code.

Fichier de configuration config.clientcred.json :

{
  "client_id": "",
  "client_secret": "",
  "token_uri": "https://openflyers.com/nom-de-plateforme/oauth/access_token.php",
  "resource_uri": "https://openflyers.com/nom-de-plateforme/oauth/resource.php"
}

Ce fichier de configuration doit si situer au même niveau que le script php dans le système de fichiers.

Script php :

<?php
//Import client configuration. This configuration stores the client's ID and secret (passphrase), as well as the remote 
// server's access_token and resource endpoints, used to get the required credentials and access resources.
$config = json_decode(file_get_contents('config.clientcred.json'), true);
 
//Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
$port = ($protocol == 'https://' && $_SERVER['SERVER_PORT'] == 443)
        || ($protocol == 'http://' && $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];
 
$baseURL = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];
 
/*------------------------------------------/WARNING/--------------------------------------------*/
// Because in our specific case, this test code is accessed as a web resource with a web browser,
// the access token is stored in session cookies. This is not usually the case as this particular
// oauth flow is meant to be automated and used by the client itself, without any end-user.
// The communication between the client, AS and resource server (RS), however, is the same.
session_start();
 
 
function login($url, $id, $secret) {
    unset($_SESSION['access_token']);
 
//Curl request section, more details in resourceServer/index.php
    $curlRequest = curl_init($url);
 
    curl_setopt($curlRequest, CURLOPT_RETURNTRANSFER, true);
 
    //Setting necessary POST parameters
    curl_setopt($curlRequest, CURLOPT_POSTFIELDS, http_build_query([
        'grant_type' => 'client_credentials',
        'scope' => 'test',
        'client_id' => $id,
        'client_secret' => $secret
    ]));
//Setting necessary headers
    $headers = [
        'accept: application/json',
        'cache-control: no-cache',
        'content-type: application/x-www-form-urlencoded'
    ];
 
    curl_setopt($curlRequest, CURLOPT_HTTPHEADER, $headers);
 
//Executing the request and returning the response as a php array
    return json_decode(curl_exec($curlRequest), true);
}
 
function displayMenuLoggedIn(): void
{
    echo '<h3>Logged In</h3>';
    echo '<p><a href="?action=resource">View Resource</a></p>';
}
 
function displayMenuLoggedOut(): void
{
    echo '<h3>Not logged in</h3>';
    echo '<p><a href="?action=login">Log In</a></p>';
}
 
 
if (!isset($_GET['action'])) {
    echo '<h2><a href="/">Home</a></h2>';
//if 'access_token' is set, the client is "logged in"
    if (!empty($_SESSION['access_token'])) {
        displayMenuLoggedIn();
    } else {
        displayMenuLoggedOut();
    }
}
 
if (isset($_GET['action'])) {
    switch ($_GET['action']) {
        case 'login':
            $token = login($config['token_uri'], $config['client_id'], $config['client_secret']);
            $_SESSION['access_token'] = $token['access_token'];
//The location header is used for redirections
            header('Location: '.$baseURL);
            break;
        case 'resource':
//Making request to resource server
            $resourceRequest = curl_init($config['resource_uri'] . '?resource=test');
            curl_setopt($resourceRequest, CURLOPT_RETURNTRANSFER, true);
 
            curl_setopt($resourceRequest, CURLOPT_HTTPHEADER, [
                'Accept: application/json',
                'Authorization: Bearer '.$_SESSION['access_token'],
                'ID: '.base64_encode($config['client_id'].':'.$config['client_secret'])
            ]);
 
            $resourceResponse = curl_exec($resourceRequest);
            header('content-type: application/json');
            echo $resourceResponse;
            break;
    }
    die();
}
 
Ce script n'est qu'un exemple basique conçu pour montrer le fonctionnement du mécanisme et tester l'implémentation d'un serveur, il n'a pas été testé extensivement. Il est conseillé d'utiliser une solution qui a fait ses preuves dans un environnement de production.

Utiliser l'API

Une fois un jeton d'accès obtenu, les données sont accédées en exécutant des requêtes sur l'URL : https://openflyer.com/nom-de-plateforme/oauth/resource.php

Le jeton d'accès doit être renseigné dans le header Authorization avec le format suivant : Authorization: Bearer <access_token>

Plugin d'authentification Joomla

Si vous avez un site Joomla et que vous désirer de permettre aux utilisateurs OpenFlyers de se connecter à votre espace restreint Joomla, vous devriez ajouter ce plugin de manière à avoir une unique base de données de comptes utilisateurs : celle d'OpenFlyers.

Vous n'avez pas besoin de mettre à jour votre base de données Joomla, ce plugin interroge directement OpenFlyers grâce au script PHP CheckIdent.php.