Django SNS handling and signals.
Project description
A Django library for handling and validating AWS SNS (Simple Notification Service) webhook messages with cryptographic signature verification and Django signals.
Features
Cryptographic Signature Verification - Validates SNS message authenticity using AWS certificates
Django Signals - Fire signals for subscription, unsubscription, and notification events
Auto-confirmation - Automatically confirms SNS subscriptions and unsubscriptions
Certificate Caching - Configurable caching of AWS signing certificates (default: 24 hours)
Minimal Dependencies - Only requires Django and cryptography; uses Python’s standard library for HTTP
Type Safety - Full type hints with Python 3.10+
Installation
pip install django-sns-signals
Requirements
Python 3.10+
Django 4.2+
cryptography ~=46.0.0
Quick Start
1. Add to your Django URLs
# urls.py
from django.urls import path
from django_sns_signals.views import sns_webhook
urlpatterns = [
path('sns/webhook/', sns_webhook, name='sns_webhook'),
]
2. Connect to Django Signals
# apps.py or signals.py
from django.apps import AppConfig
from django_sns_signals import sns_notification
def handle_notification(sender, notification_message, topic_arn, subject=None, **kwargs):
"""Handle SNS notifications"""
print(f"Received from {topic_arn}: {notification_message}")
# Your business logic here
class MyAppConfig(AppConfig):
def ready(self):
sns_notification.connect(handle_notification)
3. Configure SNS Topic (AWS Console)
Create an SNS topic in AWS
Add an HTTPS subscription with your webhook URL: https://yourdomain.com/sns/webhook/
The library will automatically confirm the subscription
Configuration
Optional Settings
Add to your Django settings.py:
# Optional: Configure signing certificate cache timeout (in seconds)
# Default: 86400 (24 hours)
SNS_SIGNING_CERT_CACHE_TIMEOUT = 86400
The certificate cache timeout controls how long AWS SNS signing certificates are cached. AWS rarely rotates these certificates, so a longer cache period (24 hours or more) is safe and reduces HTTP requests.
Architecture
Core Components
SNSSignatureValidator
Validates AWS SNS message signatures using cryptographic verification:
Verifies certificate URLs come from amazonaws.com domain
Implements certificate caching using Django’s cache framework
Builds canonical signing strings based on message type
Uses RSA PKCS1v15 padding with SHA1 hash (AWS SNS standard)
sns_webhook View
Django view function that handles SNS webhook POST requests:
CSRF exempt (AWS cannot provide CSRF tokens)
Validates message signatures before processing
Handles three message types:
SubscriptionConfirmation: Auto-confirms by fetching SubscribeURL
UnsubscribeConfirmation: Auto-confirms unsubscription by fetching SubscribeURL
Notification: Processes actual SNS notifications and fires signals
Returns appropriate HTTP status codes (200-499 range required by SNS)
Django Signals
The library fires Django signals for each SNS message type:
sns_subscription_confirmation
Fired after successful subscription confirmation.
Signal Parameters:
message (dict) - Full parsed SNS message
raw_message (bytes) - Raw request body
message_id (str) - Unique message identifier
topic_arn (str) - Topic ARN
subject (str | None) - Optional subject
timestamp (str) - Message timestamp
subscribe_url (str) - Subscription confirmation URL
token (str) - Subscription token
sns_unsubscribe_confirmation
Fired after successful unsubscribe confirmation.
Signal Parameters:
message (dict) - Full parsed SNS message
raw_message (bytes) - Raw request body
message_id (str) - Unique message identifier
topic_arn (str) - Topic ARN
subject (str | None) - Optional subject
timestamp (str) - Message timestamp
subscribe_url (str) - Unsubscribe confirmation URL
token (str) - Unsubscription token
sns_notification
Fired when a notification is received.
Signal Parameters:
message (dict) - Full parsed SNS message
raw_message (bytes) - Raw request body
message_id (str) - Unique message identifier
topic_arn (str) - Topic ARN
subject (str | None) - Optional subject
timestamp (str) - Message timestamp
notification_message (str) - The actual notification payload
unsubscribe_url (str) - URL to unsubscribe from topic
Usage Examples
Basic Notification Handler
from django_sns_signals import sns_notification
def handle_sns_notification(sender, notification_message, topic_arn, subject=None, **kwargs):
print(f"Topic: {topic_arn}")
print(f"Subject: {subject}")
print(f"Message: {notification_message}")
sns_notification.connect(handle_sns_notification)
Topic-Specific Handler
from django_sns_signals import sns_notification
import json
def handle_order_notifications(sender, notification_message, topic_arn, **kwargs):
if 'orders' not in topic_arn:
return # Ignore non-order topics
order_data = json.loads(notification_message)
process_order(order_data)
sns_notification.connect(handle_order_notifications)
Subscription Tracking
from django_sns_signals import sns_subscription_confirmation, sns_unsubscribe_confirmation
def log_subscription(sender, topic_arn, **kwargs):
print(f"Subscribed to: {topic_arn}")
def log_unsubscription(sender, topic_arn, **kwargs):
print(f"Unsubscribed from: {topic_arn}")
sns_subscription_confirmation.connect(log_subscription)
sns_unsubscribe_confirmation.connect(log_unsubscription)
Security
Message Signature Validation
All SNS messages are cryptographically validated before processing:
Extract SigningCertURL from SNS message
Validate URL hostname ends with .amazonaws.com
Fetch certificate (cached for performance)
Build canonical string-to-sign based on message type
Verify signature using certificate’s public key with PKCS1v15 padding and SHA1
Reject message if signature invalid
The library follows AWS best practices for SNS message verification as documented in the AWS SNS Developer Guide.
Development
Setup
# Clone the repository
git clone https://github.com/newadventures/django-sns-signals.git
cd django-sns-signals
# Install in development mode
pip install -e .
pip install -r requirements_dev.txt
Running Tests
# Run tests with pytest
pytest tests/
# Or with Django's test runner
python -m django test --settings=tests.settings
# Run with coverage
pytest --cov=django_sns_signals tests/
Code Quality
# Format and lint code
ruff check src/ tests/
ruff format src/ tests/
Building the Package
# Build distribution packages
python -m build
# Check package for PyPI compliance
twine check dist/*
License
BSD-3-Clause License - see LICENSE file for details.
Links
AWS SNS Documentation: https://docs.aws.amazon.com/sns/
Support
For issues and questions, please use the GitHub issue tracker.
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_sns_signals-0.1.tar.gz.
File metadata
- Download URL: django_sns_signals-0.1.tar.gz
- Upload date:
- Size: 12.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63eaa8bf7e1054cd2b6173f1e263d15490723001233b99c0d08167567eb27dcf
|
|
| MD5 |
5c2b70818dc60d09aeea5783298ed6e6
|
|
| BLAKE2b-256 |
6582b833b011fcb8935ba0a34eab50176e19ecf3fbdf444be0908580d96592b5
|
Provenance
The following attestation bundles were made for django_sns_signals-0.1.tar.gz:
Publisher:
publish-to-pypi.yml on newadventures/django-sns-signals
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_sns_signals-0.1.tar.gz -
Subject digest:
63eaa8bf7e1054cd2b6173f1e263d15490723001233b99c0d08167567eb27dcf - Sigstore transparency entry: 705316216
- Sigstore integration time:
-
Permalink:
newadventures/django-sns-signals@4e9606f1823d21328cb0b1e81e78a578cba494ff -
Branch / Tag:
refs/tags/0.1 - Owner: https://github.com/newadventures
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@4e9606f1823d21328cb0b1e81e78a578cba494ff -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_sns_signals-0.1-py3-none-any.whl.
File metadata
- Download URL: django_sns_signals-0.1-py3-none-any.whl
- Upload date:
- Size: 7.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69364d75a6fde9c915f722d4324afc6a95992d613d232bf1c21e29b0f1db6d5f
|
|
| MD5 |
bcb04f45fe49495143935335c9e30158
|
|
| BLAKE2b-256 |
7d01fdf634627364c3cdc2239ab608ad3b96f3dcbb7fc0d76680ef8220f89ba6
|
Provenance
The following attestation bundles were made for django_sns_signals-0.1-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on newadventures/django-sns-signals
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_sns_signals-0.1-py3-none-any.whl -
Subject digest:
69364d75a6fde9c915f722d4324afc6a95992d613d232bf1c21e29b0f1db6d5f - Sigstore transparency entry: 705316218
- Sigstore integration time:
-
Permalink:
newadventures/django-sns-signals@4e9606f1823d21328cb0b1e81e78a578cba494ff -
Branch / Tag:
refs/tags/0.1 - Owner: https://github.com/newadventures
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@4e9606f1823d21328cb0b1e81e78a578cba494ff -
Trigger Event:
release
-
Statement type: