Rest API in PHP e autenticazione con JWT

Mattepuffo's logo
Rest API in PHP e autenticazione con JWT

Rest API in PHP e autenticazione con JWT

JWT sta per JSON Web Tokens ed è uno standard open; viene usato soprattutto per l'autenticazione nelle web application.

In una API Rest non usiamo le sessioni lato server, ma usiamo un token per l'autenticazione e il blocco dei servizi.

JWT è supportato da molti linguaggi, ed oggi vediamo come usarlo in PHP.

Nell'articolo darò per scontato che abbiate già una tabella per gli utenti, e che sappiate come connettervi al database.

Spostatevi nella cartella del progetto e digitate questo comando:

$ composer require firebase/php-jwt

Questo insallerà la llibreria con le dipendenze; se siete su hosting condiviso dove non potete usare il comando, vi basterà installare la libreria su un server e poi copiare tutto sull'hosting.

Cominciamo con il login:

header("Access-Control-Allow-Origin: * ");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

// MIO FILE PER LA CONNESSIONE
require "../../lib/Connessione.php";
// MIO FILE PER IL LOGIN DEGLI UTENTI
require "../../lib/Utenti.php";
// RICHIAMO LIBRERIA JWT
require "../../lib/php-jwt/autoload.php";

use FirebaseJWTJWT;

$connessione = Connessione::getInstance();
$utenti = new Utenti($connessione);

$user = '';
$password = '';
$data = json_decode(file_get_contents("php://input"));
$user = $data->user;
$password = $data->password;

$resLogin = $utenti->loginApi($user, $password);

if (!$resLogin) {
    echo json_encode(
        array(
            "res" => "ko",
            "message" => "Credenziali errate"
        ));
} else {
    $secretKey = "VOSTRA_SECRETE_KEY";
    $issuerClaim = "SERVER.IT"; // SERVER NAME
    $audienceClaim = "NOME_API"; // NOME API
    $issuedatClaim = time();
    $notbeforeClaim = $issuedatClaim + 10;
    $expireClaim = $issuedatClaim + 60000; // SCADENZA IN SECONDI
    $token = array(
        "iss" => $issuerClaim,
        "aud" => $audienceClaim,
        "iat" => $issuedatClaim,
        "nbf" => $notbeforeClaim,
        "exp" => $expireClaim,
        "data" => array(
            "id" => $resLogin[0]["id"],
            "username" => $user,
        ));

    $jwt = JWT::encode($token, $secretKey);
    echo json_encode(
        array(
            "res" => "ok",
            "message" => "Login eseguito correttamente",
            "jwt" => $jwt,
            "username" => $user,
            "userid" => $resLogin[0]["id"],
            "expireAt" => $expireClaim
        ));
}

Vi posto il metodo loginApi che si trova dentro la classe Utenti:

public function loginApi($user, $pwd) {
	$cmd = 'SELECT * FROM utenti WHERE utente = ?';
	$res = $this->connessione->execQueryPrepare($cmd, array($user));
	if (password_verify($pwd, $res[0]['password'])) {
		return $res;
	} else {
		return FALSE;
	}
}

Quindi ritorna false se le credenziali sono errate, o il record trovato.

Come detto, la parte della connessione ed esecuzione query la lascio a voi; ognuno ha il suo metodo.

Ovviamente, in tutti i casi, dovete verificare se il login è avvenuto con successo o meno.

Nel caso in cui avete eseguito il login, vi verrà data in risposta una cosa del genere:

{
    "res": "ok",
    "message": "Login eseguito correttamente",
    "jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJiZW15YmFuay5pdCIsImF1ZCI6ImJhbmtfYXBpIiwiaWF0IjoxNTgyMjc0Mjk5LCJuYmYiOjE1ODIyNzQzMDksImV4cCI6MTU4MjMzNDI5OSwiZGF0YSI6eyJpZCI6IjEiLCJ1c2VybmFtZSI6Im1hdHRlIn19.vZX4JWv5joqZVyiuQx7tiLpzPLsv4fpTW6eUJyKz934",
    "username": "VOSTRO_USERNAME",
    "userid": "VOSTRO_ID_DA_DATABASE",
    "expireAt": 1582334299
}

Qui sotto un esempio di codice di richiesta protetta da token:

header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

require "../../lib/php-jwt/autoload.php";

use FirebaseJWTJWT;

$jwt = null;
$secretKey = "VOSTRA_SECRETE_KEY";

$authHeader = $_SERVER['HTTP_AUTHORIZATION'];
$arr = explode(" ", $authHeader);
$jwt = $arr[1];
$explJwt = explode(".", $jwt);

if ($jwt) {
    try {
        $decoded = JWT::decode($jwt, $secretKey, array('HS256'));
		
		// DO STUFF
    } catch (Exception $e) {
        echo json_encode(array(
            "res" => "ko",
            "message" => "Accesso negato",
            "error" => $e->getMessage()
        ));
    }
} else {
    echo json_encode(array(
        "res" => "ko",
        "message" => "Accesso negato",
        "error" => "Nessun token"
    ));
}

Per richiamare questo servizio dovete impostare due voci nell'header:

  • Content-Type -> application/json
  • Authorization -> Bearer TOKEN

Enjoy


Condividi

Commentami!