django-sns-signals
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.
Metadata
Release files for django-sns-signals 0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| django_sns_signals-0.1.tar.gz | 12.6 kB | With provenance | Details for django_sns_signals-0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| django_sns_signals-0.1-py3-none-any.whl | Python 3 | none | any | Details for django_sns_signals-0.1-py3-none-any.whl |
Total release size: 20.5 kB
Release files / django_sns_signals-0.1.tar.gz
| Download URL | django_sns_signals-0.1.tar.gz |
|---|---|
| Size | 12.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
63eaa8bf7e1054cd2b6173f1e263d15490723001233b99c0d08167567eb27dcf
|
|
BLAKE2b-256 checksum How to use checksums |
6582b833b011fcb8935ba0a34eab50176e19ecf3fbdf444be0908580d96592b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 17, 2025.
Transparency logRelease files / django_sns_signals-0.1-py3-none-any.whl
| Download URL | django_sns_signals-0.1-py3-none-any.whl |
|---|---|
| Size | 7.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
69364d75a6fde9c915f722d4324afc6a95992d613d232bf1c21e29b0f1db6d5f
|
|
BLAKE2b-256 checksum How to use checksums |
7d01fdf634627364c3cdc2239ab608ad3b96f3dcbb7fc0d76680ef8220f89ba6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 17, 2025.
Transparency logSecurity for django-sns-signals 0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for django_sns_signals-0.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 17, 2025.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.