Django HMAC authentication using shared secret
Project description
django_hmac_authentication
Django hmac authentication with shared secret
- Django model with HMAC shared secret
- Each user's shared secret is protected with separate key
- Authentication class
HMACAuthentication
- Reject requests earlier than configured timeout
- Supports
HMAC-SHA512
,HMAC-SHA384
,HMAC-SHA256
- HMAC secret can be created with management command or obtained with a configured url
- Supports Javascript and Python clients for programmatic access
- Optional configuration to auto revoke keys after N failed attempts to authenticate
- Optional
HMAC_EXPIRES_IN
configuration. If set HMAC keys will expire after interval.
New features
- Option to speedup using cache in Django's
CACHES
settings. - A lru_cache is enabled locally to save compute time to decode hmac keys
:rocket: :rocket: Built on Debian, KDE and CI/CD on GitLab :rocket: :rocket:
1. Install
pip install django_hmac_authentication
2. Configuration
2.1 settings.py
- Add
MAX_HMACS_PER_USER
Default: 10 - Add
HMAC_AUTH_REQUEST_TIMEOUT
in seconds. Requests earlier than this are rejected Default:5
- Add
django_hmac_authentication
to installed apps along withrest_framework
. - Add hmac authentication class to
REST_FRAMEWORK
insettings.py
.
Optional configurations:
-
HMAC_AUTH_FAILED_ATTEMPTS_THRESHOLD
for maximum tolerated failed attempts. Setting this value will enable revoking keys that exceed max failed attempts. -
HMAC_EXPIRES_IN
to expire keys after interval 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)
Example
MAX_HMACS_PER_USER = 10
HMAC_AUTH_REQUEST_TIMEOUT = 4
INSTALLED_APPS = [
...,
'rest_framework',
'django_hmac_authentication',
...
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'django_hmac_authentication.authentication.HMACAuthentication',
],
}
# 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'
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
Django settings.SECRET_KEY salt per user
│ │ │
│ │ │
└───────────► pbkdf2_hmac ◄──┘ │
│ │
│ │
▼ │
aes 256 bit key │
│ │
│ │
▼ │
enc user secret ◄──────── aes │
▲ │
│ │
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/
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
Hashes for django_hmac_authentication-1.4.1.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5265d655a60de11af10d745b72b5e64d798f991e4574cfdbfe888d0489e1c29b |
|
MD5 | 02118ba6a72bea38acf20b9d5cea81db |
|
BLAKE2b-256 | ad51a12f2f5022badca459cae44e8239d766d4fdf53b0a5ee078a93e0b93be9a |
Hashes for django_hmac_authentication-1.4.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0426dfceadbea643e5e1ebff5efadabebdc6ae57100c285f54ed557be77930b7 |
|
MD5 | c780882a1d723aa491ca2ccc9025866d |
|
BLAKE2b-256 | 28724454344f528c434c3178f1f7853830b5439f048bb4f15952a37257c0c162 |