Django HMAC authentication using shared secret
Project description
django_hmac_authentication
Django hmac authentication with multiple encrypted hmac secrets per user
:rocket: :rocket: Built on Debian, KDE and CI/CD on GitLab :penguin: :penguin: :rocket: :rocket:
Features
| # | 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. Chosen randomly from the two |
| 13 | test_mode for keys | Keys have test_mode flag in Django admin set to default False. Authenticated requests will have attribute api_hmac_key |
| 14 | Option to separate HMAC key definition password | HMAC_KD_PASSWORD to set explicit key definition password. Default is Django settings.SECRET_KEY |
What's new
a) Backward incompatible change from 5.0.0
API keys must be re-issued to users.
5.0.0usesvevde-security-utils 2.0.0 with pkcs7 padding
b) Optional separate HMAC key definition password using setting HMAC_KD_PASSWORD.
c) API keys have test_mode with default value False. This flag can be modified in Django admin. All authenticated
requests will have attribute api_hmac_key. API views can change behavior on request.api_hmac_key.test_mode flag. For example,
client apps can use test_mode keys to onboard i.e test-drive integration with backend and views can handle those test_mode
requests differently.
d) From version 4.0.0 hmac utility functions are refactored to new package vevde-security-utils.
Client apps and Fast API, Flask projects can use this new package to implement hmac authentication.
i.e. decoupling utilities from django package pip dependency.
1. Install
pip install django_hmac_authentication
2. Configuration
2.1 settings.py
See example configurations below.
1. In Django INSTALLED_APPS
Add django_hmac_authentication to INSTALLED_APPS
2. In REST_FRAMEWORK
Add HMAC authentication class to REST_FRAMEWORK settings dict.
3. Package specific settings in HMAC_AUTHENTICATION_SETTINGS
MAX_HMACS_PER_USERDefault: 10. Maximum hmac secrets per userHMAC_AUTH_REQUEST_TIMEOUTRequests earlier than this are rejected. Default:5in seconds- Optional settings
HMAC_AUTH_FAILED_ATTEMPTS_THRESHOLDMax attempts to authenticate after which key is auto-revokedHMAC_EXPIRES_INHMAC keys will auto-expire after this period in hours, minutes or seconds. Example'1h','5m','3600s'HMAC_CACHE_ALIASAlias of a cache backend in Django'sCACHESsettings. 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_SWITCHIf set, enables checking cache to force-reject requests for certain keys.HMAC_CACHE_ALIASmust 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.pyfor 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 configurationThrottlingAdd throttling class inREST_FRAMEWORK>DEFAULT_THROTTLE_CLASSESas
django_hmac_authentication.throttling.HMACApiKeyRateThrottle. Throttling uses cache andHMAC_CACHE_ALIASmust be set. By default all hmac keys are created with rate200/min. Rate can be changed on admin interface.HMAC_KD_PASSWORDA secure random string. If set, this will be used as key definition password. If not set, Djangosettings.SECRET_KEYis used as key definition password.Note: Fresh keys need to be allocated, if you set this to value different from
settings.SECRET_KEYin an existing project.
Example
HMAC_AUTHENTICATION_SETTINGS = {
'MAX_HMACS_PER_USER':10,
'HMAC_AUTH_REQUEST_TIMEOUT': 4,
# Optional configurations
# If needed use a different header for hmac signature in requests
'HMAC_AUTH_HEADER_NAME': 'HMAC_SIGNATURE',
# Set explicit key definition password to decouple from default Django settings.SECRET_KEY
'HMAC_KD_PASSWORD': 'Use a secure string here',
#
'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'
],
}
2.2 urls.py
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'),
...
]
2.3 Run migrations
python manage.py migrate django_hmac_authentication
3. Usage
3.1 Obtain HMAC key and secret
3.1.1 Using management command
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"}
3.1.2 Using curl
# 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"}
4. Sign requests client-side
4.1 Javascript client
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).
4.2 Python client
See example_django_project/example_python_client.py
5. Signature
5.1 How is it calculated
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
6. Authorization header
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'
7. Protecting user's hmac secret
HMAC_KD_PASSWORD / Django settings.SECRET_KEY salt per user
│ │ │
│ │ │
└───────────► pbkdf2_hmac ◄───────────┘ │
│ │
│ │
▼ │
256 bit key │
│ │
│ │
▼ │
encrypt user secret ◄───── aes/camellia │
▲ │
│ │
iv ◄─────────────────────┘
8. License
Apache2 License
9. Github
https://github.com/harisankar-krishna-swamy/django_hmac_authentication
10. See also
https://www.okta.com/au/identity-101/hmac/
https://docs.python.org/3/library/hashlib.html
#encryption #fileencryption #security #hmac #softwaresecurity #authentication #signature #symmetric #ciphers #hash #python
#django #fastapi #api #apisecurity
Project details
Release history Release notifications | RSS feed
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 django_hmac_authentication-5.0.3.tar.gz.
File metadata
- Download URL: django_hmac_authentication-5.0.3.tar.gz
- Upload date:
- Size: 23.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6fb5f0c2a10600cad1abb7b4a34b9a04d1bb8aab289f49722e1aa68a30848265
|
|
| MD5 |
a49ecdb9778951a7d34899898999d0ef
|
|
| BLAKE2b-256 |
d1332ea735451a71e079d51d22a71ffea8cd303fb1d9917fed8b3b22c564753c
|
File details
Details for the file django_hmac_authentication-5.0.3-py3-none-any.whl.
File metadata
- Download URL: django_hmac_authentication-5.0.3-py3-none-any.whl
- Upload date:
- Size: 27.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b13cc82598757b44c7f20af29af49c1ade1c76000161e920479117f5ff816e4c
|
|
| MD5 |
f1c5efec3776e6b9addca2cc7c572afb
|
|
| BLAKE2b-256 |
10e401eac5d2ff13aeed0907d8593b6baf2d5e34abec8cd3a857f69c7f56dbb5
|