API OpenFlyers
Présentation
Cette page 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>// 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("
Request:\n".htmlentities($request)."
");
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</php>
OAuth2
OpenFlyers possède une API OAuth2 qu'il est possible d'utiliser. /*écrire plus en détails les avantages que ça apporte par rapport à l'ancien système, les cas d'utilisation, et*/
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 permissions à assigner à ce profil. Ces permissions 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.
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.
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é |
2. Demande de jeton d'accès
3. Accès aux ressources
Config: <javascript>{
"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"
}</javascript>
Code: <php><?php
$config = json_decode(file_get_contents('config.authcode.json'), true);
//Base URL of the client, used for redirection /*todo swap this for the more complex and more compatible option in auth middleware*/ $baseURL = 'http://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['PHP_SELF'];
//Session cookies are used to store information necessary for the authorization code flow session_start();
/**
* @param $url * @param $post * @param array $headers * @return mixed * function used to make api calls to the RS */
function apiRequest($url, $post = false, $headers = array()) {
$ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if ($post) { curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post)); }
$headers += [ 'Accept: application/json', 'User-Agent: http://127.0.0.1:8080/authorizationCode.php' ];
if (isset($_SESSION['access_token'])) { $headers[] = 'Authorization: Bearer ' . $_SESSION['access_token']; }
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
return json_decode($response, true);
}
/**
* @param string $clientID * @param string $redirectURL * @param string $authorizeURL * @throws Exception * function used to initiate the authentication code flow. */
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));
//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 = array( 'response_type' => 'code', 'client_id' => $clientID, 'redirect_uri' => $redirectURL, 'scope' => 'test_data', 'state' => $_SESSION['state'] );
//redirecting the browser to the AS authorization endpoint to obtain the authorization code
header('Location: ' . $authorizeURL . '?' . http_build_query($params));
}
/**
* @param string $baseURL */
function logout(string $baseURL): void {
unset($_SESSION['access_token']);
header('Location: ' . $baseURL);
}
function displayMenuLoggedIn(): void {
echo '
Logged In
'; echo '
<a href="?action=repos">View Repos</a>
'; echo '
<a href="?action=logout">Log Out</a>
';
}
function displayMenuLoggedOut(): void {
echo '
Not logged in
'; echo '
<a href="?action=login">Log In</a>
';
}
echo '
<a href="/">Home</a>
';
//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 '
- ';
foreach ($resources as $resource) {
echo '
- ' . $resource['name'] . ' '; } echo '
';
} 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'], array( 'grant_type' => 'authorization_code', 'client_id' => $config['client_id'], 'client_secret' => $config['client_secret'], 'redirect_uri' => $baseURL, 'code' => $_GET['code'] ));
//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); die();
} </php>
Client credentials
Config: <javascript>{
"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"
}</javascript>
Code: <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);
//Client's home URL, used for redirection. $baseURL = 'http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_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 '
Logged In
'; echo '
<a href="?action=resource">View Resource</a>
';
}
function displayMenuLoggedOut(): void {
echo '
Not logged in
'; echo '
<a href="?action=login">Log In</a>
';
}
if (!isset($_GET['action'])) {
echo '
<a href="/">Home</a>
';
//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();
} </php>
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.