2024年5月12日日曜日

JWTヘッダのメディアタイプの大文字・小文字問題でハマった話

こんにちは、富士榮です。

id_tokenを作るときにJWTヘッダのメディアタイプ(typパラメータ)の値として'JWT'を指定すると思いますが、この値の大文字・小文字ではまった話です。

ちなみに、こんな感じでjoseのライブラリを使ってJWTを作っていたのですが、下から2行目のオプション指定のところで{ typ: 'jwt' }という形で小文字指定をしていました。

// JWSの作成
exports.generateJWS = async function(payload) {
const ks = fs.readFileSync(path.resolve(__dirname, keyStoreFile));
const keyStore = await jose.JWK.asKeyStore(ks.toString());
const [key] = keyStore.all({ use: 'sig' });
   const opt = { compact: true, jwk: key, fields: { typ: 'jwt' } };
return jose.JWS.createSign(opt, key).update(JSON.stringify(payload)).final();
}

JWTの仕様を見る限りnot case sentisiveとあるので、その後にあるレガシー実装との互換性のために常に"JWT(大文字)"を使うことを推奨という文言を舐めていました。

If present, it is RECOMMENDED that its value be "JWT" to indicate that this object is a JWT.  While media type names are not case sensitive, it is RECOMMENDED that "JWT" always be spelled using uppercase characters for compatibility with legacy implementations.

仕様)

https://datatracker.ietf.org/doc/html/rfc7519#section-5.1


ということで、MicrosoftのRPに小文字'jwt'で作ったid_tokenを投げ込むとこんな感じで怒られます。

仕方なく、コードを修正しました。

exports.generateJWS = async function(payload) {
const ks = fs.readFileSync(path.resolve(__dirname, keyStoreFile));
const keyStore = await jose.JWK.asKeyStore(ks.toString());
const [key] = keyStore.all({ use: 'sig' });
const opt = { compact: true, jwk: key, fields: { typ: 'JWT' } };
return jose.JWS.createSign(opt, key).update(JSON.stringify(payload)).final();
}


確かに軽く他社の実装(Microsoft以外だとAuth0とかGoogleとか)を見るとちゃんと大文字になってますね。

0 件のコメント: