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 はクレーム(ユーザー情報など)を含みます。例:
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に指定してください。
結果
これで、EMQX設定に応じてMQTTのCONNECTパケットのユーザー名またはパスワードフィールドに使用可能な署名済みJWTトークンが生成されました。
複雑なビジネス用途向けのJWTトークン生成手順は、ブログ記事MQTTにおけるJWT認証とJWKSエンドポイント:原理と実践ガイドをご参照ください。
アクセス制御リスト(オプション)
アクセス制御リスト(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 From:クライアント接続リクエスト内のJWTの位置を指定します。選択肢は
password、username(それぞれMQTTクライアントのCONNECTパケット内のPassword、Usernameフィールドに対応) - Algorithm:JWTの暗号化方式を指定します。選択肢は
hmac-based、public-keyhmac-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形式の公開鍵を指定
- Precondition(オプション):1~256文字のVariform式を入力し、EMQXがクライアントに対してこのJWTまたはJWKS認証器を呼び出すか制御します。式の評価結果が文字列の
'true'の場合のみ認証器が呼び出され、それ以外はスキップされます。この機能はEMQX 6.1以降のデプロイメントで利用可能です。対応するクライアント属性と例は認証器の事前条件を参照してください。 - Disconnect After Expiration:JWTの有効期限切れ後にクライアントを切断するかどうかを設定します。デフォルトで有効です。
- Payload:カスタムクレームの検証を追加します。ユーザーはクレームのキーと期待値をそれぞれ追加します。
${clientid}や${username}のプレースホルダーが利用可能です。キーはJWT内のクレームを特定し、値はクレームの実際の値と比較されます。
JWTSを認証方式に選択した場合:
上記の設定に加え、以下も設定してください。
- JWKS Endpoint:EMQXがJWKSを問い合わせるサーバーのエンドポイントアドレスを指定します。GETリクエストに対応し、標準に準拠したJWKSを返す必要があります。
- JWKS Refresh Interval:JWKSの更新間隔(EMQXがJWKSを問い合わせる間隔)を秒単位で指定します。デフォルトは300秒です。設定後、作成をクリックして設定を完了します。
- Headers:JWKSサーバーへのリクエストに含める追加のHTTPヘッダーを指定します。これにより、サーバーの要件に応じた適切なリクエストが可能となります。キーと値のペアを追加できます。例:
- Key:
Accept - Value:
application/json
- Key:
TIP
- 現在のデプロイメントがDedicated Flex版の場合は、VPCピアリング接続を作成し、サーバーアドレスに内部ネットワークアドレスを使用してください。
- 現在のデプロイメントがBYOC版の場合は、パブリッククラウドコンソールでVPCピアリング接続を作成する必要があります。詳細はBYOCデプロイメントの作成 - VPCピアリング接続の設定を参照してください。サーバーアドレスには内部ネットワークアドレスを使用してください。
- 「Init resource failure!」というメッセージが表示された場合は、サーバーアドレスが正しいか、セキュリティグループが開放されているかを確認してください。