gRPC Authentication
Learn how to secure your gRPC services with API keys.
🎯 Overview
Django-CFG gRPC uses API Key authentication for secure service access:
| Method | Best For | Management | Lifespan |
|---|---|---|---|
| API Keys | Services, CLI tools, webhooks, all use cases | Django Admin | Long-lived (configurable) |
Historical Note
Django-CFG previously supported JWT authentication for gRPC. As of v1.5.8, we’ve migrated to API Key authentication only for better security and manageability.
API Keys provide:
- Centralized management through Django Admin
- Easy revocation without changing secrets
- Per-service key tracking
- Usage statistics and monitoring
- No token expiration complexity
🔑 API Key Authentication
Concept
API keys are long-lived tokens for machine-to-machine communication:
- Create keys in Django Admin
- Each key authenticates as a specific user
- Can be revoked instantly
- Usage is tracked automatically
Creating Keys
Via Django Admin:
- Go to
/admin/→ gRPC API Keys - Click “Add gRPC API Key”
- Fill in name, user, type, expiration
- Save and copy the generated key
Using Keys
With grpcurl:
grpcurl -H "x-api-key: YOUR_API_KEY" \
localhost:50051 api.users.UserService/GetUserWith Python client:
import grpc
# Add API key to metadata
metadata = [('x-api-key', 'YOUR_API_KEY')]
with grpc.insecure_channel('localhost:50051') as channel:
stub = UserServiceStub(channel)
response = stub.GetUser(request, metadata=metadata)In service:
class UserService(BaseService):
def UpdateProfile(self, request, context):
# Access authenticated user
user = context.user # Set by API key auth
# Also access the API key used
api_key = context.api_key # Which key was used
user.bio = request.bio
user.save()
return UserResponse(...)Development Shortcut
For development, you can use Django’s SECRET_KEY:
# Use SECRET_KEY instead of creating API key
grpcurl -H "x-api-key: django-insecure-dev-key..." \
localhost:50051 api.users.UserService/GetUserOnly use SECRET_KEY in development! Disable in production via accept_django_secret_key: False
🔧 Configuration
API Key Settings
# api/config.py
from django_cfg import DjangoConfig, GRPCConfig, GRPCAuthConfig
class MyConfig(DjangoConfig):
grpc = GRPCConfig(
enabled=True,
enabled_apps=["apps.users"],
# Authentication settings
auth=GRPCAuthConfig(
enabled=True, # Enable authentication
require_auth=False, # Allow anonymous by default
# API Key settings
api_key_header="x-api-key", # Header name
accept_django_secret_key=True, # Allow SECRET_KEY (dev only!)
# Public methods (no auth needed)
public_methods=[
"/grpc.health.v1.Health/Check",
],
),
)Authentication Modes
1. Disabled (Development):
auth=GRPCAuthConfig(
enabled=False, # All methods public
)2. Optional Auth (Recommended):
auth=GRPCAuthConfig(
enabled=True,
require_auth=False, # Some methods can be public
api_key_header="x-api-key",
accept_django_secret_key=True, # Allow SECRET_KEY for dev
)3. Required Auth (Strict):
auth=GRPCAuthConfig(
enabled=True,
require_auth=True, # All methods require API key
api_key_header="x-api-key",
accept_django_secret_key=False, # Production: only DB keys
public_methods=[
"/grpc.health.v1.Health/Check", # Except health check
],
)🛡️ Service Authorization
Public Methods
class UserService(BaseService):
def GetUser(self, request, context):
# No auth required - anyone can call
user = User.objects.get(id=request.user_id)
return UserResponse(...)Protected Methods
class UserService(BaseService):
def UpdateProfile(self, request, context):
# Require authentication
user = self.require_user(context)
user.bio = request.bio
user.save()
return UserResponse(...)Permission Checks
class UserService(BaseService):
def DeleteUser(self, request, context):
# Require staff permission
self.require_staff(context)
User.objects.get(id=request.user_id).delete()
return Empty()📊 Monitoring
View Logs
All authenticated requests are logged with:
- Which user made the request
- Which API key was used (if applicable)
- Request duration and status
Django Admin:
/admin/ → gRPC Request LogsFilter by:
- User
- API Key
- Status (success/error)
- Date range
Check API Key Usage
Django Admin:
/admin/ → gRPC API KeysSee for each key:
- Total request count
- Last used timestamp
- Status (active/expired/revoked)
🔒 Best Practices
API Keys
✅ DO:
- Create separate keys for each service
- Set expiration dates for better security
- Revoke unused keys regularly
- Monitor usage in Django Admin
- Disable
accept_django_secret_keyin production - Use descriptive names (e.g., “Analytics Service”, “Mobile App Backend”)
- Track usage statistics regularly
❌ DON’T:
- Share keys between services
- Use SECRET_KEY in production
- Hardcode keys in source code
- Leave expired keys active
- Create keys without expiration dates in production
📚 Common Patterns
Service-to-Service Communication
# Service A calls Service B
# 1. Create API key for Service A in Django Admin
# 2. Store key in Service A's environment variables
# 3. Service A includes key in metadata
# Service A (caller)
import os
metadata = [('x-api-key', os.getenv('SERVICE_B_API_KEY'))]
response = service_b_stub.Method(request, metadata=metadata)CLI Tools
# Create API key for CLI tool
# 1. Go to Django Admin → gRPC API Keys
# 2. Create key with type "cli"
# 3. Copy key and store securely
# Use in CLI tool
grpcurl -H "x-api-key: YOUR_CLI_API_KEY" \
localhost:50051 api.users.UserService/GetUserWebhook Handlers
# Webhook service calling gRPC
# 1. Create API key with type "webhook"
# 2. Configure webhook handler
from django.views.decorators.csrf import csrf_exempt
import grpc
@csrf_exempt
def webhook_handler(request):
# Parse webhook data
data = json.loads(request.body)
# Call gRPC with API key
metadata = [('x-api-key', settings.WEBHOOK_GRPC_API_KEY)]
with grpc.insecure_channel('localhost:50051') as channel:
stub = ServiceStub(channel)
response = stub.Method(data, metadata=metadata)
return JsonResponse({'status': 'ok'})Development Testing
# Use Django SECRET_KEY for quick testing
# (Only works if accept_django_secret_key=True)
from django.conf import settings
metadata = [('x-api-key', settings.SECRET_KEY)]
response = stub.Method(request, metadata=metadata)Next Steps:
- Configuration - Complete auth config reference
- Getting Started - Build authenticated service
- FAQ - Authentication troubleshooting