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.