{"id":9673,"library":"django-graphql-jwt","title":"JSON Web Token for Django GraphQL","description":"django-graphql-jwt is a Python library that provides JSON Web Token (JWT) authentication for Django GraphQL applications. It integrates seamlessly with graphene-django and Django's authentication system, offering mutations for obtaining, refreshing, and verifying tokens, as well as decorators and mixins for protecting GraphQL views and fields. It is currently at version 0.4.0 and typically releases updates as needed, often tied to major versions of Django, Graphene-Django, or PyJWT.","status":"active","version":"0.4.0","language":"en","source_language":"en","source_url":"https://github.com/flaviochaves/django-graphql-jwt","tags":["django","graphql","jwt","authentication","graphene"],"install":[{"cmd":"pip install django-graphql-jwt","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core web framework dependency.","package":"Django","optional":false},{"reason":"Handles JWT encoding and decoding.","package":"PyJWT","optional":false},{"reason":"Core GraphQL library for Python.","package":"graphql-core","optional":false},{"reason":"Django integration for Graphene GraphQL.","package":"graphene-django","optional":false}],"imports":[{"note":"Old package name or common confusion with Graphene.","wrong":"from graphene_jwt.decorators import login_required","symbol":"login_required","correct":"from graphql_jwt.decorators import login_required"},{"symbol":"JSONWebTokenMixin","correct":"from graphql_jwt.mixins import JSONWebTokenMixin"},{"note":"JSONWebTokenMutation is a base class, ObtainJSONWebToken is the concrete mutation.","wrong":"from graphql_jwt.mutations import JSONWebTokenMutation","symbol":"ObtainJSONWebToken","correct":"from graphql_jwt.mutations import ObtainJSONWebToken"},{"symbol":"VerifyToken","correct":"from graphql_jwt.mutations import VerifyToken"},{"symbol":"RefreshToken","correct":"from graphql_jwt.mutations import RefreshToken"},{"symbol":"jwt_settings","correct":"from graphql_jwt.settings import jwt_settings"},{"note":"Used in Django's AUTHENTICATION_BACKENDS setting.","symbol":"JSONWebTokenBackend","correct":"graphql_jwt.backends.JSONWebTokenBackend"},{"note":"Used in Django's MIDDLEWARE setting.","symbol":"JSONWebTokenMiddleware","correct":"graphql_jwt.middleware.JSONWebTokenMiddleware"}],"quickstart":{"code":"import graphene\nimport graphql_jwt\nfrom django.conf import settings\nfrom django.core.management import call_command\nfrom django.contrib.auth import get_user_model\n\n# Minimal Django settings for a runnable example\nif not settings.configured:\n    settings.configure(\n        SECRET_KEY='a-very-secret-key-for-testing',\n        DEBUG=True,\n        ALLOWED_HOSTS=['*'],\n        INSTALLED_APPS=[\n            'django.contrib.admin',\n            'django.contrib.auth',\n            'django.contrib.contenttypes',\n            'django.contrib.sessions',\n            'django.contrib.messages',\n            'django.contrib.staticfiles',\n            'graphene_django',\n            'graphql_jwt',\n        ],\n        AUTHENTICATION_BACKENDS=[\n            'graphql_jwt.backends.JSONWebTokenBackend',\n            'django.contrib.auth.backends.ModelBackend',\n        ],\n        MIDDLEWARE=[\n            'django.middleware.security.SecurityMiddleware',\n            'django.contrib.sessions.middleware.SessionMiddleware',\n            'django.middleware.common.CommonMiddleware',\n            'django.middleware.csrf.CsrfViewMiddleware',\n            'django.contrib.auth.middleware.AuthenticationMiddleware',\n            'django.contrib.messages.middleware.MessageMiddleware',\n            'django.middleware.clickjacking.XFrameOptionsMiddleware',\n            'graphql_jwt.middleware.JSONWebTokenMiddleware',\n        ],\n        ROOT_URLCONF=__name__, # Simplistic for example\n        TEMPLATES=[{ # Required for admin to work minimally\n            'BACKEND': 'django.template.backends.django.DjangoTemplates',\n            'DIRS': [], 'APP_DIRS': True,\n            'OPTIONS': {'context_processors': [\n                'django.template.context_processors.debug',\n                'django.template.context_processors.request',\n                'django.contrib.auth.context_processors.auth',\n                'django.contrib.messages.context_processors.messages',\n            ]}},\n        ],\n        DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},\n        GRAPHQL_JWT={ # Example custom settings\n            'JWT_VERIFY_EXPIRATION': True,\n            'JWT_EXPIRATION_DELTA': 'datetime.timedelta(minutes=5)',\n            'JWT_REFRESH_EXPIRATION_DELTA': 'datetime.timedelta(days=7)',\n        }\n    )\n    # Apply migrations for auth models\n    call_command('migrate', verbosity=0, interactive=False)\n\n# Create a dummy user for the example\nUser = get_user_model()\ntry:\n    User.objects.get(username='testuser')\nexcept User.DoesNotExist:\n    user = User.objects.create_user(username='testuser', email='test@example.com', password='password123')\n\n# Define your GraphQL schema\nclass Query(graphene.ObjectType):\n    hello = graphene.String(name=graphene.String(default_value=\"World\"))\n\n    def resolve_hello(self, info, name):\n        return f\"Hello {name}!\"\n\n# Custom mutation for obtaining token with user info\nclass ObtainJSONWebToken(graphql_jwt.JSONWebTokenMutation):\n    user = graphene.Field(User.__class__)\n\n    @classmethod\n    def resolve_mutant(cls, root, info, **kwargs):\n        return cls(user=info.context.user)\n\n# Custom mutation for refreshing token with user info\nclass RefreshToken(graphql_jwt.RefreshTokenMutation):\n    user = graphene.Field(User.__class__)\n\n    @classmethod\n    def resolve_mutant(cls, root, info, **kwargs):\n        return cls(user=info.context.user)\n\n# Custom mutation for verifying token with user info\nclass VerifyToken(graphql_jwt.VerifyTokenMutation):\n    user = graphene.Field(User.__class__)\n\n    @classmethod\n    def resolve_mutant(cls, root, info, **kwargs):\n        return cls(user=info.context.user)\n\n\nclass Mutation(graphene.ObjectType):\n    token_auth = ObtainJSONWebToken.Field()\n    verify_token = VerifyToken.Field()\n    refresh_token = RefreshToken.Field()\n\nschema = graphene.Schema(query=Query, mutation=Mutation)\n\n# Example usage (run a mutation against the schema)\nif __name__ == \"__main__\":\n    print(\"\\n--- Attempting to obtain token ---\")\n    obtain_token_query = \"\"\"\n        mutation ObtainToken {\n            tokenAuth(username: \"testuser\", password: \"password123\") {\n                token\n                user {\n                    username\n                    email\n                }\n            }\n        }\n    \"\"\"\n    result = schema.execute(obtain_token_query)\n    if result.errors:\n        print(\"Errors:\", result.errors)\n    else:\n        print(\"Data:\", result.data)\n        token = result.data['tokenAuth']['token']\n\n        print(\"\\n--- Attempting to verify token ---\")\n        verify_token_query = f\"\"\"\n            mutation VerifyToken {{\n                verifyToken(token: \"{token}\") {{\n                    payload\n                    user {{\n                        username\n                    }}\n                }}\n            }}\n        \"\"\"\n        result_verify = schema.execute(verify_token_query)\n        if result_verify.errors:\n            print(\"Errors:\", result_verify.errors)\n        else:\n            print(\"Data:\", result_verify.data)\n","lang":"python","description":"This quickstart demonstrates how to define a basic `django-graphql-jwt` schema with `ObtainJSONWebToken`, `VerifyToken`, and `RefreshToken` mutations. It includes a minimal, self-contained Django environment setup to make the code runnable, creating a test user and then executing sample GraphQL mutations to obtain and verify a token. For a full Django project, you would integrate `AUTHENTICATION_BACKENDS` and `MIDDLEWARE` into your project's `settings.py` and expose the schema via `graphene_django.views.GraphQLView`."},"warnings":[{"fix":"Update your GraphQL clients or resolver logic to properly catch and handle `JSONWebTokenError` exceptions, providing more informative error messages.","message":"As of version 0.4.0, JWT token verification errors are now correctly propagated as `graphql_jwt.exceptions.JSONWebTokenError` exceptions, rather than being silently suppressed or returning `None` in some contexts. This changes error handling behavior.","severity":"breaking","affected_versions":"0.4.0+"},{"fix":"Add `'graphql_jwt.backends.JSONWebTokenBackend'` to your `AUTHENTICATION_BACKENDS` list in `settings.py`. Ensure it's before `'django.contrib.auth.backends.ModelBackend'` if you want JWT to be the primary authentication method.","message":"For `django-graphql-jwt` to function correctly, `graphql_jwt.backends.JSONWebTokenBackend` MUST be included in your Django project's `AUTHENTICATION_BACKENDS` setting. Without it, Django's authentication system will not recognize the JWT backend.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Add `'graphql_jwt.middleware.JSONWebTokenMiddleware'` to your `MIDDLEWARE` list in `settings.py`, preferably after `django.contrib.auth.middleware.AuthenticationMiddleware`.","message":"To ensure that the authenticated user information from a JWT is available in `info.context.user` within your GraphQL resolvers, you must include `graphql_jwt.middleware.JSONWebTokenMiddleware` in your Django project's `MIDDLEWARE` setting.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Update your GraphQL clients and schema to use the dedicated `refreshToken` mutation (e.g., `refresh_token = RefreshToken.Field()`) instead of relying on the `tokenAuth` mutation for token refreshing.","message":"The `refresh_token` field on the `tokenAuth` mutation is deprecated as of version 0.4.0. Users should migrate to using the standalone `RefreshTokenMutation` for token refreshing.","severity":"deprecated","affected_versions":"0.4.0+"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Run `pip install django-graphql-jwt` in your project's virtual environment.","cause":"`django-graphql-jwt` has not been installed or is not available in the current Python environment.","error":"ModuleNotFoundError: No module named 'graphql_jwt'"},{"fix":"Add `'graphql_jwt.backends.JSONWebTokenBackend'` to the `AUTHENTICATION_BACKENDS` list in your `settings.py`.","cause":"The required JWT authentication backend is missing from Django's `AUTHENTICATION_BACKENDS` setting.","error":"django.core.exceptions.ImproperlyConfigured: AUTHENTICATION_BACKENDS must contain 'graphql_jwt.backends.JSONWebTokenBackend'."},{"fix":"Ensure your `Mutation` class in `schema.py` explicitly includes `token_auth = ObtainJSONWebToken.Field()` (and similar for `verify_token` and `refresh_token`).","cause":"The GraphQL `Mutation` type in your schema does not include the `tokenAuth` field (or `verifyToken`, `refreshToken`).","error":"Cannot query field \"tokenAuth\" on type \"Mutation\"."},{"fix":"Obtain a new token using the `tokenAuth` mutation or use the `refreshToken` mutation with a valid refresh token. If tokens expire too quickly for your use case, adjust `JWT_EXPIRATION_DELTA` in `settings.py` (e.g., `datetime.timedelta(hours=1)`).","cause":"The provided JWT token has exceeded its expiration time, as defined by `JWT_EXPIRATION_DELTA` in your `GRAPHQL_JWT` settings.","error":"graphql_jwt.exceptions.JSONWebTokenError: Signature has expired"}]}