import cryptography from django.contrib.auth.models import AnonymousUser from rest_framework import authentication from rest_framework import exceptions from . import actors from . import keys from . import serializers from . import signing class SignatureAuthentication(authentication.BaseAuthentication): def authenticate(self, request): try: signature = request.META['headers']['Signature'] key_id = keys.get_key_id_from_signature_header(signature) except KeyError: raise exceptions.AuthenticationFailed('No signature') except ValueError as e: raise exceptions.AuthenticationFailed(str(e)) try: actor_data = actors.get_actor_data(key_id) except Exception as e: raise exceptions.AuthenticationFailed(str(e)) try: public_key = actor_data['publicKey']['publicKeyPem'] except KeyError: raise exceptions.AuthenticationFailed('No public key found') serializer = serializers.ActorSerializer(data=actor_data) if not serializer.is_valid(): raise exceptions.AuthenticationFailed('Invalid actor payload') try: signing.verify_django(request, public_key.encode('utf-8')) except cryptography.exceptions.InvalidSignature: raise exceptions.AuthenticationFailed('Invalid signature') user = AnonymousUser() ac = serializer.build() setattr(request, 'actor', ac) return (user, None)