ungleich-otp/ungleichotp/otpauth/serializer.py

98 lines
3.3 KiB
Python
Raw Normal View History

2018-11-17 16:46:16 +00:00
from rest_framework import serializers, exceptions
2018-11-17 10:21:35 +00:00
from otpauth.models import OTPSeed
import pyotp
2018-11-17 16:46:16 +00:00
import otpauth
2018-11-17 10:21:35 +00:00
class OTPSerializer(serializers.ModelSerializer):
class Meta:
model = OTPSeed
2018-11-17 21:15:17 +00:00
fields = ('name', 'realm', 'seed')
read_only_fields = ('seed',)
2018-11-17 21:28:17 +00:00
def create(self, validated_data):
2018-11-17 21:53:51 +00:00
validated_data['seed'] = pyotp.random_base32()
2018-11-17 21:28:17 +00:00
return OTPSeed.objects.create(**validated_data)
2018-11-17 10:21:35 +00:00
2018-11-18 12:24:09 +00:00
class VerifySerializerV1(serializers.Serializer):
"""
This is the first version of the serializer that would authenticate the request
itself. This is not necessary anymore starting from version 0.5
Code to be removed prior to 1.0
"""
2018-11-17 16:46:16 +00:00
name = serializers.CharField(max_length=128)
2018-11-17 10:21:35 +00:00
token = serializers.CharField(max_length=128)
2018-11-17 16:46:16 +00:00
realm = serializers.CharField(max_length=128)
2018-11-17 10:21:35 +00:00
verifyname = serializers.CharField(max_length=128)
verifytoken = serializers.CharField(max_length=128)
verifyrealm = serializers.CharField(max_length=128)
2018-11-17 21:53:51 +00:00
def save(self):
token_in = self.validated_data.get('token')
name_in = self.validated_data.get('name')
realm_in = self.validated_data.get('realm')
verifytoken = self.validated_data.get('verifytoken')
verifyname = self.validated_data.get('verifyname')
verifyrealm = self.validated_data.get('verifyrealm')
2018-11-17 17:48:12 +00:00
# 1. Verify that the connection might authenticate
2018-11-17 10:21:35 +00:00
try:
2018-11-17 10:39:42 +00:00
db_instance = otpauth.models.OTPSeed.objects.get(name=name_in, realm=realm_in)
except (OTPSeed.MultipleObjectsReturned, OTPSeed.DoesNotExist):
2018-11-17 17:48:12 +00:00
raise exceptions.AuthenticationFailed()
2018-11-17 10:39:42 +00:00
totp = pyotp.TOTP(db_instance.seed)
2018-11-17 10:21:35 +00:00
2018-11-17 17:48:12 +00:00
if not totp.verify(token_in, valid_window=3):
raise exceptions.AuthenticationFailed()
# 2. Verify the requested data
try:
verifyinstance = otpauth.models.OTPSeed.objects.get(name=verifyname, realm=verifyrealm)
except (OTPSeed.MultipleObjectsReturned, OTPSeed.DoesNotExist):
raise exceptions.PermissionDenied()
totp = pyotp.TOTP(verifyinstance.seed)
if not totp.verify(verifytoken, valid_window=3):
raise exceptions.PermissionDenied()
print("All verified!")
return verifyinstance
class TokenSerializer(serializers.Serializer):
name = serializers.CharField(max_length=128)
token = serializers.CharField(max_length=128)
realm = serializers.CharField(max_length=128)
2018-11-18 12:24:09 +00:00
token_name = 'token'
name_name = 'name'
realm_name = 'realm'
def save(self):
token_in = self.validated_data.get('token')
name_in = self.validated_data.get('name')
realm_in = self.validated_data.get('realm')
# 1. Verify that the connection might authenticate
try:
db_instance = otpauth.models.OTPSeed.objects.get(name=name_in, realm=realm_in)
except (OTPSeed.MultipleObjectsReturned, OTPSeed.DoesNotExist):
raise exceptions.AuthenticationFailed()
totp = pyotp.TOTP(db_instance.seed)
if not totp.verify(token_in, valid_window=3):
raise exceptions.AuthenticationFailed()
2018-11-18 12:05:21 +00:00
return (db_instance, token_in)
2018-11-18 12:24:09 +00:00
class VerifySerializer(TokenSerializer):
token_name = 'verifytoken'
name_name = 'verifyname'
realm_name = 'verifyrealm'