PHPでfirebase/php-jwtを使ってJWT認証を実装する
JWTとは
JSON Web Token(JWT)は、Webサービス間で安全に情報をやり取りするための仕組みです。
データはJSON形式で表現され、ヘッダー、クレーム、署名というカテゴリで構成されます。
中身は暗号化されることで、安全に情報を送受信できます。
クレームは、JSON Web Signature(JWS)やJSON Web Encryption(JWE)のペイロードに含まれており、Base64でエンコードされたJSON文字列として表現されます。
JWT認証
JWTは一度発行されると、取り消しが効かないことにより、
APIなどを使った、認証の場面において使われることが多いです。
ほかでもいろんなサンプルはたくあんありますが、読みにくいことが多く困ったので、
ここではライブラリを使ったシンプルな実装例のメモです。
ライブラリは firebase/php-jwt と acodercat/php-jwk-to-pem を使います。
<?php
// JWT認証
require_once(./autoload.php);
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use CoderCat\JWKToPEM\JWKConverter;
print(auth()); // デバッグ用
function auth() {
// リクエストヘッダ取得
$headers = getallheaders();
$jwt = '';
foreach ($headers as $name => $value) {
if ($name == 'Authorization') {
$jwt = $value;
break;
}
}
if ($jwt) {
$url = 'https://...'; // 指定の公開鍵
// kidを見つける
$tks = explode('.', $jwt);
if (count($tks) != 3) {
// フォーマット不良
return false;
}
list($headb64, $bodyb64, $cryptob64) = $tks;
$jwtHeader = json_decode(JWT::urlsafeB64Decode($headb64), true);
if (empty($jwtHeader['kid'])) {
// kidがない
return false;
}
// jwkから公開鍵取得
$publicKey = '';
$jwks = file_get_contents($url);
$jwkData = json_decode($jwks, true);
foreach ($jwkData['keys'] as $jwk) {
if ($jwk['kid'] == $jwtHeader['kid']) {
$jwkConverter = new JWKConverter();
$publicKey = $jwkConverter->toPEM($jwk);
break;
}
}
if (!$publicKey) {
// 取得失敗
return false;
}
// 検証
$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
if (!decoded) {
// 検証失敗
return false;
}
// 認証OK
return true;
}
else {
// 取得失敗
return false;
}
}
?>