Authentication: move to msgpack for the encrypted parts.
This commit is contained in:
parent
85de674ee2
commit
453275eadf
@ -64,6 +64,15 @@ class BinaryBase64Field(serializers.Field):
|
||||
return b64decode(data)
|
||||
|
||||
|
||||
# This field does nothing to the data. It's useful for raw binary data
|
||||
class RawField(serializers.Field):
|
||||
def to_representation(self, value):
|
||||
return value
|
||||
|
||||
def to_internal_value(self, data):
|
||||
return data
|
||||
|
||||
|
||||
class CollectionEncryptionKeyField(BinaryBase64Field):
|
||||
def get_attribute(self, instance):
|
||||
request = self.context.get('request', None)
|
||||
@ -413,7 +422,7 @@ class AuthenticationLoginSerializer(serializers.Serializer):
|
||||
|
||||
|
||||
class AuthenticationLoginInnerSerializer(AuthenticationLoginChallengeSerializer):
|
||||
challenge = BinaryBase64Field()
|
||||
challenge = RawField()
|
||||
host = serializers.CharField()
|
||||
action = serializers.CharField()
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
import msgpack
|
||||
from functools import reduce
|
||||
|
||||
from django.conf import settings
|
||||
@ -72,6 +72,14 @@ from .serializers import (
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
def msgpack_encode(content):
|
||||
return msgpack.packb(content, use_bin_type=True)
|
||||
|
||||
|
||||
def msgpack_decode(content):
|
||||
return msgpack.unpackb(content, raw=False)
|
||||
|
||||
|
||||
class BaseViewSet(viewsets.ModelViewSet):
|
||||
authentication_classes = tuple(app_settings.API_AUTHENTICATORS)
|
||||
permission_classes = tuple(app_settings.API_PERMISSIONS)
|
||||
@ -638,7 +646,7 @@ class AuthenticationViewSet(viewsets.ViewSet):
|
||||
enc_key = self.get_encryption_key(salt)
|
||||
box = nacl.secret.SecretBox(enc_key)
|
||||
|
||||
challenge_data = json.loads(box.decrypt(challenge).decode())
|
||||
challenge_data = msgpack_decode(box.decrypt(challenge))
|
||||
now = int(datetime.now().timestamp())
|
||||
if action != expected_action:
|
||||
content = {'code': 'wrong_action', 'detail': 'Expected "{}" but got something else'.format(expected_action)}
|
||||
@ -680,8 +688,7 @@ class AuthenticationViewSet(viewsets.ViewSet):
|
||||
"timestamp": int(datetime.now().timestamp()),
|
||||
"userId": user.id,
|
||||
}
|
||||
challenge = box.encrypt(json.dumps(
|
||||
challenge_data, separators=(',', ':')).encode(), encoder=nacl.encoding.RawEncoder)
|
||||
challenge = box.encrypt(msgpack_encode(challenge_data), encoder=nacl.encoding.RawEncoder)
|
||||
|
||||
ret = {
|
||||
"salt": b64encode(salt),
|
||||
@ -698,10 +705,11 @@ class AuthenticationViewSet(viewsets.ViewSet):
|
||||
outer_serializer.is_valid(raise_exception=True)
|
||||
|
||||
response_raw = outer_serializer.validated_data['response']
|
||||
response = json.loads(response_raw.decode())
|
||||
response = msgpack_decode(response_raw)
|
||||
signature = outer_serializer.validated_data['signature']
|
||||
|
||||
serializer = AuthenticationLoginInnerSerializer(data=response, context={'host': request.get_host()})
|
||||
context = {'host': request.get_host(), 'supports_binary': True}
|
||||
serializer = AuthenticationLoginInnerSerializer(data=response, context=context)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
bad_login_response = self.validate_login_request(
|
||||
@ -730,11 +738,11 @@ class AuthenticationViewSet(viewsets.ViewSet):
|
||||
outer_serializer.is_valid(raise_exception=True)
|
||||
|
||||
response_raw = outer_serializer.validated_data['response']
|
||||
response = json.loads(response_raw.decode())
|
||||
response = msgpack_decode(response_raw)
|
||||
signature = outer_serializer.validated_data['signature']
|
||||
|
||||
serializer = AuthenticationChangePasswordInnerSerializer(
|
||||
request.user.userinfo, data=response, context={'host': request.get_host()})
|
||||
context = {'host': request.get_host(), 'supports_binary': True}
|
||||
serializer = AuthenticationChangePasswordInnerSerializer(request.user.userinfo, data=response, context=context)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
bad_login_response = self.validate_login_request(
|
||||
|
@ -4,5 +4,6 @@ django-cors-headers
|
||||
django-fullurl
|
||||
djangorestframework
|
||||
drf-nested-routers
|
||||
msgpack
|
||||
psycopg2-binary
|
||||
pynacl
|
||||
|
@ -15,6 +15,7 @@ django==3.0.3 # via -r requirements.in/base.txt, django-anymail, dja
|
||||
djangorestframework==3.11.0 # via -r requirements.in/base.txt, drf-nested-routers
|
||||
drf-nested-routers==0.91 # via -r requirements.in/base.txt
|
||||
idna==2.8 # via requests
|
||||
msgpack==1.0.0 # via -r requirements.in/base.txt
|
||||
psycopg2-binary==2.8.4 # via -r requirements.in/base.txt
|
||||
pycparser==2.20 # via cffi
|
||||
pynacl==1.3.0 # via -r requirements.in/base.txt
|
||||
|
Loading…
Reference in New Issue
Block a user