auth_jwt_validator
A simple and secure JWT validation and permission checking package for DRF and GraphQL APIs.
✨ Features
- 🔐 Verifies JWT tokens using RS256 public keys.
- ⚙️ Supports dynamic domain configuration to fetch keys from
/.well-known/jwks.json. - ⚡ Internal caching of public keys to reduce HTTP calls.
- 🔎 Verifies
exp,iat, andkidfields. - 🔐 Extracts
permissionsanduser_idfrom JWT. - ✅ Validates required permissions.
- ✅ Works with DRF: APIView, GenericAPIView, ViewSet.
- ✅ Supports function-based DRF views.
- ✅ Supports GraphQL (Graphene).
📦 Installation
pip install auth_jwt_validator
⚙️ Configuration
Before using the validator, configure your auth domain in main settings.py:
from auth_jwt_validator.settings import settings
# Set your user service domain dynamically
settings.set_domain("https://auth.myapp.com")
You can also set custom cache TTL (default is 300 seconds):
configure("https://auth.myapp.com", cache_ttl=600)
🚀 Usage
✅ Option 1: DRF Permission Class (Recommended for class-based views)
Add to your APIView, GenericAPIView, or ViewSet:
from rest_framework.views import APIView
from rest_framework.response import Response
from auth_jwt_validator.drf.permissions import HasJWTAndPermissions
class MyView(APIView):
permission_classes = [HasJWTAndPermissions]
required_permissions = ["read_profile"]
def get(self, request):
return Response({"user_id": request.user_id})
You can also use this with GenericAPIView:
from rest_framework.generics import GenericAPIView
class MyGenericView(GenericAPIView):
permission_classes = [HasJWTAndPermissions]
required_permissions = ["read_profile"]
def get(self, request):
return Response({"user_id": request.user_id})
Or inside a ViewSet:
from rest_framework.viewsets import ViewSet
class MyViewSet(ViewSet):
permission_classes = [HasJWTAndPermissions]
required_permissions = ["read_profile"]
def retrieve(self, request, pk=None):
return Response({"user_id": request.user_id, "profile_id": pk})
✅ Option 2: drf_jwt_required Decorator (for function-based views or custom method handling)
Use it for full control over the method:
from rest_framework.views import APIView
from rest_framework.response import Response
from auth_jwt_validator.decorators.drf import drf_jwt_required
class MyView(APIView):
@drf_jwt_required(["read_profile"])
def get(self, request):
return Response({"user_id": request.user_id})
🧠 Tip: This approach bypasses
permission_classesand does everything inline.
✅ With GenericAPIView
from rest_framework.generics import GenericAPIView
class MyGenericView(GenericAPIView):
@drf_jwt_required(["read_profile"])
def get(self, request, *args, **kwargs):
return Response({"user_id": request.user_id})
✅ With ViewSet
from rest_framework.viewsets import ViewSet
class MyViewSet(ViewSet):
@drf_jwt_required(["read_profile"])
def retrieve(self, request, pk=None):
return Response({"user_id": request.user_id, "profile_id": pk})
⚠️ Only use
drf_jwt_requiredwhen you need per-method control and don’t want to usepermission_classes.
🧪 GraphQL Usage (Graphene)
Add the decorator to your GraphQL resolvers:
import graphene
from auth_jwt_validator.decorators.graphql import graphql_jwt_required
class Query(graphene.ObjectType):
me = graphene.String()
@graphql_jwt_required(["read_profile"])
def resolve_me(self, info):
user_id = info.context.user_id
return f"Hello user {user_id}"
🔐 JWT Payload Format
JWTs should contain at minimum:
{
"user_id": "123",
"permissions": ["read_profile", "edit_profile"],
"exp": 1712345678,
"iat": 1712340000,
"iss": "auth.myapp.com"
}
🛠 Internals
validate_jwt_token(token: str, required_permissions: list[str] | None)
- Validates signature using public key (with
kid) - Checks
exp,iat, andiss - Raises:
JWTValidationErrorPermissionDeniedError
💡 Best Practices
- Use
permission_classes = [HasJWTAndPermissions]for most DRF views. - Use
drf_jwt_requiredonly for function-based views or fine-grained control. - Always call
configure(...)once at app startup. - Ensure
/.well-known/jwks.jsonis exposed in your user service.
🤝 Contributing
Pull requests welcome!
📄 License
MIT
Metadata
Release files for auth-jwt-validator 0.1.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| auth_jwt_validator-0.1.9.tar.gz | 8.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| auth_jwt_validator-0.1.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.9 kB
Release files / auth_jwt_validator-0.1.9.tar.gz
| Download URL | auth_jwt_validator-0.1.9.tar.gz |
|---|---|
| Size | 8.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fbc235504e3bb1cacebcb8fa0c3e7fdfbf88fc2e10abcdc65197ffe0f87fe0dd
|
|
BLAKE2b-256 checksum How to use checksums |
13f5da532177cb1e2440b15020342bb3f6c754bc050fb74dbafcbf72c382e5b2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.11.3
|
Release files / auth_jwt_validator-0.1.9-py3-none-any.whl
| Download URL | auth_jwt_validator-0.1.9-py3-none-any.whl |
|---|---|
| Size | 10.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c2c46bb6b2239edf8ca243ac7f9cb847bbb8ee1a63c1e2ecdf50fa9ae0738183
|
|
BLAKE2b-256 checksum How to use checksums |
9431d9eed2d448ccb3c2213de9eb3262564506f3c8e23578608f3e234bb1083b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.11.3
|