Skip to main content

JWT graphql (Django + GraphQL (Graphene))

jwt ini digunakan sebagi authentication pengguna, yang mana authentication ini memberikan batasan terhadap akses ases tententu

untuk implementasi jwt ini yang pertama install terlebih dahulu package yang dibutuhkan

🔐 1. Setup Dependencies

pip install graphene-django django-graphql-jwt

⚙️ 2. Configuration in Settings.py

# settings.py
INSTALLED_APPS = [
...
'graphene_django',
'graphql_jwt.refresh_token.apps.RefreshTokenConfig',
]

GRAPHENE = {
'SCHEMA': 'your_app.schema.schema',
'MIDDLEWARE': [
'graphql_jwt.middleware.JSONWebTokenMiddleware',
],
}

AUTHENTICATION_BACKENDS = [
'graphql_jwt.backends.JSONWebTokenBackend',
'django.contrib.auth.backends.ModelBackend',
]

JWT middleware

middleware ini berfunsgi untuk menambahkan user yang login ke resolve. jadi kita bisa mengakses uuser disemua route


from graphql_jwt.middleware import JSONWebTokenMiddleware
from graphql_jwt.decorators import jwt_cookie
from django.views.decorators.csrf import csrf_exempt


urlpatterns = [
path('admin/', admin.site.urls),
path('graphql', jwt_cookie(csrf_exempt(GraphQLView.as_view(
graphiql=True,
middleware=[JSONWebTokenMiddleware], # tambahakn middleware ini
schema=schema,))))
]

🛠️ 3. GraphQL Schema Implementation

# schema.py
import graphene
from graphene_django import DjangoObjectType
from graphql_jwt.decorators import login_required, permission_required

# Protected Query Example
class Query(graphene.ObjectType):
protected_data = graphene.String()

@login_required
@permission_required("blog.view_blog")
def resolve_protected_data(self, info):
return "Secret data!"

# Authentication Mutations
class AuthMutation(graphene.ObjectType):
token_auth = graphql_jwt.ObtainJSONWebToken.Field() # untuk mendapatkan token baru
verify_token = graphql_jwt.Verify.Field() # untuk cek token apakah token valid
refresh_token = graphql_jwt.Refresh.Field() # untuk refresh token apabila expired
delete_token = graphql_jwt.DeleteJSONWebTokenCookie.Field() # untuk delete token / logout

class Mutation(AuthMutation, graphene.ObjectType):
pass

schema = graphene.Schema(query=Query, mutation=Mutation)

🔌 4. URL Configuration

# urls.py
from django.urls import path
from graphene_django.views import GraphQLView
from graphql_jwt.decorators import jwt_cookie

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

🔥 5. Client Usage (React/Apollo Example)

a. Login and Get Token

mutation {
tokenAuth(username: "user", password: "pass") {
token
}
}

b. Access Protected Query

// Apollo Client setup
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link-context';

const httpLink = createHttpLink({ uri: '/graphql/' });

const authLink = setContext((_, { headers }) => {
const token = localStorage.getItem('token');
return {
headers: {
...headers,
authorization: token ? `JWT ${token}` : '',
}
};
});

const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});

🛡️ 6. Field-Level Protection (Optional)

class UserType(DjangoObjectType):
class Meta:
model = User
fields = ('username', 'email')

sensitive_data = graphene.String()

@login_required
def resolve_sensitive_data(self, info):
return "For logged-in users only!"

📌 Best Practices

Secure Token Storage

# settings.py
GRAPHQL_JWT = {
'JWT_COOKIE_SECURE': True,
'JWT_COOKIE_HTTPONLY': True,
}

Token Expiration

GRAPHQL_JWT = {
'JWT_EXPIRATION_DELTA': timedelta(hours=1),
'JWT_REFRESH_EXPIRATION_DELTA': timedelta(days=7),
}

🚨 Error Handling

Example error response:

{
"errors": [
{
"message": "You do not have permission to perform this action",
"extensions": { "code": "UNAUTHENTICATED" }
}
]
}

💡 Production Enhancements

Rate Limiting

from django_graphql_ratelimit import RatelimitMixin

class ProtectedQuery(RatelimitMixin, graphene.ObjectType):
ratelimit_key = "ip"
ratelimit_rate = "10/m"

Audit Logging

def resolve_protected_data(self, info):
log_access(info.context.user)
return sensitive_data

This implementation provides:

  • JWT token authentication
  • Query/mutation protection via decorators
  • Token management (refresh/verify)
  • Compatibility with Apollo Client and other GraphQL libraries