JWT validator with public key verification and permission check
Project description
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:
from auth_jwt_validator.config import configure
configure("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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file auth_jwt_validator-0.1.5.tar.gz.
File metadata
- Download URL: auth_jwt_validator-0.1.5.tar.gz
- Upload date:
- Size: 8.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eeac35ee83c4ef3caef6a33a484c8e266d614f5cc0db01195d0cf8cff50c86e6
|
|
| MD5 |
66dd8ab163a1b36ca5ef8a1749ba58bd
|
|
| BLAKE2b-256 |
f0ad5e0067b911af879d936f4c350ff3e8249b6f1fe8e3c2746de9f3bb5c24db
|
File details
Details for the file auth_jwt_validator-0.1.5-py3-none-any.whl.
File metadata
- Download URL: auth_jwt_validator-0.1.5-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df08e7618210d23ba59cb2600d302f027e3ba6df1a2cc5febcfe482bdc4a84b4
|
|
| MD5 |
3139d278763be0a35f26ac9b093ab251
|
|
| BLAKE2b-256 |
46bce33fdf8f5212936cef4393f09c2cc195cdc2fa8c8e2de7146c94e223604e
|