Django hmac authentication with multiple encrypted hmac secrets per user
π π Built on Debian, KDE and CI/CD on GitLab π§ π§ π π
# | Feature | Description |
---|---|---|
1 | Multiple hmac secrets per user | Each secret is protected with a separate key |
2 | Django Model and Authentication | Django ApiHMACKey and Authentication classes HMACAuthentication for Django Rest Framework |
3 | Obtain credentials | Django management command or a configured url to get credentials |
4 | Reject stale requests | Reject requests earlier than configured timeout and also with future timestamps |
5 | Supported HMAC hash functions | HMAC-SHA512 , HMAC-SHA384 , HMAC-SHA256 |
6 | Clients | Javascript and Python clients for programmatic access. See example_django_project and Postman collections |
7 | Auto-Revoke | Optional configuration to auto revoke keys after N failed attempts to authenticate |
8 | Auto-Expire | Optional HMAC_EXPIRES_IN configuration. If set HMAC keys will expire after interval |
9 | Performance (Caching) | * Option to speedup using a cache in Django's CACHES settings. * A lru_cache is enabled locally to save compute time to decode hmac key |
10 | Kill switch | An out-of-band capability to reject requests |
11 | Throttling | Throttling requests on hmac key used |
12 | Supported encryption ciphers | AES-256 , CAMELLIA-256 to encrypt user's hmac secrets |
Camellia 256 cipher is used along with aes. Package now picks one of AES-256 or Camellia-256 to secure users' HMAC secrets at runtime. Encryption now has two algorithms instead of just one. Client side changes not required. To use new feature just update package and run migrations.
pip install django_hmac_authentication
See example configurations below.
Add django_hmac_authentication
to INSTALLED_APPS
Add HMAC authentication class to REST_FRAMEWORK settings dict.
MAX_HMACS_PER_USER
Default: 10
. Maximum hmac secrets per userHMAC_AUTH_REQUEST_TIMEOUT
Requests earlier than this are rejected. Default:5
in seconds- Optional settings
HMAC_AUTH_FAILED_ATTEMPTS_THRESHOLD
Max attempts to authenticate after which key is auto-revokedHMAC_EXPIRES_IN
HMAC keys will auto-expire after this period in hours, minutes or seconds. Example'1h'
,'5m'
,'3600s'
HMAC_CACHE_ALIAS
Alias of a cache backend in Django'sCACHES
settings. When set, the cache specified by the alias is used to cache hmac keys. Example:hmac_cache
. Default: None (i.e caching disabled)HMAC_KILL_SWITCH
If set, enables checking cache to force-reject requests for certain keys.HMAC_CACHE_ALIAS
must be set.Note: The hmac keys in this package can be disabled and enabled using the admin interface. This switch helps when that option is not feasible and out of band intervention is needed. See
example_django_project/scripts/out_of_band_hmac_kill_switch.py
for a sample program that demonstrates switching keys on/off. Depending on cache backend used and CACHES configuration in settings.py, the cache key needs to be formatted. See Django cache key formatting based on configurationThrottling
Add throttling class inREST_FRAMEWORK
>DEFAULT_THROTTLE_CLASSES
as
django_hmac_authentication.throttling.HMACApiKeyRateThrottle
. Throttling uses cache andHMAC_CACHE_ALIAS
must be set. By default all hmac keys are created with rate200/min
. Rate can be changed on admin interface.
HMAC_AUTHENTICATION_SETTINGS = {
'MAX_HMACS_PER_USER':10,
'HMAC_AUTH_REQUEST_TIMEOUT': 4,
# Optional configurations
'HMAC_AUTH_FAILED_ATTEMPTS_THRESHOLD': 10,
'HMAC_EXPIRES_IN': '5m',
# This cache alias must be defined in Django's CACHES.
# See https://docs.djangoproject.com/en/4.2/ref/settings/#caches
'HMAC_CACHE_ALIAS': 'hmac_cache',
'HMAC_KILL_SWITCH': True
}
INSTALLED_APPS = [
...,
'rest_framework',
'django_hmac_authentication',
...
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
# Add authentication class
'django_hmac_authentication.authentication.HMACAuthentication',
],
# Throttling
'DEFAULT_THROTTLE_CLASSES': [
'django_hmac_authentication.throttling.HMACApiKeyRateThrottle'
],
}
Add url to obtain HMAC key and secret
...
from django_hmac_authentication.views import CreateApiHMACKey
urlpatterns = [
...,
# django_hmac_authentication
path('obtain-hmac-api-key/',
CreateApiHMACKey.as_view(),
name='api_hmac_key'),
...
]
python manage.py migrate django_hmac_authentication
Use management command to create a HMAC API key with secret for a user
python manage.py create_hmac_for_user bob
{"api_key": "f4c3801c-a277-4fcb-92bb-44cb814026f6", "api_secret": "vEOQRdvaK4jyeLKGNP9oqpYTUvt/GZWbGG6iNmnDh8c=", "message": "These credentials will be lost forever if not stored now"}
# Use the url from configuration
curl -X POST -H "Content-Type: application/json" -d '{"username":"bob", "password":"bobspassword"}' http://127.0.0.1:8000/obtain-hmac-api-key/
{"api_key":"7ebc25d7-d237-4f90-b4ad-98f0c228fc1e","api_secret":"EDQppq0B3rIxvaA7PyPUHPF6kiXTnnbvnMiZDzYFSRA=","message":"These credentials will be lost forever if not stored now"}
See example_django_project/javascript_topman_collection
folder
A postman collection with environment is provided which can be imported to Postman. A prerequest script for generating the signature is provided (same as included in postman collection).
See example_django_project/example_python_client.py
Signature is calculated on hash( request body json ) + utc 8601
request data
β
βΌ
json
β
βΌ
hash + ; + utc 8601
βββββββββββββ¬βββββββββββββ
β
βΌ
signature
- Hash function is one of supported methods in Authorization header
- UTC time now in ISO 8601 format. Example
2023-05-07T14:15:37.862560+00:00
Syntax
: METHOD
api_key;signature;request_utc_8601
- method: One of
HMAC-SHA512
,HMAC-SHA384
,HMAC-SHA256
- api_key: Key used to identify the hmac secret used to generate signature
- signature: base64 signature
- request_utc: time in ISO 8601 set in signed string
Example
'HMAC-SHA512 aa733037-e4c0-4f75-a864-df6c1966481b;6k3XaUREI6dDw6thyQWASJjzjsx1M7GOZAglguv0OElpRue1+gb7CK2n3JpzJGz9VcREw2y3rIW5zoZYEUY+0w==;2023-05-07T14:15:37.862560+00:00'
Django settings.SECRET_KEY salt per user
β β β
β β β
βββββββββββββΊ pbkdf2_hmac ββββ β
β β
β β
βΌ β
256 bit key β
β β
β β
βΌ β
encrypt user secret ββββββ aes/camellia β
β² β
β β
iv ββββββββββββββ
Apache2 License
https://github.com/harisankar-krishna-swamy/django_hmac_authentication
https://www.okta.com/au/identity-101/hmac/