# JWT認証

[JSON Web Token (JWT)](https://jwt.io/) はトークンベースの認証機構です。サーバー側でクライアントの認証情報やセッション情報を保持する必要がありません。EMQXはユーザー認証にJWTを使用することをサポートしています。

::: tip 前提条件

[EMQXの基本的な認証概念](../authn/authn.md)の知識

:::

## 認証の原理

クライアントは接続リクエストにJWTを含め、EMQXは事前に設定されたシークレットまたは公開鍵を使ってJWTの署名を検証します。ユーザーがJWKSエンドポイントを設定している場合、JWT認証機はJWKSエンドポイントから取得した公開鍵のリストを用いてJWTの署名を検証します。

署名検証が成功すると、JWT認証機はクレームのチェックに進みます。JWT認証機は`iat`（発行時刻）、`nbf`（有効開始時刻）、`exp`（有効期限）などのクレームに基づきJWTの有効性を積極的に検証します。追加のカスタムクレームも検証対象として指定可能です。署名とクレームの両方の検証が成功した場合にのみ、クライアントにアクセスが許可されます。

EMQXバージョン5.7.0以降では、JWT認証にJWTの有効期限切れ後にクライアントを切断するオプションが追加されました。設定パラメータ`disconnect_after_expire`はデフォルトで`true`に設定されています。JWTが期限切れになってもクライアントを接続し続けたい場合は、このパラメータを`false`に設定してください。

## ベストプラクティス

JWT認証機は基本的にJWTの署名のみを検証するため、クライアントの正当性を保証するものではありません。

ベストプラクティスとしては、独立した認証サーバーを構築し、クライアントはまず認証サーバーにアクセスして認証サーバーがクライアントの正当性を検証し、正当なクライアントに対してJWTを発行します。その後、クライアントは取得したJWTを用いてEMQXに接続します。

:::tip

JWTのペイロードはBase64エンコードされているだけなので、JWTを入手した誰でもBase64デコードにより元の情報を取得できます。そのため、JWTのペイロードに機密性の高いデータを格納することは推奨されません。

JWTの漏洩や盗難の可能性を減らすために、適切な有効期限を設定し、TLSを有効にしてクライアント接続を暗号化することを推奨します。

:::

## アクセス制御リスト（オプション）

アクセス制御リスト（ACL）は認証結果の拡張機能であり、ログイン後のクライアントの権限を制御します。JWTには`acl`フィールドを含めてクライアントの権限を指定できます。

詳細は[アクセス制御リスト（ACL）](./acl.md)をご参照ください。

## クライアント属性

EMQX v5.7.0以降、JWTペイロード内のオプションフィールド`client_attrs`を使用して[クライアント属性](../../client-attributes/client-attributes.md)を設定できます。キーと値は両方とも文字列型である必要があります。

例：

```json
{
  "exp": 1654254601,
  "username": "emqx_u",
  "client_attrs": {
      "role": "admin",
      "sn": "10c61f1a1f47"
  }
}
```

## ダッシュボードでのJWT認証設定

1. 左側のナビゲーションメニューから **Access Control** -> **Authentication** を選択します。

2. **Authentication** ページの右上にある **Create** をクリックし、**Mechanism** に **JWT** を選択して **Next** をクリックします。Backendの選択はスキップして、**Configuration** タブに進みます。

   <img src="./assets/authn-jwt.png" alt="JWT" style="zoom:67%;" />

3. 以下のオプションを設定します：

   - **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`：`Secret`がBase64エンコードされているかどうかを設定し、EMQXが署名検証時にデコードするかを決定します。

     - `public-key`：秘密鍵でJWTの署名を生成し、公開鍵で検証します。サポートされるアルゴリズムはRS256、RS384、RS512、ES256、ES384、ES512です。設定には以下が必要です：
       - `Public Key`：署名検証に使用するPEM形式の公開鍵を指定します。

   - **Precondition**：[Variform式](../../configuration/configuration.md#variform-expressions)で、このJWT認証機をクライアント接続に適用するかどうかを制御します。式はクライアントの属性（`username`、`clientid`、`listener`など）に対して評価され、結果が文字列の`"true"`の場合にのみ認証機が呼び出されます。それ以外の場合はスキップされます。詳細は[認証の前提条件](./authn.md#authentication-preconditions)をご覧ください。

   - **Disconnect After Expiration**：JWTの有効期限切れ後にクライアントを切断するかどうかを設定します。デフォルトで有効です。

   - **Payload**：追加で検証したいクレームを指定します。ユーザーは複数のキーと値のペアを**Claim**と**Expected Value**フィールドで定義できます。キーはJWT内のクレーム名と一致させる必要があり、値は実際のクレーム値と比較されます。現在サポートされているプレースホルダーは`${clientid}`と`${username}`です。

4. **Create** をクリックして設定を完了します。

EMQXはJWKSエンドポイントから最新のJWKSを定期的に取得することもサポートしています。JWKSは認可サーバーが発行しRSAまたはECDSAアルゴリズムで署名された任意のJWTを検証するための公開鍵の集合です。この機能を利用する場合は、**JWKS**設定ページに切り替えてください。

<img src="./assets/authn-jwt-2.png" style="zoom:67%;" />

以下のJWKS固有の設定項目を構成します：

- **JWKS Server**：EMQXがJWKSを取得するサーバーのエンドポイントアドレスを指定します。エンドポイントはGETリクエストをサポートし、仕様に準拠したJWKSを返す必要があります。

- **JWKS Refresh Interval**：JWKSの更新間隔を指定します。EMQXがJWKSを問い合わせる間隔です。

- **Headers**：JWKSサーバーへのリクエストに含める追加のHTTPヘッダーを指定します。これにより、サーバーの要件に応じた適切なリクエストが可能になります。キーと値のペアを追加できます。例：
  - **Key**: `Accept`
  - **Value**: `application/json`

**Create** をクリックして設定を完了します。

<!-- ## 設定項目による設定

設定項目による設定も可能です。詳細な手順は[authn-jwt:*](../../configuration/configuration-manual.html#authn-jwt:hmac-based)をご参照ください。 -->
