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
php jwt php-jwt token bearer json
Commentami!