Sécurisé son API avec des jetons

JSON Web Token (JWT) est un standard ouvert défini dans la RFC 7519. Disponible dans la plupart des langages pour l’échange sécurisé de jeton. On pourra obtenir les extensions nécessaires sur le site jwt.io.

Intro

  • modifier la doc de votre API  pour prendre en compte les codes HTTP et la gestion des tokens.

Partie 1 – Amor

Livrable gitlab : finder/mission5/slim/…

  • Ajouter JWT grâce à composer.
composer require firebase/php-jwt
  • Permettre à un utilisateur d’obtenir un jeton valable 30 minutes lors de la connexion au site grâce à l’URI /obtentionToken. On enregistrera ce jeton en session JavaScript.
  • En cas d’erreur à la connexion (login et mot de passe incorrect) le serveur renverra un code HTTP 401 Unauthorized .

Exemple de code client

 $( "#btn-valide").click(function(event) {               
               $.ajax({ 
                type: "GET",
                url: urlServeur+"/obtentionToken",
                data: "pass="+ $("#password").val(),
                success: function(data){
                      sessionStorage.setItem('token', data);                               
                },
                error: function(XMLHttpRequest, textStatus, errorThrown) {      
                        $(".form-group-password").addClass("has-danger");
                        $("#password").addClass("form-control-danger");
                }             
                });
});

Exemple de code serveur

<?php 
require 'vendor/autoload.php';
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
use \Firebase\JWT\JWT;
use Firebase\JWT\Key;
$app = new \Slim\App;
error_reporting(E_ALL);
ini_set('display_errors', 1);

$app->get('/obtentionToken', function(Request $request, Response $response){	
	//vérification de l'utilisateur
	$tb = $request->getQueryParams(); 
        $login= $tb["login"];
        $pass= $tb["pass"];	
	$allowed= ckeckUser($login,$pass);
	if($allowed){
		$token=getTokenJWT();
		return $response->withJson($token,200);
	}else{
		return $response->withStatus(401);
	}
});

$app->post('/verifToken', function(Request $request, Response $response){
        $tb = $request->getQueryParams(); 
	$token = $tb["token "];
	if(validJWT($token)){
		//J'execute la fonction
	}else{
		//non autorisé
		return $response->withStatus(401);
	}	
});

 function getTokenJWT() {
   // Make an array for the JWT Payload
  $payload = array(
    //30 min
    "exp" => time() + (60 * 30)
  );
   // encode the payload using our secretkey and return the token
  return JWT::encode($payload, "secret",'HS256');
}

  function validJWT($token) {
    $res = false;
    try {
        $decoded = JWT::decode($token, new Key($key, 'HS256'));       
    } catch (Exception $e) {
      return $res;
    }
    $res = true;
    return $res;  
  }
   
$app->run();
  • Sécuriser les routes permettant d’afficher les utilisateurs grâce à la vérification d’un jeton. On pourra s’inspirer de la route  /verifToken ci dessus.
  • Sécuriser toutes les routes permettant de modifier, ajouter ou supprimer un élément (POST, DELETE, PUT).

Partie 2 – Byzance

Livrable gitlab : finder/mission5/express/…

  • Ajouter JWT.
npm install jsonwebtoken
  • Permettre à un utilisateur d’obtenir un jeton valable 30 minutes lors de la connexion au site. On enregistrera ce jeton en session JavaScript. Documentation jsonwebtoken
var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' },'superSecret', {
          expiresIn: 1440 // expires in 24 hours
        });

        // return the information including token as JSON
        res.json({
          success: true,
          message: 'Enjoy your token!',
          token: token
        });
if (token) {
    // verifies secret and checks exp
    jwt.verify(token, 'superSecret', function(err, decoded) {      
      if (err) {
        return res.json({ success: false, message: 'Failed to authenticate token.' });    
      } else {
        // if everything is good, save to request for use in other routes
        req.decoded = decoded;    
        next();
      }
    });

  } else {
    // if there is no token
     return res.status(403).end();
  }
  • Sécuriser les routes permettant d’afficher les utilisateurs grâce à la vérification d’un jeton.
  • Sécuriser toutes les routes permettant de modifier, ajouter ou supprimer un élément.

Partie 3 – Caraïbes

Livrable gitlab : finder/mission5/flask/…

  • Ajouter JWT.
pip install pyjwt
  • Permettre à un utilisateur d’obtenir un jeton valable 30 minutes lors de la connexion au site. On enregistrera ce jeton en session JavaScript. Documentation pyjwt
>>import jwt 
>>key = 'secret' 
>>encoded = jwt.encode({'some': 'payload'}, key, algorithm='HS256') 
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9.4twFt5NiznN84AWoo1d7KO1T_yoc0Z6XOpOVswacPZg' 
>>decoded = jwt.decode(encoded, key, algorithms='HS256') 
{'some': 'payload'}





from flask import Response

  return Response("{'a':'b'}", status=201, mimetype='application/json')
  • Sécuriser les routes permettant d’afficher les utilisateurs grâce à la vérification d’un jeton.
  • Sécuriser toutes les routes permettant de modifier, ajouter ou supprimer un élément.