Bitcoin Cash OAuth - Django
Bitcoin Cash OAuth authentication for Django and Django REST Framework (DRF).
Installation
pip install bitcoincash-oauth-django
Add to INSTALLED_APPS:
INSTALLED_APPS = [
...
'bitcoincash_oauth_django',
]
Django Views Usage
URL Configuration
# urls.py
from django.urls import path
from bitcoincash_oauth_django import register, token, refresh, revoke, me
urlpatterns = [
path('auth/register', register, name='register'),
path('auth/token', token, name='token'),
path('auth/refresh', refresh, name='refresh'),
path('auth/revoke', revoke, name='revoke'),
path('auth/me', me, name='me'),
]
Custom View Instance
# urls.py
from django.urls import path
from bitcoincash_oauth_django import BitcoinCashOAuthViews
oauth = BitcoinCashOAuthViews(
token_ttl=3600,
refresh_token_ttl=2592000,
max_tokens_per_user=5
)
urlpatterns = [
path('auth/register', oauth.register_view, name='register'),
path('auth/token', oauth.token_view, name='token'),
path('auth/refresh', oauth.refresh_view, name='refresh'),
path('auth/revoke', oauth.revoke_view, name='revoke'),
path('auth/me', oauth.me_view, name='me'),
]
Django REST Framework Usage
URL Configuration
# urls.py
from django.urls import path
from bitcoincash_oauth_django.drf import (
RegisterView, TokenView, RefreshView, RevokeView, MeView
)
urlpatterns = [
path('auth/register', RegisterView.as_view(), name='register'),
path('auth/token', TokenView.as_view(), name='token'),
path('auth/refresh', RefreshView.as_view(), name='refresh'),
path('auth/revoke', RevokeView.as_view(), name='revoke'),
path('auth/me', MeView.as_view(), name='me'),
]
Protecting Views with DRF
from rest_framework.views import APIView
from rest_framework.response import Response
from bitcoincash_oauth_django.drf import IsBitcoinCashAuthenticated, HasScope
class ProtectedView(APIView):
permission_classes = [IsBitcoinCashAuthenticated]
def get(self, request):
# Access token data from request
user_id = request.token_data.user_id
scopes = request.token_data.scopes
return Response({
"user_id": user_id,
"scopes": scopes,
"message": "This is a protected resource"
})
class AdminView(APIView):
permission_classes = [IsBitcoinCashAuthenticated, HasScope]
required_scopes = ["admin"]
def get(self, request):
return Response({"message": "Admin only"})
Using with ViewSets
from rest_framework import viewsets
from rest_framework.decorators import action
from bitcoincash_oauth_django.drf import IsBitcoinCashAuthenticated
class MyViewSet(viewsets.ViewSet):
permission_classes = [IsBitcoinCashAuthenticated]
def list(self, request):
user_id = request.token_data.user_id
return Response({"user_id": user_id, "items": []})
API Endpoints
POST /auth/register
Register a new user with a Bitcoin Cash address. Signature verification is required to prove wallet ownership.
Request:
{
"bitcoincash_address": "bitcoincash:qqrxvhnn88gmpczyxry254vcsnl6canmkqgt98lpn5",
"user_id": "your_user_id",
"timestamp": 1234567890,
"domain": "app.example.com",
"public_key": "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
"signature": "3045022100..."
}
Message Format: bitcoincash-oauth|domain|userId|timestamp|register
bitcoincash-oauth: Protocol identifier (prevents cross-protocol replay)domain: Domain/host of the application (prevents phishing)userId: User's unique identifiertimestamp: Unix timestamp for replay protectionregister: Action identifier
Response:
{
"user_id": "user_abc123",
"address": "bitcoincash:qqrxvhnn88gmpczyxry254vcsnl6canmkqgt98lpn5",
"message": "User registered successfully"
}
POST /auth/token
Obtain an OAuth token using Bitcoin Cash signature. The client must sign the message in the format bitcoincash-oauth|domain|userId|timestamp.
Request:
{
"user_id": "user_abc123",
"timestamp": 1234567890,
"domain": "app.example.com",
"public_key": "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
"signature": "3045022100...",
"scopes": ["read", "write"]
}
Message Format: bitcoincash-oauth|domain|userId|timestamp
bitcoincash-oauth: Protocol identifier (prevents cross-protocol replay)domain: Domain/host of the application (prevents phishing)userId: User's unique identifiertimestamp: Unix timestamp for replay protection
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...",
"scopes": ["read", "write"]
}
POST /auth/refresh
Refresh an access token.
Request:
{
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g..."
}
POST /auth/revoke
Revoke an access token.
Request:
{
"token": "eyJhbGciOiJIUzI1NiIs..."
}
GET /auth/me
Get current user information (requires Bearer token).
Headers:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Advanced Usage
Using the Validator Directly
from bitcoincash_oauth_django import BitcoinCashValidator, verify_bitcoin_cash_auth
# Validate a CashAddr
is_valid, network = BitcoinCashValidator.validate_cash_address(
"bitcoincash:qqrxvhnn88gmpczyxry254vcsnl6canmkqgt98lpn5"
)
# Verify authentication with domain binding
is_valid, reason = verify_bitcoin_cash_auth(
user_id="user_123",
timestamp=1234567890,
public_key="0279BE...",
signature="3045...",
expected_address="bitcoincash:qz7f...",
domain="app.example.com" # Optional: prevents phishing across domains
)
# Convert public key to address
address = BitcoinCashValidator.public_key_to_cash_address(
bytes.fromhex("0279BE..."),
network="mainnet"
)
Custom Token Manager
from bitcoincash_oauth_django import TokenManager, token_manager
# Configure the singleton token manager
token_manager.access_token_ttl = 7200 # 2 hours
token_manager.max_tokens_per_user = 10
# Or create your own instance
custom_manager = TokenManager(
access_token_ttl=7200,
refresh_token_ttl=604800, # 7 days
max_tokens_per_user=10
)
DRF Permission Classes
| Permission Class | Description |
|---|---|
IsBitcoinCashAuthenticated |
Validates Bearer token and attaches token_data to request |
HasScope |
Checks if user has required OAuth scopes |
Configuration
# settings.py
# Optional: Configure token settings
BITCOINCASH_OAUTH = {
'TOKEN_TTL': 3600, # 1 hour
'REFRESH_TOKEN_TTL': 2592000, # 30 days
'MAX_TOKENS_PER_USER': 5,
}
| Setting | Default | Description |
|---|---|---|
TOKEN_TTL |
3600 |
Access token lifetime (seconds) |
REFRESH_TOKEN_TTL |
2592000 |
Refresh token lifetime (seconds) |
MAX_TOKENS_PER_USER |
5 |
Maximum active tokens per user |
MAX_TIMESTAMP_DIFF |
300 |
Max timestamp age for replay protection (seconds) |
Custom Models (Avoiding Conflicts)
If your project already has models named BitcoinCashUser or OAuthToken, you can use custom models:
# settings.py
BITCOINCASH_OAUTH = {
'USER_MODEL': 'myapp.MyBitcoinCashUser', # Your custom user model
'TOKEN_MODEL': 'myapp.MyOAuthToken', # Your custom token model
}
Your custom models should inherit from the base models:
# myapp/models.py
from bitcoincash_oauth_django.models import BitcoinCashUser, OAuthToken
class MyBitcoinCashUser(BitcoinCashUser):
# Add your custom fields
custom_field = models.CharField(max_length=100)
class MyOAuthToken(OAuthToken):
# Add your custom fields
custom_data = models.JSONField(default=dict)
Note: When using custom models, do NOT add bitcoincash_oauth_django to INSTALLED_APPS. Instead:
# settings.py
INSTALLED_APPS = [
# 'bitcoincash_oauth_django', # Don't add this
'myapp', # Add your app with the custom models
]
# Keep the URLs
urlpatterns = [
path('auth/', include('bitcoincash_oauth_django.urls')),
]
Dependencies
django>=4.0djangorestframework>=3.14.0coincurve>=18.0.0cashaddress>=1.0.6PyJWT>=2.8.0
License
MIT
Metadata
Release files for bitcoincash-oauth-django 0.2.11
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 |
|---|---|---|---|---|
| bitcoincash_oauth_django-0.2.11.tar.gz | 31.4 kB | Without provenance | Details for bitcoincash_oauth_django-0.2.11.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| bitcoincash_oauth_django-0.2.11-py3-none-any.whl | Python 3 | none | any | Details for bitcoincash_oauth_django-0.2.11-py3-none-any.whl |
Total release size: 75.9 kB
Release files / bitcoincash_oauth_django-0.2.11.tar.gz
| Download URL | bitcoincash_oauth_django-0.2.11.tar.gz |
|---|---|
| Size | 31.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8d64764883c2110d192d926439b23e0b864d80957267744b8e1592153e93b2f3
|
|
BLAKE2b-256 checksum How to use checksums |
80c68fa1cd1522e500b7d4d20feee2cf6787a802484c15c0c52bb50953d48233
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.8
|
Release files / bitcoincash_oauth_django-0.2.11-py3-none-any.whl
| Download URL | bitcoincash_oauth_django-0.2.11-py3-none-any.whl |
|---|---|
| Size | 44.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3a83c761d855898e2eee3354414a1d124f3a90a8213f238240e2998e5d6eda93
|
|
BLAKE2b-256 checksum How to use checksums |
414df65f0f748b508aebfcac8332b05ea7c9bb35886e37ee4627e3ce8ffd8a44
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.8
|
Security for bitcoincash-oauth-django 0.2.11
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.