64 lines
1.9 KiB
Python
64 lines
1.9 KiB
Python
from django.contrib.auth.models import User
|
|
from rest_framework import authentication, exceptions, serializers
|
|
|
|
import urllib.request
|
|
import pyotp
|
|
import json
|
|
|
|
# For parsing
|
|
class TokenSerializer(serializers.Serializer):
|
|
name = serializers.CharField(max_length=128)
|
|
token = serializers.CharField(max_length=128)
|
|
realm = serializers.CharField(max_length=128)
|
|
|
|
token_name = 'token'
|
|
name_name = 'name'
|
|
realm_name = 'realm'
|
|
|
|
def __init__(self, name, realm, seed, serverurl, *args, **kwargs):
|
|
self.name = name
|
|
self.realm = realm
|
|
self.seed = seed
|
|
self.serverurl = serverurl
|
|
|
|
super(serializers.Serializer, self).__init__(*args, **kwargs)
|
|
|
|
def save(self):
|
|
to_send = {}
|
|
|
|
# Client credentials to be verified
|
|
to_send['verifytoken'] = self.validated_data.get(self.token_name)
|
|
to_send['verifyname'] = self.validated_data.get(self.name_name)
|
|
to_send['verifyrealm'] = self.validated_data.get(self.real_name)
|
|
|
|
# Our credentials
|
|
to_send['token'] = pyotp.TOTP(self.seed)
|
|
to_send['name'] = self.name
|
|
to_send['realm'] = self.realm
|
|
|
|
data = json.dumps(to_send).encode("utf-8")
|
|
|
|
req = urllib.request.Request(url=serverurl,
|
|
data=data,
|
|
headers={'Content-Type': 'application/json'},
|
|
method='POST')
|
|
|
|
f = urllib.request.urlopen(req)
|
|
|
|
if not f.status == 200:
|
|
raise exceptions.AuthenticationFailed()
|
|
|
|
return True
|
|
|
|
|
|
class OTPAuthentication(authentication.BaseAuthentication):
|
|
def authenticate(self, request):
|
|
serializer = TokenSerializer(data=request.data)
|
|
|
|
if serializer.is_valid():
|
|
print("trying to save... {}".format(serializer))
|
|
user, token = serializer.save()
|
|
else:
|
|
raise exceptions.AuthenticationFailed()
|
|
|
|
return (user, token)
|