web-dev-qa-db-ja.com

サードパーティライブラリを使用せずにPHPのJWT(JSON Web Token)。署名するには?

PHPでJSONWeb Token(JWT)を実装するためのライブラリがいくつかあります。たとえば、 php-jwt です。私は自分の非常に小さくて単純なクラスを書いていますが、標準に固執しようとしても、署名が検証に失敗する理由を理解できません ここ 。私は何時間も試していて、行き詰まっています。助けてください!

私のコードは単純です

//build the headers
$headers = ['alg'=>'HS256','typ'=>'JWT'];
$headers_encoded = base64url_encode(json_encode($headers));

//build the payload
$payload = ['sub'=>'1234567890','name'=>'John Doe', 'admin'=>true];
$payload_encoded = base64url_encode(json_encode($payload));

//build the signature
$key = 'secret';
$signature = hash_hmac('SHA256',"$headers_encoded.$payload_encoded",$key);

//build and return the token
$token = "$headers_encoded.$payload_encoded.$signature";
echo $token;

base64url_encode 関数:

function base64url_encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

ヘッダーとペイロードは 検証サイトの デフォルトのJWTと完全に一致しますが、署名が一致しないため、トークンに無効のフラグが付けられます。この標準は本当に簡単に思えますが、私の署名の何が問題になっていますか?

11
BeetleJuice

解決しました!署名自体をbase64でエンコードする必要があることに気づきませんでした。さらに、hash_hmac関数の最後のオプションパラメータを$raw_output=trueに設定する必要がありました( ドキュメント を参照してください。要するに、コードを元のコードから変更する必要がありました。

//build the signature
$key = 'secret';
$signature = hash_hmac('SHA256',"$headers_encoded.$payload_encoded",$key);

//build and return the token
$token = "$headers_encoded.$payload_encoded.$signature";

修正された:

//build the signature
$key = 'secret';
$signature = hash_hmac('SHA256',"$headers_encoded.$payload_encoded",$key,true);
$signature_encoded = base64url_encode($signature);

//build and return the token
$token = "$headers_encoded.$payload_encoded.$signature_encoded";
echo $token;
18
BeetleJuice