LoginSignup
5
2

More than 3 years have passed since last update.

【Django】GraphQLのJWT認証を構築

Last updated at Posted at 2020-12-05

概要

DjangoにGraphQLサーバーを構築し、JWT認証を実装を紹介します。
Djangoのユーザで認証できるようにし、リフレッシュトークンはDBに保存しすぐ無効化できるように設定します。
また、一度使用したリフレッシュトークンは無効化し、再度利用できないように設定します。
別サーバーからアクセスすることを想定し、CORSの設定も行います。

バージョン

  • python 3.9.0
  • django 3.1.3
  • django-graphql-jwt 0.3.1
  • django-cors-headers 3.5.0

ライブラリのインストール

Djangoのプロジェクトが既に作成済みとして話を進めます。(名前はconfig)

$ pip install django-graphql-jwt==0.3.1 django-cors-headers==3.5.0

Settingファイルの修正

1.AuthenticationMiddlewareMIDDLEWAREに追加します。
MIDDLEWARE = [
    # 追加
    'django.contrib.auth.middleware.AuthenticationMiddleware',
]
2.JSONWebTokenMiddlewareGRAPHENEに追加します。
GRAPHENE = {
    # configというプロジェクトを作成して、schemaというファイルを作成しています。
    'SCHEMA': 'config.schema.schema',
    'MIDDLEWARE': [
        # 追加
        'graphql_jwt.middleware.JSONWebTokenMiddleware',
    ],
}
3.JSONWebTokenBackendAUTHENTICATION_BACKENDSに追加します。
AUTHENTICATION_BACKENDS = [
    'graphql_jwt.backends.JSONWebTokenBackend',
    'django.contrib.auth.backends.ModelBackend',
]
4.RefreshTokenConfigcorsheadersINSTALLED_APPSに追加します。

RefreshTokenConfigは、リフレッシュトークンをDBに保存するために、追加します。
追加後は、python manage.py migrateを実行してください。
refresh_token_refreshtokenテーブルが作成されます。

corsheadersはCORSの設定のため、追加します。

INSTALLED_APPS = [
    'corsheaders',
    'graphql_jwt.refresh_token.apps.RefreshTokenConfig',
]
5.トークンの各種設定を追加します。

JWT_VERIFY_EXPIRATION・・・有効期限を確認するように設定します。
JWT_LONG_RUNNING_REFRESH_TOKEN・・・長期間有効なリフレッシュトークンを有効にします。
JWT_EXPIRATION_DELTA・・・トークンの有効期限を5分に設定します。
JWT_REFRESH_EXPIRATION_DELTA・・・リフレッシュトークンの有効期限を7日に設定します。

GRAPHQL_JWT = {
    'JWT_VERIFY_EXPIRATION': True,
    'JWT_LONG_RUNNING_REFRESH_TOKEN': True,
    'JWT_EXPIRATION_DELTA': timedelta(minutes=5),
    'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=7),
}
6.CORSの設定を追加します。

ローカルホストの3000番ポートからのアクセスを許可します。

CORS_ORIGIN_WHITELIST = [
    "http://localhost:3000",
]

ルートスキーマの修正

プロジェクトフォルダ(config)に、schema.pyを作成してjwt認証のMutaionを追加します。

import graphene
import graphql_jwt

class Mutation(graphene.ObjectType):
    # トークン生成
    token_auth = graphql_jwt.ObtainJSONWebToken.Field()
    # トークン認証
    verify_token = graphql_jwt.Verify.Field()
    # トークンリフレッシュ
    refresh_token = graphql_jwt.Refresh.Field()
    # リフレッシュトークンの無効化
    revoke_token = graphql_jwt.Revoke.Field()

    # リフレッシュトークンを一度使用したら削除する設定を追加
    @receiver(refresh_token_rotated)
    def revoke_refresh_token(sender, request, refresh_token, **kwargs):
        refresh_token.revoke(request)

schema = graphene.Schema(mutation=Mutation)

エンドポイントの作成

urls.pyを修正し、GraphQLのエンドポイントを作成します。
Django以外からアクセスしたときに、CSRFのエラーが出るためcsrf_exemptで機能を解除します。

from graphene_django.views import GraphQLView
from django.views.decorators.csrf import csrf_exempt

urlpatterns = [
    path('graphql/', csrf_exempt(GraphQLView.as_view(graphiql=True)))
]

サンプルクエリ

設定は以上です。
参考に、各ユースケースのクエリをサンプルとして載せておきます。
クエリを実行したときに、payloadの取得やリフレッシュトークンのテーブルへの保存、無効化などがわかるかと思います。

  • トークン生成
mutation TokenAuth($username: String!, $password: String!) {
  tokenAuth(username: $username, password: $password) {
    token
    payload
    refreshToken
    refreshExpiresIn
  }
}
  • トークン認証
mutation VerifyToken($token: String!) {
  verifyToken(token: $token) {
    payload
  }
}
  • トークンリフレッシュ
mutation RefreshToken($refreshToken: String!) {
    refreshToken(refreshToken: $refreshToken) {
        token
        payload
        refreshToken
        refreshExpiresIn
    }
}
  • リフレッシュトークンの無効化
mutation RevokeToken($refreshToken: String!) {
    revokeToken(refreshToken: $refreshToken) {
        revoked
    }
}

最後に

今回はDjangoを利用してGraphQLのJWT認証を構築しました。
ライブラリを使うと簡単に構築できるので良いですね。

今回構築したJWT認証をフロントエンドのReactから使うことをこれから構築していく予定です。
構築できたらまた紹介できたらと思います。

参考サイト

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2