JWT認証
JWT認証は、クライアントの認証情報やセッション情報をサーバー側で保持しないトークンベースの認可機構です。鍵を所持していれば認証情報を一括で発行できるため、最もシンプルな認証方法となります。
注意
JWT認証はEMQXサーバレスのデプロイメントではサポートされていません。
JWT認証の仕組み
クライアントは接続開始時に、モジュール設定に応じてユーザー名またはパスワードのフィールドにJWTを保持します。EMQX Cloudは設定された鍵または証明書を用いてJWTの復号を行います。復号が成功すれば認証成功、失敗すれば認証失敗となります。
署名検証が成功すると、JWT認証器はクレームの検証に進みます。JWT認証器はiat(発行時刻)、nbf(有効開始時刻)、exp(有効期限)などのクレームに基づきJWTの有効性を積極的にチェックします。追加のカスタムクレームの検証も可能です。署名とクレームの両方の検証が成功した場合にのみ、クライアントにアクセスが許可されます。
デフォルト設定では、JWT認証を有効にすると任意のユーザー名と以下のパスワードで接続可能であり、パスワードはデフォルトの鍵フィールドemqxsecretに対して検証されます。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJFTVFYIENsb3VkIiwiaWF0IjoxNTE2MjM5MDIyfQ.-k9Ggc6L_Jxq4uUf9xwdJpwRrS3PquL-JZKtAJoOvBo上記のJWTトークンはテスト用のものです。ビジネスニーズに合わせたJWTトークンは適切なツールを使って生成してください。詳細はJWTの生成方法をご参照ください。
JWTの生成方法
このセクションでは、EMQXでクライアント認証に使用する有効なJWTを生成する手順を説明します。
前提条件
- 秘密鍵(HMACアルゴリズム用)またはプライベートキー(RSA/ECDSA用)
- JWT生成ツールまたはライブラリ(例:jwt.io、jjwt、mkjwk、Python、Node.js)
- EMQXが期待するアルゴリズム(
HS256、RS256など)を把握していること
JWTの構造
JWTは以下の3つの部分で構成されます。
JWT = base64UrlEncode(Header) + "." + base64UrlEncode(Payload) + "." + SignatureHeader はトークンのメタデータ(アルゴリズムやトークンタイプなど)を指定します。例:
json{ "alg": "HS256", "typ": "JWT" }Payload は
username、exp、client_attrsなどのクレーム(ユーザー情報)を含みます。例:json{ "username": "emqx_user", "exp": 1719830400, "client_attrs": { "role": "admin", "sn": "device-001" } }Signature はトークンの改ざんを防ぐための署名で、ヘッダーとペイロードを秘密鍵またはプライベートキーで署名して生成します。
手順
JWTヘッダーを定義します。例(HMAC SHA-256の場合):
json{ "alg": "HS256", "typ": "JWT" }RSA/ECDSAの場合は、鍵の種類に応じて
"alg"をRS256、ES256などに置き換えます。JWTペイロードを定義します。ペイロードにはEMQXで使用するクレームを含めます。主なフィールド例:
json{ "sub": "mqtt_client", // サブジェクト:任意、識別用 "username": "emqx_user", // 任意:EMQX設定でバインドされている場合に使用 "clientid": "client_123", // 任意:クライアント制限用 "exp": 1719830400 // 必須:有効期限(Unixタイムスタンプ) }重要事項:
expは必須です。ない場合、EMQXはトークンを拒否する可能性があります。usernameやclientidはEMQXでトークン内検証が設定されている場合に追加してください。aclやclient_attrsなどのカスタムクレームも含められます。
ヘッダーとペイロードをBase64Urlエンコードします。手動でもJWTライブラリを使っても構いません。
JWTに署名します。秘密鍵またはプライベートキーを使って署名を生成します。
- HMAC(例:
HS256)の場合:HMACSHA256(base64Url(header) + "." + base64Url(payload), secret) - RSA/ECDSA(例:
RS256)の場合:適切な署名アルゴリズムでプライベートキーを使用します。
- HMAC(例:
JWTを組み立てます。エンコード済みのヘッダー、ペイロード、署名をドットで連結します。
<header>.<payload>.<signature>JWTを検証します(任意ですが推奨)。jwt.ioや開発ツールでトークンをデコードし、正しく生成されているか確認してください。
Python(pyjwt)の例
import jwt
import datetime
secret = "your_shared_secret"
payload = {
"username": "emqx_user",
"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}
token = jwt.encode(payload, secret, algorithm="HS256")
print(token)RS256の場合はsecretをプライベートキーに置き換え、RS256アルゴリズムを指定してください。
結果
これで署名済みのJWTトークンが生成され、EMQXの設定に応じてMQTTのCONNECTパケットのユーザー名かパスワードフィールドに使用できます。
複雑なビジネスユースケース向けのJWTトークン生成手順は、ブログ記事JWT Authentication and JWKS Endpoint in MQTT: Principle and a Hands-on Guideをご参照ください。
アクセスコントロールリスト(オプション)
アクセスコントロールリスト(ACL)は、認証結果の拡張機能で、ログイン後のクライアントの権限を制御します。JWTにaclフィールドを含めてクライアントの権限を指定できます。
詳細はアクセスコントロールリスト(ACL)をご覧ください。
クライアント属性
EMQX v5.7.0以降、JWTペイロードのオプションフィールドclient_attrsを使ってクライアント属性を設定できます。キーと値はどちらも文字列型である必要があります。
例:
{
"exp": 1654254601,
"username": "emqx_u",
"client_attrs": {
"role": "admin",
"sn": "10c61f1a1f47"
}
}JWT認証の設定
デプロイメントで、アクセス制御 - 拡張認証をクリックし、JWT認証の設定をクリックして新しい認証を作成します。
以下のように関連設定を完了できます。
認証方式でJWTを選択した場合:
- JWTの取得元:クライアント接続要求内のJWTの位置を指定します。選択肢は
password、username(それぞれMQTTクライアントCONNECTパケットのPassword、Usernameフィールドに対応) - アルゴリズム:JWTの暗号化方式を指定します。選択肢は
hmac-based、public-key;hmac-basedを選択した場合、JWTは対称鍵で署名生成・検証を行います(HS256、HS384、HS512をサポート)。以下も設定してください:- Secret:署名検証に使用する鍵。署名生成時と同じ鍵を指定します。
- Secret Base64 Encode:EMQXが署名検証前に
SecretをBase64デコードするかどうかを設定します。選択肢はTrue、False、デフォルトはFalse。
public-keyを選択した場合、JWTはプライベートキーで署名生成し、検証には公開鍵を使用します(RS256、RS384、RS512、ES256、ES384、ES512をサポート)。以下も設定してください:- Public Key:署名検証に使用するPEM形式の公開鍵を指定します。
- 有効期限切れ後の切断:JWTの有効期限切れ後にクライアントを切断するかどうかを設定します。デフォルトで有効です。
- Payload:カスタムクレームの検証を追加します。ユーザーはクレームのキーと期待値をそれぞれ追加できます。
${clientid}や${username}のプレースホルダーもサポートします。キーはJWT内のクレームを特定し、値はクレームの実際の値と比較されます。
JWTSを認証方式に選択した場合:
上記設定に加えて以下も設定してください。
- JWKSエンドポイント:EMQXがJWKSを問い合わせるサーバーのエンドポイントアドレスを指定します。GETリクエストに対応し、標準に準拠したJWKSを返す必要があります。
- JWKS更新間隔:JWKSの更新間隔を指定します。EMQXがJWKSを問い合わせる周期です。デフォルトは300秒(s)。設定後、作成をクリックして完了します。
- ヘッダー:JWKSサーバーへのリクエストに含める追加のHTTPヘッダーを指定します。これにより、サーバーの要件に合わせた適切なリクエストが可能になります。キーと値のペアを追加できます。例:
- キー:
Accept - 値:
application/json
- キー:
TIP
- 現在のデプロイメントがDedicated Flexエディションの場合は、VPCピアリング接続を作成し、サーバーアドレスに内部ネットワークアドレスを使用してください。
- 現在のデプロイメントがBYOCエディションの場合は、パブリッククラウドコンソールでVPCピアリング接続を作成する必要があります。詳細はBYOCデプロイメントの作成 - VPCピアリング接続の設定をご参照ください。サーバーアドレスには内部ネットワークアドレスを使用してください。
- 「Init resource failure!」というメッセージが表示される場合は、サーバーアドレスが正しいか、セキュリティグループが開放されているかを確認してください。