Skip to main content

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.0 uses vevde-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_USER Default: 10. Maximum hmac secrets per user
  • HMAC_AUTH_REQUEST_TIMEOUT Requests earlier than this are rejected. Default: 5 in seconds
  • Optional settings
    • HMAC_AUTH_FAILED_ATTEMPTS_THRESHOLDMax attempts to authenticate after which key is auto-revoked
    • HMAC_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's CACHES 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 configuration

    • Throttling Add throttling class in REST_FRAMEWORK > DEFAULT_THROTTLE_CLASSES as
      django_hmac_authentication.throttling.HMACApiKeyRateThrottle. Throttling uses cache and HMAC_CACHE_ALIAS must be set. By default all hmac keys are created with rate 200/min. Rate can be changed on admin interface.
    • HMAC_KD_PASSWORD A secure random string. If set, this will be used as key definition password. If not set, Django settings.SECRET_KEY is used as key definition password.

      Note: Fresh keys need to be allocated, if you set this to value different from settings.SECRET_KEY in 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

https://learn.microsoft.com/en-us/azure/communication-services/tutorials/hmac-header-tutorial?pivots=programming-language-python

#encryption #fileencryption #security #hmac #softwaresecurity #authentication #signature #symmetric #ciphers #hash #python
#django #fastapi #api #apisecurity

Release files for django-hmac-authentication 5.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-hmac-authentication 5.0.3
File Size Uploaded
django_hmac_authentication-5.0.3.tar.gz 23.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-hmac-authentication 5.0.3
File Interpreter ABI Platform
django_hmac_authentication-5.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 50.2 kB

Release files / django_hmac_authentication-5.0.3.tar.gz

Download URL django_hmac_authentication-5.0.3.tar.gz
Size 23.0 kB
Tags Source
SHA-256 checksum
How to use checksums
6fb5f0c2a10600cad1abb7b4a34b9a04d1bb8aab289f49722e1aa68a30848265
BLAKE2b-256 checksum
How to use checksums
d1332ea735451a71e079d51d22a71ffea8cd303fb1d9917fed8b3b22c564753c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.10.12

Release files / django_hmac_authentication-5.0.3-py3-none-any.whl

Download URL django_hmac_authentication-5.0.3-py3-none-any.whl
Size 27.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b13cc82598757b44c7f20af29af49c1ade1c76000161e920479117f5ff816e4c
BLAKE2b-256 checksum
How to use checksums
10e401eac5d2ff13aeed0907d8593b6baf2d5e34abec8cd3a857f69c7f56dbb5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.10.12

Release history Release notifications | RSS feed

This release

5.0.3 This release

2 release files

5.0.2

2 release files

5.0.1

2 release files

4.2.0

2 release files

4.1.0

2 release files

4.0.0

2 release files

3.1.0

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.2.0

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page