import pyotp import otpauth from rest_framework import serializers, exceptions from otpauth.models import OTPSeed # For accessing / modifying the data -- currently unused 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 TokenSerializer(serializers.Serializer): name = serializers.CharField(max_length=128) realm = serializers.CharField(max_length=128) auth_name = serializers.CharField(max_length=128) auth_token = serializers.CharField(max_length=128) auth_realm = serializers.CharField(max_length=128) def create(self, validated_data): print("Trying to create") validated_data['seed'] = pyotp.random_base32() return OTPSeed.objects.create(**validated_data) def update(self, instance, validated_data): print("Trying to update") instance.name = validated_data.get('name', instance.name) instance.realm = validated_data.get('realm', instance.realm) instance.save() return instance def save(self): name_in = self.validated_data.get("name") realm_in = self.validated_data.get("realm") auth_token = self.validated_data.get("auth_token") auth_name = self.validated_data.get("auth_name") auth_realm = self.validated_data.get("auth_realm") print("auth: {}@'{}' {} + {})".format(auth_name, auth_realm, auth_token, self.validated_data)) # 1. Verify that the connection might authenticate try: db_instance = otpauth.models.OTPSeed.objects.get(name=auth_name, realm=auth_realm) except (OTPSeed.MultipleObjectsReturned, OTPSeed.DoesNotExist): print("does not exist") raise exceptions.AuthenticationFailed() totp = pyotp.TOTP(db_instance.seed) print("calculated token = {}".format(totp.now())) if not totp.verify(auth_token, valid_window=3): raise exceptions.AuthenticationFailed() return (db_instance, auth_token) # For verifying a token class VerifySerializer(TokenSerializer): verifyname = serializers.CharField(max_length=128) verifytoken = serializers.CharField(max_length=128) verifyrealm = serializers.CharField(max_length=128) token_name = 'verifytoken' name_name = 'verifyname' realm_name = 'verifyrealm' # token_name = 'token' # name_name = 'name' # realm_name = 'realm' # auth_token_name = 'auth_token' # auth_name_name = 'auth_name' # auth_realm_name = 'auth_realm'