🗂

Drupal JSON Web Token Authenticationモジュールを試す

2023/12/31に公開

概要

DrupalのJSON Web Token Authenticationモジュールを試してみます。

https://www.drupal.org/project/jwt

以下のページを参考にしました。

https://preston.so/writing/decoupled-drupal-authentication-with-json-web-tokens/

なお、類似するモジュールとして、以下があるようです。

https://www.drupal.org/project/rest_api_authentication

上記モジュールを使ったjwt認証は以下で説明されています。

https://www.drupal.org/docs/contributed-modules/api-authentication/jwt-authentication

しかし、以下の記事に記載したように、上記モジュールでjwt認証を使用するには有料プランに加入する必要があるようでした。

https://zenn.dev/nakamura196/articles/04461ffea44f3f

そこで、今回は、jwtモジュールのほうを試してみます。

インストールと有効化

jwtモジュール

注意点として、jwtだけでなく、jwt_auth_consumerjwt_auth_issuerも有効化する必要がありました。

composer.phar require 'drupal/jwt:^2.0'
vendor/bin/drush en jwt jwt_auth_consumer jwt_auth_issuer

restuiモジュール

composer.phar require 'drupal/restui:^1.21'
vendor/bin/drush en restui

設定

以下にアクセスして、キーを作成します。

/admin/config/system/keys

Key typeとしてJWT HMAC Keyを選択して、JWT AlgorithmとしてSHA-256を選択しました。

次に、以下にアクセスして、JWTの設定を行います。

AlgorithmとしてデフォルトのSHA-256を選択して、Secretとして先ほど作成したキー(ここではjwt)を選択します。

その後、ログインした状態で、以下にアクセスしてみます。

/jwt/token

すると、以下のようなトークンが得られます。

参考までに、このトークンをjwt.ioで検証してみます。

https://jwt.io/

PAYLOADの箇所を見てみると、iat(Issued A: トークンが発行された時刻)やDrupalの「User ID」を確認することができます。

RESTリソースの設定

以下にアクセスします。

/admin/config/services/rest

ここでは、コンテンツに対して、POSTを有効化し、認証プロバイダとしてjwt_authを選択します。

Postman

Postmanを使って、コンテンツの作成を試してみます。

まず、Authorizationを指定せずに、コンテンツの作成試してみます。

Bodyrawを選択して、フォーマットをJSONとします。以下の最低限のデータで、articleタイプのコンテンツの作成してみます。

{
    "type": [
        {
            "target_id": "article"
        }
    ],
    "title": [
        {
            "value": "新しい記事のタイトル"
        }
    ]
}

POST先のURLは以下です。

{DRUPALをインストールしたパス}/node?_format=json

結果、以下のような結果が返却されます。

{
    "status": "error",
    "code": "401",
    "error_description": "MISSING AUTHORIZATION HEADER"
}

次に、AuthorizationBear Tokenを選択して、先ほど取得したトークンを入力してpostしてみます。

結果、以下のようにコンテンツを作成することができました。

{
    "nid": [
        {
            "value": 2890
        }
    ],
    "uuid": [
        {
            "value": "2638690a-e6c3-4723-843a-38c951f5809a"
        }
    ],
    "vid": [
        {
            "value": 2916
        }
    ],
    "langcode": [
        {
            "value": "ja"
        }
    ],
    "type": [
        {
            "target_id": "article",
            "target_type": "node_type",
            "target_uuid": "974a1b20-9965-45bc-95a6-0466e536040a"
        }
    ],
    "revision_timestamp": [
        {
            "value": "2023-12-31T07:14:33+00:00",
            "format": "Y-m-d\\TH:i:sP"
        }
    ],
    "revision_uid": [
        {
            "target_id": 1,
            "target_type": "user",
            "target_uuid": "fc10b1ef-c493-475d-b206-43b4d61ee171",
            "url": "/xxx/user/1"
        }
    ],
    "revision_log": [],
    "status": [
        {
            "value": true
        }
    ],
    "uid": [
        {
            "target_id": 1,
            "target_type": "user",
            "target_uuid": "fc10b1ef-c493-475d-b206-43b4d61ee171",
            "url": "/xxx/user/1"
        }
    ],
    "title": [
        {
            "value": "新しい記事のタイトル"
        }
    ],
    "created": [
        {
            "value": "2023-12-31T07:14:33+00:00",
            "format": "Y-m-d\\TH:i:sP"
        }
    ],
    "changed": [
        {
            "value": "2023-12-31T07:14:33+00:00",
            "format": "Y-m-d\\TH:i:sP"
        }
    ],
    "promote": [
        {
            "value": true
        }
    ],
    "sticky": [
        {
            "value": false
        }
    ],
    "default_langcode": [
        {
            "value": true
        }
    ],
    "revision_translation_affected": [
        {
            "value": true
        }
    ],
    "path": [
        {
            "alias": null,
            "pid": null,
            "langcode": "ja"
        }
    ],
    "body": [],
    "field_image": []
}

(参考)JSON:APIの場合

次に、JSON:APIを使った場合の結果も確認してみます。

設定

まずウェブサービスのJSON:APIを有効化します。

次に、/admin/config/services/jsonapiにアクセスして、すべての操作を許可します。

なお、この設定を行わずに後述するpostを行うと、以下のエラーが返却されます。

{
    "jsonapi": {
        "version": "1.0",
        "meta": {
            "links": {
                "self": {
                    "href": "http://jsonapi.org/format/1.0/"
                }
            }
        }
    },
    "errors": [
        {
            "title": "Method Not Allowed",
            "status": "405",
            "detail": "JSON:API is configured to accept only read operations. Site administrators can configure this at xxx/admin/config/services/jsonapi.",
            "links": {
                "via": {
                    "href": "xxx/jsonapi/node/article"
                },
                "info": {
                    "href": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.6"
                }
            },
            "source": {
                "file": "xxx/core/modules/jsonapi/src/Routing/ReadOnlyModeMethodFilter.php",
                "line": 76
            },
            "meta": {
                ...
            }
        }
    ]
}

Postman

JSON:APIを用いる場合には、以下のようなjsonデータを使ってコンテンツを作成します。

{
    "data": {
        "type": "node--article",
        "attributes": {
            "title": "Page Title"
        }
    }
}

articleタイプのコンテンツを作成する場合のPOST先のURLは以下です。

{DRUPALをインストールしたパス}/jsonapi/node/article

Authorizationを指定せずに、コンテンツの作成を試みます。結果、以下のように、先ほどと同様の結果が得られます。

{
    "status": "error",
    "code": "401",
    "error_description": "MISSING AUTHORIZATION HEADER"
}

Authorizationを指定した場合、以下のようにコンテンツが作成されました。

{
    "jsonapi": {
        "version": "1.0",
        "meta": {
            "links": {
                "self": {
                    "href": "http://jsonapi.org/format/1.0/"
                }
            }
        }
    },
    "data": {
        "type": "node--article",
        "id": "a4338a64-2f84-4685-9abf-9519a3ceef09",
        "links": {
            "self": {
	    ...
}

まとめ

DrupalのJWTモジュールを用いたAPIの利用例について紹介しました。

十分に考慮できていない点が多いかと思いますが、本モジュール等の使い方の参考になりましたら幸いです。

Discussion