JSON Web Token
a.k.a JWT
JSON Web Token (JWT) is a compact, URL-safe means of representing
claims to be transferred between two parties
- Compact
Fit into HTTP header, cookie, request body parameter or URI query argument
- Self-contained
Work in Python, Go, Node.js, PHP, Ruby, Javascript, Java and Haskell
- Cross-language
Includes all the required informations about itself, including what and why
What does it look like?
// String composed of 3 parts separated by dot
aaaaaaaaa.bbbbbbbbbbbbb.cccccc
// Real world JWT
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.eyJrZXkiOiJ2YWwiLCJpYXQiOjE0MjI2MDU0NDV9
.eUiabuiKv-8PYk2AkGY4Fb5KMZeorYBLw261JPQD5lM
- Header
Anatomy
// JWT's metadata
{
"alg": "HS256", // the signature algorithm (here HMAC SHA-256)
"typ": "JWT" // the token type
}
- Claims
// JWT's claims
{
"user": "chalasr", // user-related claim (custom)
"iat": "1484246137", // issued at (standard)
"exp": "1484249737" // expiration (standard)
}
// JWT's Signature (HMAC SHA-256)
eUiabuiKv-8PYk2AkGY4Fb5KMZeorYBLw261JPQD5lM
- Signature
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 // header
.eyJrZXkiOiJ2YWwiLCJpYXQiOjE0MjI2MDU0NDV9 // claims
.eUiabuiKv-8PYk2AkGY4Fb5KMZeorYBLw261JPQD5lM // signature
Standard claims
iss (Issuer) | Who delivered the JWT |
sub (Subject) | What is the subject of the JWT |
aud (Audience) | Who can process the JWT |
exp (Expiration time) | Until when is the JWT valid |
nbf (Not before) | From when can the JWT be processed |
iat (Issued at) | When the JWT has been delivered |
jti (JWT ID) | What is the JWT unique identifier |
- defined by the RFC
- not mandatory
- recommended to use
- not relevant in all contexts
Those claims are:
Custom claims
Share information between parties that agree on using them
// Common custom claims
{
"username": "chalasr",
"roles": [
"ROLE_USER",
]
}
In PHP
- OpenSSL
- phpseclib
Crypto engines
JOSE libraries
-
spomky-labs/jose
-
lcobucci/jwt
-
namshi/jose
-
firebase/php-jwt
* JOSE: Javascript Object Signing Encryption
Creation
// jwt.php
$base64UrlEncode = function (string $json) {
return str_replace('=', '', strtr(base64_encode($json), '+/', '-_'));
};
$headers = json_encode(['typ' => 'JWT', 'alg' => 'RS256']);
$claims = json_encode(['usr' => 'chalasr', 'exp' => time() + 3600, 'iat' => time()]);
$payload = [$base64UrlEncode($headers), $base64UrlEncode($claims)];
$privateKey = openssl_get_privatekey(file_get_contents(__DIR__.'/private.pem'), 'jwt-demo');
$signature = '';
openssl_sign(implode('.', $payload), $signature, $privateKey, OPENSSL_ALGO_SHA256);
$payload[] = $base64UrlEncode($signature);
$token = implode('.', $payload);
print $token; // JWT Created :)
$ php jwt.php
> eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.eyJrZXkiOiJ2YWwiLCJpYXQiOjE0MjI2MDU0NDV9
.eUiabuiKv-8PYk2AkGY4Fb5KMZeorYBLw261JPQD5lM
Verification
// verify.php
$base64UrlDecode = function (string $encoded) {
if ($remainder = strlen($encoded) % 4) {
$encoded .= str_repeat('=', 4 - $remainder);
}
return base64_decode(strtr($encoded, '-_', '+/'));
};
$token = $argv[1];
$payload = explode('.', $token);
$headers = (array) json_decode($base64UrlDecode($payload[0]));
$claims = (array) json_decode($base64UrlDecode($payload[1]));
$signature = $base64UrlDecode($payload[2]);
$publicKey = openssl_get_publickey(file_get_contents('public.pem'));
$verified = openssl_verify($payload[0].'.'.$payload[1], $signature, $publicKey, OPENSSL_ALGO_SHA256);
if (!$verified || !isset($claims['exp']) || time() >= $claims['exp']) {
die('Invalid JWT');
}
printf('Hello %s!', $claims['usr']); // JWT Verified :)
$ php verify.php eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
.eyJrZXkiOiJ2YWwiLCJpYXQiOjE0MjI2MDU0NDV9
.eUiabuiKv-8PYk2AkGY4Fb5KMZeorYBLw261JPQD5lM
> Hello chalasr!
Signature/Encryption algorithms
- asymmetric
- symmetric
Symmetric cryptography is a cryptographic system in which both the sender and the receiver of a message share a single, common key that is used to encrypt and decrypt the message.
e.g: HS256 (HMAC)
Asymmetric cryptography is any cryptographic system that uses pairs of keys: public keys which may be disseminated widely, and private keys which are known only to the owner.
e.g: RS256 (RSA)
In Symfony
$ composer require lexik/jwt-authentication-bundle
Demonstration
Thanks!
Sources: github.com/chalasr/jwt-prez
JSON Web Token
By Robin Chalas
JSON Web Token
- 1,214