本文へスキップ
ecdsa.com
jose (JavaScript)JWT ライブラリ

エラーメッセージ

Key for the ES256 algorithm must be one of type CryptoKey, KeyObject, or JSON Web Key.

別の表記

  • Key for the RS256 algorithm must be one of type CryptoKey, KeyObject, or JSON Web Key.
  • Key for the HS256 algorithm must be one of type CryptoKey, KeyObject, JSON Web Key, or Uint8Array.

文中のアルゴリズムはトークンに応じて変わります(`ES256`、`RS256`、`EdDSA` など)。HMAC アルゴリズムの場合、列挙の末尾は「or Uint8Array」になります。

jose (JavaScript) — TypeError from jwtVerify / SignJWT.sign

このエラーの意味

jose に、鍵として使えない値が渡されました。最も多いのは PEM の文字列や、文字列のままのシークレットです。バージョン 4 以降の jose が受け付けるのは鍵オブジェクトだけで、WebCrypto の `CryptoKey`、Node.js の `KeyObject`、JWK オブジェクト、または(HMAC アルゴリズムの場合)`Uint8Array` です。テキスト形式の鍵は先にインポートする必要があります。jose が文字列の中身を推測することはありません。

発生する理由

修正方法

  1. 1.

    PEM の鍵を起動時に一度だけインポートする

    `importSPKI` と `importPKCS8` は、PEM テキストとその鍵を使うアルゴリズムを受け取り、すべてのリクエストで再利用できる `CryptoKey` を返します。

    js
    import { importSPKI, importPKCS8, jwtVerify } from "jose";
    
    const publicKey = await importSPKI(process.env.JWT_PUBLIC_KEY_PEM, "ES256");   // -----BEGIN PUBLIC KEY-----
    await jwtVerify(token, publicKey, { algorithms: ["ES256"] });
    
    const privateKey = await importPKCS8(process.env.JWT_PRIVATE_KEY_PEM, "ES256"); // -----BEGIN PRIVATE KEY-----
  2. 2.

    HMAC シークレットをバイト列にエンコードする

    HS256 には 32 バイト以上のランダムなシークレットを使い、`Uint8Array` として渡してください。シークレットを base64 でエンコードして保存している場合は、base64 のテキストをエンコードするのではなく、デコードしてバイト列にしてください。

    js
    import { jwtVerify } from "jose";
    
    const secret = new TextEncoder().encode(process.env.JWT_SECRET); // 32+ random bytes for HS256
    await jwtVerify(token, secret, { algorithms: ["HS256"] });
  3. 3.

    URL ではなく鍵セットで検証する

    ID プロバイダーが発行したトークンには、`createRemoteJWKSet` が返す関数を渡してください。そうすれば、jose がトークンごとに `kid` で鍵を選びます。

    js
    import { createRemoteJWKSet, jwtVerify } from "jose";
    
    const jwks = createRemoteJWKSet(new URL("https://issuer.example.com/.well-known/jwks.json"));
    await jwtVerify(token, jwks, { algorithms: ["ES256"] });

関連するエラー

署名エラーデータベースをすべて見る