jose vs jsonwebtoken vs jwa vs jws vs node-jose
Node.js 環境における JWT と JWS/JWE の実装戦略とライブラリ選定
josejsonwebtokenjwajwsnode-jose類似パッケージ:

Node.js 環境における JWT と JWS/JWE の実装戦略とライブラリ選定

josejsonwebtokenjwajwsnode-jose は、すべて JSON Web Token (JWT) や関連する暗号規格(JWS, JWE, JWK)を扱うための Node.js ライブラリですが、その役割と設計思想は大きく異なります。

jsonwebtoken は長年デファクトスタンダードとして使われてきた高レベルなライブラリで、JWT の署名と検証を単純な API で提供します。一方、jose はモダンな設計で、ブラウザと Node.js の両方で動作し、JWT だけでなく JWE(暗号化)や JWK(鍵管理)も包括的にサポートする次世代の標準です。

jwsjwa は、より低レベルな処理に特化しています。jws は JWT の署名部分のみを扱い、jwa はアルゴリズムの識別子変換など基礎的な utilities を提供します。これらは通常、独自の実装が必要な場合に使用されます。

node-jose はかつて JWE サポートで重要でしたが、現在はメンテナンスが停滞しており、新しいプロジェクトでの使用は推奨されません。現代の開発では、セキュリティと将来性を考慮し jose への移行が強く推奨されています。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
jose07,759248 kB06日前MIT
jsonwebtoken018,19043.4 kB2089ヶ月前MIT
jwa010314.1 kB181年前MIT
jws072118.8 kB339ヶ月前MIT
node-jose0721353 kB734年前Apache-2.0

JWT ライブラリ完全比較:jose, jsonwebtoken, jws, jwa, node-jose の実装と選定

Node.js で認証システムを構築する際、JSON Web Token (JWT) の扱いは避けて通れません。しかし、npm には類似した名前のパッケージが乱立しており、どれを選べばよいのか迷う開発者は少なくありません。

ここでは、josejsonwebtokenjwsjwanode-jose の 5 つを徹底比較します。単なる機能リストではなく、実際のコードがどう変わるか、セキュリティ面で何が違うかに焦点を当てて解説します。

🏗️ アーキテクチャの根本的な違い:高レベル vs 低レベル

まず理解すべきは、これらのライブラリが「どのレベル」の抽象化を提供しているかです。

jsonwebtokenjose は「高レベル」ライブラリです。これらは、署名の生成、トークンの検証、有効期限のチェックまでをワンステップで処理します。

一方、jwsjwa は「低レベル」な部品です。jws は署名の作成のみを行い、有効期限のチェックなどは行いません。jwa に至っては、アルゴリズム名の文字列操作などが主な役割です。

node-jose はかつて高レベルな選択肢でしたが、現在は時代遅れとなっています。

🔐 基本的な JWT の署名と検証

最も一般的なユースケースである「トークンの発行」と「検証」を、主要な 2 つの高レベルライブラリで比較します。

jsonwebtoken の実装

長年使われてきたこのライブラリは、API が非常にシンプルです。秘密鍵を渡すだけで署名付きトークンが生成できます。

const jwt = require('jsonwebtoken');

const secret = 'my-secret-key';

// 署名 (Sign)
const token = jwt.sign(
  { userId: 123, role: 'admin' },
  secret,
  { expiresIn: '1h' }
);

// 検証 (Verify)
try {
  const decoded = jwt.verify(token, secret);
  console.log(decoded.userId); // 123
} catch (err) {
  console.error('Invalid token');
}

jose の実装

jose はより明示的で、モダンな Promise ベースの API を採用しています。鍵の扱いも厳格で、セキュリティ上のミスが減りやすい設計です。

import { SignJWT, jwtVerify } from 'jose';
import { textEncoder } from 'jose/util';

const secret = new TextEncoder().encode('my-secret-key');

// 署名 (Sign)
const token = await new SignJWT({ userId: 123, role: 'admin' })
  .setProtectedHeader({ alg: 'HS256' })
  .setExpirationTime('1h')
  .sign(secret);

// 検証 (Verify)
try {
  const { payload } = await jwtVerify(token, secret);
  console.log(payload.userId); // 123
} catch (err) {
  console.error('Invalid token');
}

比較のポイント: jsonwebtoken は同期処理のように見えますが、内部で暗号化処理を行っています。jose は非同期処理であることを明確にし、アルゴリズムをヘッダーで明示的に指定させることで、アルゴリズム混在攻撃(Algorithm Confusion Attack)を防ぐ設計になっています。

🔒 低レベルライブラリの役割:jws と jwa

なぜ jwsjwa といったライブラリが存在するのでしょうか?それは、JWT の仕組みを完全にコントロールしたい場合や、独自のプロトコルを構築する必要がある場合です。

jws の実装

jws は、JWT の「署名部分」のみを作成・検証します。ペイロードの中身や有効期限(exp)のチェックは行いません。

const jws = require('jws');

// 署名の作成
const signature = jws.sign({
  header: { alg: 'HS256' },
  payload: { userId: 123 },
  secret: 'my-secret-key'
});

// 署名の検証(中身のチェックはしない)
const isValid = jws.verify(signature, 'HS256', 'my-secret-key');

if (isValid) {
  const decoded = jws.decode(signature); // ペイロードを取り出すだけ
  console.log(decoded.payload);
}

このように、jws を使うと「有効期限が切れていても署名が合っていれば true を返す」ため、認証ロジックを自分で全て書く必要があります。通常のプロダクションコードでは、このライブラリを直接使用することは稀です。

jwa の実装

jwa は、アルゴリズム名の正規化など、極めて基礎的な処理を行います。例えば、RS256rsa-sha2-256 のような表記ゆれを吸収する際などに使われます。

const jwa = require('jwa');

// アルゴリズムエイリアスの解決
const algo = jwa('RS256');
console.log(algo.algorithm); // 'RS256'

// 通常、開発者が直接呼び出す機会はほとんどありません
// 他のライブラリ内部で使用されることが多いです

📦 暗号化トークン (JWE) の扱い

JWT には、署名だけでなく「暗号化」されたタイプ(JWE)があります。機密情報をトークン自体に含めたい場合に必要です。

node-jose の現状と限界

かつて node-jose は、Node.js で JWE を扱うための数少ない選択肢でした。

// 【非推奨】node-jose の例
const jose = require('node-jose');

// 鍵の準備と暗号化
jose.JWK.createKeyStore().then((keystore) => {
  return keystore.generate('oct', 256).then((key) => {
    return jose.JWE.createEncrypt({ format: 'compact' }, key)
      .update(JSON.stringify({ data: 'secret' }))
      .final();
  });
});

しかし、このライブラリは更新が止まっており、セキュリティのパッチも適用されていません。新しいプロジェクトで node-jose を選ぶべきではありません。

jose による JWE 実装

現代の正解は jose です。JWE の作成も JWT と同様にモダンな API で処理できます。

import { CompactEncrypt } from 'jose';
import { generateSecret } from 'jose/util';

// 対称鍵の生成
const secret = await generateSecret('A256GCM');

// 暗号化 (Encrypt)
const encryptedToken = await new CompactEncrypt(
  new TextEncoder().encode(JSON.stringify({ data: 'secret' }))
)
  .setProtectedHeader({ alg: 'dir', enc: 'A256GCM' })
  .encrypt(secret);

console.log(encryptedToken);
// 結果は JWE 形式の文字列になります

jose は JWE だけでなく、JWK(JSON Web Key)のインポート・エクスポートも容易に扱えるため、鍵管理システムとの連携もスムーズです。

🌐 環境対応:Node.js とブラウザ

アーキテクチャを決定する際、どこでコードを動かすかは重要です。

ライブラリNode.jsブラウザ備考
jose単一コードベースで両方対応可能
jsonwebtokenNode.js の crypto モジュールに依存
jws⚠️ブラウザではポリフィルが必要
jwa⚠️同上
node-jose非推奨

jsonwebtoken は Node.js 固有の機能を使っているため、ブラウザ(React や Vue のフロントエンドコード内など)で動かすことはできません。一方、jose は Web Crypto API を活用しているため、サーバーとクライアントで同じライブラリを共有できます。

⚠️ セキュリティとメンテナンス状況

選択を誤ると、セキュリティリスクに直結します。

  1. node-jose: メンテナンス終了。既知の脆弱性が放置されている可能性があります。即刻移行を検討してください。
  2. jsonwebtoken: 広く使われていますが、機能追加はほぼ停止しており、バグフィックス中心のメンテナンスモードです。アルゴリズムの指定を怠るとセキュリティホールになる過去の実装方針でした。
  3. jose: 現在最もアクティブに開発されており、最新の仕様を追従しています。デフォルトで安全な設定が多く、誤用を防ぐ設計になっています。

💡 実戦的な選定ガイド

実際のプロジェクトでは、以下のように判断するのが賢明です。

シナリオ A: 新規の認証システム構築

jose 一択です。 ブラウザとサーバーでコードを共有でき、JWE への拡張も容易です。将来のセキュリティ要件の変化にも柔軟に対応できます。

シナリオ B: 既存システムの保守

jsonwebtoken のまま維持するか、段階的に jose へ移行。 すぐに書き換える必要はありませんが、新規機能追加時には jose を導入し、徐々に置き換えるのが現実的です。

シナリオ C: 独自のトークンフォーマット開発

jws を検討。 標準的な JWT のルールに縛られず、ヘッダーやペイロードの構造を完全にカスタマイズする場合のみ使用します。

📊 機能比較サマリー

機能josejsonwebtokenjwsnode-jose
JWT 署名・検証⚠️ (署名のみ)
JWE (暗号化)
ブラウザ対応⚠️
Promise 対応✅ (Native)❌ (Callback/Promise)
メンテナンス🟢 活発🟡 保守のみ🟡 保守のみ🔴 終了
推奨度⭐⭐⭐⭐⭐⭐⭐

🎯 結論

迷ったら jose を使ってください。それは単に「新しいから」ではなく、セキュリティ設計が現代的であり、ブラウザ環境も含めた幅広いユースケースをカバーしているからです。

jsonwebtoken は過去の資産として尊重しつつ、node-jose は過去のものとしてアーカイブに送る。これが、2024 年以降の Node.js エコシステムにおける正しい立ち位置です。低レベルな jwsjwa は、本当に必要な時が来るまで、その存在を頭の片隅に置いておくだけで十分でしょう。

選び方: jose vs jsonwebtoken vs jwa vs jws vs node-jose

  • jose:

    新しいプロジェクトでは常に jose を選定すべきです。このライブラリは Node.js とブラウザの両方で動作し、JWT だけでなく JWE(暗号化)や JWK の操作もサポートしています。依存関係が少なく、モダンな Promise ベースの API を提供するため、セキュリティ要件が高く将来の拡張性を考慮する場合に最適です。

  • jsonwebtoken:

    既存のレガシーコードベースを維持する場合や、極めて単純な JWT 署名・検証のみが必要な場合は jsonwebtoken が適しています。ただし、JWE への対応がなく、メンテナンスモードに入っているため、新規プロジェクトでの採用は避けるべきです。

  • jwa:

    JWT の完全な実装ではなく、アルゴリズム名の正規化や署名アルゴリズムの識別など、極めて基礎的な処理のみを必要とする場合に使用します。通常、エンドユーザーが直接利用するライブラリではなく、他のツールを開発する際の部品として使われます。

  • jws:

    JWT のヘッダーと署名部分のみを分離して扱いたい場合、あるいはペイロードの検証ロジックを完全に自作する場合に使用します。標準的な JWT 認証を実装するだけなら、より高レベルな josejsonwebtoken を使うべきであり、このライブラリは特殊なユースケースに限られます。

  • node-jose:

    このライブラリは現在事実上メンテナンスが終了しており、新しいプロジェクトで使用してはいけません。過去に JWE 機能が必要で jose が未成熟だった時期に選ばれましたが、現在は jose がその役割を完全に代替しています。既存システムからの移行を検討してください。

jose のREADME

jose

jose is a JavaScript module for JSON Object Signing and Encryption, providing support for JSON Web Tokens (JWT), JSON Web Signature (JWS), JSON Web Encryption (JWE), JSON Web Key (JWK), JSON Web Key Set (JWKS), and more. The module is designed to work across various Web-interoperable runtimes including Node.js, browsers, Cloudflare Workers, Deno, Bun, and others.

Sponsor

Auth0 by Okta

If you want to quickly add JWT authentication to JavaScript apps, feel free to check out Auth0's JavaScript SDK and free plan. Create an Auth0 account; it's free!

💗 Help the project

Support from the community to continue maintaining and improving this module is welcome. If you find the module useful, please consider supporting the project by becoming a sponsor.

Dependencies: 0

jose has no dependencies and it exports tree-shakeable ESM1.

Documentation

jose is distributed via npmjs.com, jsr.io, jsdelivr.com, and github.com.

example ESM import1

import * as jose from 'jose'

JSON Web Tokens (JWT)

The jose module supports JSON Web Tokens (JWT) and provides functionality for signing and verifying tokens, as well as their JWT Claims Set validation.

Encrypted JSON Web Tokens

The jose module supports encrypted JSON Web Tokens and provides functionality for encrypting and decrypting tokens, as well as their JWT Claims Set validation.

Key Utilities

The jose module supports importing, exporting, and generating keys and secrets in various formats, including PEM formats like SPKI, X.509 certificate, and PKCS #8, as well as JSON Web Key (JWK).

JSON Web Signature (JWS)

The jose module supports signing and verification of JWS messages with arbitrary payloads in Compact, Flattened JSON, and General JSON serialization syntaxes.

JSON Web Encryption (JWE)

The jose module supports encryption and decryption of JWE messages with arbitrary plaintext in Compact, Flattened JSON, and General JSON serialization syntaxes.

Other

The following are additional features and utilities provided by the jose module:

Supported Runtimes

The jose module is compatible with JavaScript runtimes that support the utilized Web API globals and standard built-in objects or are Node.js.

The following runtimes are supported (this is not an exhaustive list):

Please note that certain algorithms may not be available depending on the runtime used. You can find a list of available algorithms for each runtime in the specific issue links provided above.

Supported Versions

VersionSecurity Fixes 🔑Other Bug Fixes 🐞New Features ⭐Runtime and Module type
v6.xSecurity PolicyUniversal2 ESM1

Specifications

Details
  • JSON Web Signature (JWS) - RFC7515
  • JSON Web Encryption (JWE) - RFC7516
  • JSON Web Key (JWK) - RFC7517
  • JSON Web Algorithms (JWA) - RFC7518
  • JSON Web Token (JWT) - RFC7519
  • JSON Web Key Thumbprint - RFC7638
  • JSON Web Key Thumbprint URI - RFC9278
  • JWS Unencoded Payload Option - RFC7797
  • CFRG Elliptic Curve ECDH and Signatures - RFC8037
  • Fully-Specified Algorithms for JOSE - RFC9864
  • ML-DSA for JOSE - RFC9964

The algorithm implementations in jose have been tested using test vectors from their respective specifications as well as RFC7520.

Footnotes

  1. CJS style let jose = require('jose') is possible in Node.js versions where the require(esm) feature is enabled by default (^20.19.0 || ^22.12.0 || >= 23.0.0). 2 3

  2. Assumes runtime support of WebCryptoAPI and Fetch API