JWT認証
JWT認証は、クライアントの認証情報やセッション情報をサーバー側で保持しないトークンベースの認可機構です。鍵を所有していれば認証情報を一括発行できるため、最もシンプルな認証方法となります。
注意
JWT認証はEMQX Serverlessのデプロイメントではサポートされていません。
JWT認証の仕組み
クライアントは接続開始時に、JWTをユーザー名またはパスワードフィールド(モジュール設定に依存)に保持します。EMQXプラットフォームは設定された鍵または証明書を用いて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) + "." + Signature
Headerはトークンのメタデータ(アルゴリズムやトークンタイプなど)を指定します。例:
json{ "alg": "HS256", "typ": "JWT" }
Payloadは
username
、exp
、client_attrs
などのクレーム(ユーザー情報)を含みます。例:json{ "username": "emqx_user", "exp": 1719830400, "client_attrs": { "role": "admin", "sn": "device-001" } }
Signatureはトークンの改ざんを防止するため、HeaderとPayloadを秘密鍵や秘密鍵ペアで署名して生成されます。
手順
JWTのHeaderを定義します。例(HMAC SHA-256の場合):
json{ "alg": "HS256", "typ": "JWT" }
RSA/ECDSAの場合は、鍵の種類に応じて
"alg"
をRS256
、ES256
などに置き換えます。JWTのPayloadを定義します。PayloadにはEMQXで利用するクレームを含めます。主なフィールド例:
json{ "sub": "mqtt_client", // サブジェクト:任意、識別用 "username": "emqx_user", // 任意:EMQX設定でバインドされている場合に使用 "clientid": "client_123", // 任意:クライアント制限用 "exp": 1719830400 // 必須:有効期限(Unixタイムスタンプ) }
重要事項:
exp
は必須です。設定しないとEMQXでトークンが拒否される可能性があります。username
やclientid
は、EMQXがトークン内で検証する設定の場合に追加します。acl
やclient_attrs
などのカスタムクレームも含められます。
HeaderとPayloadをBase64Urlエンコードします。手動でもJWTライブラリを使っても構いません。
JWTに署名します。秘密鍵や秘密鍵ペアを使って署名を生成します。
- HMAC(例:
HS256
)の場合:HMACSHA256(base64Url(header) + "." + base64Url(payload), secret)
- RSA/ECDSA(例:
RS256
)の場合:適切な署名アルゴリズムで秘密鍵を使用します。
- HMAC(例:
JWTを組み立てます。エンコード済みHeader、Payload、Signatureをピリオドで連結します。
<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生成手順は、ブログ記事JWT Authentication and JWKS Endpoint in MQTT: Principle and a Hands-on Guideをご参照ください。
アクセスコントロールリスト(任意)
アクセスコントロールリスト(ACL)は、認証結果の拡張機能で、ログイン後のクライアントの権限を制御します。JWTにacl
フィールドを含めてクライアントの権限を指定可能です。
詳細はアクセスコントロールリスト(ACL)をご覧ください。
クライアント属性
EMQX v5.7.0以降、JWT Payloadの任意フィールド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-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形式の公開鍵を指定します。
- 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
- 専用版のデプロイメントの場合は、VPCピアリング接続を作成し、サーバーアドレスに内部ネットワークアドレスを使用してください。
- BYOC版のデプロイメントの場合は、パブリッククラウドコンソールでVPCピアリング接続を作成する必要があります。詳細はBYOCデプロイメント作成 - VPCピアリング接続設定をご参照ください。サーバーアドレスには内部ネットワークアドレスを使用してください。
- 「Init resource failure!」というメッセージが表示された場合は、サーバーアドレスの正確性とセキュリティグループの開放状況を確認してください。