Implementación de como añadir JWT (JSON WebToken) una una capa de seguridad para consumir una API rest construida con el framework Slim PHP v3
¿Qué es JSON Web Token?
JSON Web Token (JWT) es un estándar abierto (RFC-7519) que define una forma compacta y autónoma de transmitir información de forma segura entre las partes como un objeto JSON. Esta información se puede verificar y confiar porque está firmada digitalmente.
Los JWT se pueden firmar usando un secreto (con algoritmo HMAC) o un público
- Compacto: debido a su tamaño, se puede enviar a través de una URL, parámetro POST o dentro de un encabezado HTTP. Además, debido a su tamaño su transmisión es rápida.
- Autocontenedor: el mismo contiene toda la información requerida sobre el origen de la petición para así evitar consultar de forma redundante la base de datos.
- Seguro: la firma del token garantiza que durante el traspaso del token entre servicios o aplicaciones no se ha alterado.
Estructura de un JWT
Se trata de una cadena de texto y consta de tres partes separadas por puntos (.):
header.payload.signature
Header
El encabezado consta de dos partes: el tipo de token y el algoritmo hash normalmente se usa el algoritmo HS256 y un token JWT.
{
"alg": "HS256",
"typ": "JWT"
}
La propiedad alg
indica el algoritmo usado para en la firma y la propiedad typ
define el tipo de token, en nuestro caso JWT.
Payload
La segunda parte del token es la carga útil, que contiene la información que que queramos añadir, el mismo (RFC-7519) define los siguientes campos para establecer:
- iss: (issuer) Identificador del proveedor de indetidad que emitió el JWT
- sub: (subjet) Identifica el objeto o usuario en nombre del cual fue emitido el JWT
- aud: (audience) Identifica la audiencia o receptores para lo que el JWT fue emitido,(web, android, ios..) Cada servicio que recibe un JWT para su validación tiene que controlar la audiencia a la que el JWT está destinado. Si el proveedor del servicio no se encuentra presente en el campo aud, entonces el JWT tiene que ser rechazado
- exp: (Expiration Time) Fecha expiración para controlar si el JWT está vencido.
- iat: (issued at) Fecha que fue emitido
- nbf: (Not before) Fecha permitida para el consumo, eL JWT no tiene que ser aceptado si se consume antes de la fecha establecida.
Signature
Una firma que nos permite verificar si el token es válido, se computa en la parte del servidor.
Para crear la parte de la firma, debe tomar el encabezado codificado, la carga útil codificada, un secreto, el algoritmo especificado en el encabezado y firmarlo.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
De esta forma, si alguien modifica el token por el camino, por ejemplo, inyectando alguna credencial o algún dato malicioso, entonces podríamos verificar que la comprobación de la firma no es correcta, por lo que no podemos confiar en el token recibido y deberíamos denegar la solicitud de recursos que nos haya realizado, ya sea para obtener datos o modificarlos.
Si lo que estamos requiriendo es que el usuario esté autenticado, deberíamos denegar esa petición, por lo que siempre que trabajemos con JWT deberíamos verificar con esa firma si el token es válido o no lo es.
Para más información dejo enlaces: Get Started with JSON Web Tokens y Qué es Json Web Token y cómo funciona
Integrar JWT en Slim PHP
Para integrar el uso de JWT en PHP usando el framework Slim, debemos integrar la siguiente extensión: PSR-7 and PSR-15 JWT Authentication Middleware
Instalación mediante composer:
$ composer require tuupola/slim-jwt-auth
Su uso
En el archivo midleware.php añadir
$app->add(new Tuupola\Middleware\JwtAuthentication([
"secret" => "supersecretkeyyoushouldnotcommittogithub",
"error" => function ($response, $arguments) {
$data["status"] = "error";
$data["message"] = $arguments["message"];
return $response
->withHeader("Content-Type", "application/json")
->getBody()->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
]));
Crear un JWT
Si deseamos crear un JWT de forma directa, tenemos a disposición la herramienta JSON Web Tokens
Para definr el contenido del payload JSON Web Token Builder
definir una clave secreta para su firma
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJXZWJzZXJ2ZWlzIiwiaWF0IjoxNjI0NTIyNTQ2LCJleHAiOjE2NTYwNTg1NDcsImF1ZCI6ImFuZHJvaWQiLCJzdWIiOiJhcHAucGFja2FnZS5uYW1lIn0.0oOSCmCPYhOvZ3Kt2OiasakgjuaGoCFuu7E8dwyUEtw
Descodificado:
{
"alg": "HS256",
"typ": "JWT"
},
{
"iss": "Webserveis",
"iat": 1624522546,
"exp": 1656058547,
"aud": "android",
"sub": "app.package.name"
}
Testear el JWT
Para testera el JWT recomiendo usar la herramienta postman, en Authorization selecionamos bearer y pegamos EL JWT