ungleich-otp/ungleichotp/otpauth/serializer.py

82 lines
2.9 KiB
Python

from rest_framework import serializers, exceptions
from otpauth.models import OTPSeed
import pyotp
import otpauth
class OTPSerializer(serializers.ModelSerializer):
class Meta:
model = OTPSeed
fields = ('name', 'realm', 'seed')
read_only_fields = ('seed',)
def create(self, validated_data):
validated_data['seed'] = pyotp.random_base32()
return OTPSeed.objects.create(**validated_data)
class VerifySerializer(serializers.Serializer):
name = serializers.CharField(max_length=128)
token = serializers.CharField(max_length=128)
realm = serializers.CharField(max_length=128)
verifyname = serializers.CharField(max_length=128)
verifytoken = serializers.CharField(max_length=128)
verifyrealm = serializers.CharField(max_length=128)
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')
# 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()
# 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)
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()
return db_instance