Change login flow to better verify all relevant fields.
This commit is contained in:
parent
32a8b9c90d
commit
93a0e41f03
@ -244,19 +244,21 @@ class AuthenticationLoginChallengeSerializer(serializers.Serializer):
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationLoginSerializer(AuthenticationLoginChallengeSerializer):
|
class AuthenticationLoginSerializer(serializers.Serializer):
|
||||||
challenge = BinaryBase64Field()
|
response = BinaryBase64Field()
|
||||||
host = serializers.CharField()
|
|
||||||
signature = BinaryBase64Field()
|
signature = BinaryBase64Field()
|
||||||
|
|
||||||
def validate(self, data):
|
def create(self, validated_data):
|
||||||
host = self.context.get('host', None)
|
raise NotImplementedError()
|
||||||
if data['host'] != host:
|
|
||||||
raise serializers.ValidationError(
|
def update(self, instance, validated_data):
|
||||||
'Found wrong host name. Got: "{}" expected: "{}"'.format(data['host'], host))
|
raise NotImplementedError()
|
||||||
|
|
||||||
return super().validate(data)
|
|
||||||
|
class AuthenticationLoginInnerSerializer(AuthenticationLoginChallengeSerializer):
|
||||||
|
challenge = BinaryBase64Field()
|
||||||
|
host = serializers.CharField()
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ from .serializers import (
|
|||||||
AuthenticationSignupSerializer,
|
AuthenticationSignupSerializer,
|
||||||
AuthenticationLoginChallengeSerializer,
|
AuthenticationLoginChallengeSerializer,
|
||||||
AuthenticationLoginSerializer,
|
AuthenticationLoginSerializer,
|
||||||
|
AuthenticationLoginInnerSerializer,
|
||||||
CollectionSerializer,
|
CollectionSerializer,
|
||||||
CollectionItemSerializer,
|
CollectionItemSerializer,
|
||||||
CollectionItemRevisionSerializer,
|
CollectionItemRevisionSerializer,
|
||||||
@ -368,12 +369,17 @@ class AuthenticationViewSet(viewsets.ViewSet):
|
|||||||
def login(self, request):
|
def login(self, request):
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
serializer = AuthenticationLoginSerializer(
|
outer_serializer = AuthenticationLoginSerializer(data=request.data)
|
||||||
data=request.data, context={'host': request.get_host()})
|
if outer_serializer.is_valid():
|
||||||
|
response_raw = outer_serializer.validated_data['response']
|
||||||
|
response = json.loads(response_raw.decode())
|
||||||
|
signature = outer_serializer.validated_data['signature']
|
||||||
|
|
||||||
|
serializer = AuthenticationLoginInnerSerializer(data=response, context={'host': request.get_host()})
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
user = self.get_login_user(serializer)
|
user = self.get_login_user(serializer)
|
||||||
|
host = serializer.validated_data['host']
|
||||||
challenge = serializer.validated_data['challenge']
|
challenge = serializer.validated_data['challenge']
|
||||||
signature = serializer.validated_data['signature']
|
|
||||||
|
|
||||||
salt = user.userinfo.salt
|
salt = user.userinfo.salt
|
||||||
enc_key = self.get_encryption_key(salt)
|
enc_key = self.get_encryption_key(salt)
|
||||||
@ -387,11 +393,13 @@ class AuthenticationViewSet(viewsets.ViewSet):
|
|||||||
elif challenge_data['userId'] != user.id:
|
elif challenge_data['userId'] != user.id:
|
||||||
content = {'code': 'wrong_user', 'detail': 'This challenge is for the wrong user'}
|
content = {'code': 'wrong_user', 'detail': 'This challenge is for the wrong user'}
|
||||||
return Response(content, status=status.HTTP_400_BAD_REQUEST)
|
return Response(content, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
elif host != request.get_host():
|
||||||
|
detail = 'Found wrong host name. Got: "{}" expected: "{}"'.format(host, request.get_host())
|
||||||
|
content = {'code': 'wrong_host', 'detail': detail}
|
||||||
|
return Response(content, status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
host_hash = nacl.hash.blake2b(
|
|
||||||
serializer.validated_data['host'].encode(), encoder=nacl.encoding.RawEncoder)
|
|
||||||
verify_key = nacl.signing.VerifyKey(user.userinfo.pubkey, encoder=nacl.encoding.RawEncoder)
|
verify_key = nacl.signing.VerifyKey(user.userinfo.pubkey, encoder=nacl.encoding.RawEncoder)
|
||||||
verify_key.verify(challenge + host_hash, signature)
|
verify_key.verify(response_raw, signature)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'token': Token.objects.get_or_create(user=user)[0].key,
|
'token': Token.objects.get_or_create(user=user)[0].key,
|
||||||
|
Loading…
Reference in New Issue
Block a user