django-cryptolock/django_cryptolock/backends.py

80 lines
2.5 KiB
Python
Raw Normal View History

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from monerorpc.authproxy import AuthServiceProxy, JSONRPCException
from .models import Address
2020-03-10 16:00:11 +01:00
from .utils import verify_monero_signature, verify_bitcoin_signature
User = get_user_model()
class MoneroAddressBackend(ModelBackend):
"""Custom Monero-Cryptolock authentication backend."""
def authenticate(
self, request, address=None, challenge=None, signature=None, **kwargs
):
"""Validates the provided signature for the given address and challenge.
This method currently relies on Wallet RPC access to verify the signature,
in the future it should be done locally to be more reliable and more
performant.
"""
if not all([address, challenge, signature]):
return None
stored_address = (
Address.objects.select_related("user")
.filter(address=address, network=Address.NETWORK_MONERO)
.first()
)
if not stored_address:
return None
try:
2020-03-10 16:00:11 +01:00
is_valid = verify_monero_signature(
stored_address.address, challenge, signature
)
except JSONRPCException:
raise PermissionDenied(_("Error while validating signature"))
if is_valid:
return stored_address.user
return None
2020-02-19 16:04:19 +01:00
class BitcoinAddressBackend(ModelBackend):
"""Custom Bitcoin-BitId authentication backend."""
def authenticate(
2020-03-10 16:00:11 +01:00
self, request, address=None, challenge=None, signature=None, **kwargs
2020-02-19 16:04:19 +01:00
):
"""
Validates the provided signature for the given Bitcoin address and challenge.
This method does not rely on any external components, everything is done locally.
"""
2020-03-10 16:00:11 +01:00
if not all([address, challenge, signature]):
return None
stored_address = (
Address.objects.select_related("user")
.filter(address=address, network=Address.NETWORK_BITCOIN)
.first()
)
if not stored_address:
return None
2020-03-10 16:00:11 +01:00
valid_signature = verify_bitcoin_signature(
stored_address.address, challenge, signature, request
)
if valid_signature:
return stored_address.user
else:
return None