Skip to content

Commit

Permalink
Merge pull request #20 from andrenerd/development
Browse files Browse the repository at this point in the history
update and fix authenticator device
  • Loading branch information
andrenerd committed Dec 8, 2020
2 parents a5075b6 + 0bab749 commit bcab49d
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 41 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ Flexible authentication for web, mobile, desktop and hybrid apps. It can be used
Full list of supported services and corresponding identifiers:
- Email
- Phone (as Sms)
- GoogleAuthentication (soon)
- Yubikey (soon)
- WhatsApp
- Google Authenticator
- Microsoft Authenticator
- Authy, andOTP, etc
- Yubikey (soon)
- ...add yours

and service providers:
Expand Down Expand Up @@ -90,7 +92,7 @@ Custom use cases and how to config or code them.

#### APIs

Package contains full set of [rest api endpoints](./multauth/api/urls.py), but it's optional. To use it, `djangorestframework>=3.10.3` should be installed and the urls be included:
Package contains full set of [rest api endpoints](./multauth/api/urls.py), but it's optional. To activate it, `djangorestframework>=3.10.3` should be installed and the urls be included:
```
urlpatterns = [
path(r'^', include('multauth.api.urls')),
Expand Down
2 changes: 1 addition & 1 deletion multauth/api/devices/authenticator/me/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@


class UserAuthenticatorKeySerializer(serializers.Serializer):
pass
key = serializers.CharField()
53 changes: 24 additions & 29 deletions multauth/api/devices/authenticator/me/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,31 @@ def get(self, request):
user = request.user

try:
user = request.user
device = user.get_authenticator_device()
key = device.key_b32
key = device.key_b32.decode()
result = serializers.UserAuthenticatorKeySerializer({
'key': key,
})

return Response(result.data, status=status.HTTP_200_OK)

except AuthenticatorDevice.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

# @swagger_auto_schema(
# operation_description='Set push notification code, aka token',
# operation_description='Set and get authenticator key',
# request_body=serializers.UserAuthenticatorPushcodeSerializer,
# )
# def post(self, request):
# serializer = serializers.UserAuthenticatorPushcodeSerializer(data=request.data)
# serializer.is_valid(raise_exception=True)

# try:
# user = request.user
# device = user.get_phone_device()
# device.pushcode = serializer.validated_data['pushcode'];
# device.save()
def post(self, request):
user = request.user

# return Response(status=status.HTTP_200_OK)
try:
device = user.get_authenticator_device()
device.set_key()
return self.get(request)

# except AuthenticatorDevice.DoesNotExist:
# return Response(status=status.HTTP_404_NOT_FOUND)
except AuthenticatorDevice.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)


class MeAuthenticatorKeyImageView(views.APIView):
Expand All @@ -68,7 +68,6 @@ def get(self, request):
user = request.user

try:
user = request.user
device = user.get_authenticator_device()
uri = device.key_uri

Expand All @@ -81,20 +80,16 @@ def get(self, request):
return Response(status=status.HTTP_404_NOT_FOUND)

# @swagger_auto_schema(
# operation_description='Set push notification code, aka token',
# operation_description='Set and get authenticator key',
# request_body=serializers.UserAuthenticatorPushcodeSerializer,
# )
# def post(self, request):
# serializer = serializers.UserAuthenticatorPushcodeSerializer(data=request.data)
# serializer.is_valid(raise_exception=True)

# try:
# user = request.user
# device = user.get_phone_device()
# device.pushcode = serializer.validated_data['pushcode'];
# device.save()
def post(self, request):
user = request.user

# return Response(status=status.HTTP_200_OK)
try:
device = user.get_authenticator_device()
device.set_key()
return self.get(request)

# except AuthenticatorDevice.DoesNotExist:
# return Response(status=status.HTTP_404_NOT_FOUND)
except AuthenticatorDevice.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
17 changes: 10 additions & 7 deletions multauth/devices/authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@


# see django_otp.plugins.otp_totp.models.TOTPDevice
def default_key():
def key_generator():
return random_hex(MULTAUTH_KEY_LENGTH)


Expand All @@ -46,7 +46,7 @@ def key_validator(value):

class AuthenticatorDevice(ThrottlingMixin, AbstractDevice):
# see django_otp.plugins.otp_totp.models.TOTPDevice
key = models.CharField(max_length=80, validators=[key_validator], default=default_key) # a hex-encoded secret key of up to 40 bytes
key = models.CharField(max_length=80, validators=[key_validator], default=key_generator) # a hex-encoded secret key of up to 40 bytes
step = models.PositiveSmallIntegerField(default=30) # the time step in seconds.
t0 = models.BigIntegerField(default=0) # the Unix time at which to begin counting steps
digits = models.PositiveSmallIntegerField(choices=[(6, 6), (8, 8)], default=6) # the number of digits to expect in a token
Expand Down Expand Up @@ -105,6 +105,11 @@ def save(self, *args, **kwargs):
self.key = self.generate_key()
return super().save(*args, **kwargs)

def set_key(self, raw_hardcode):
self.key = key_generator()
self.save(update_fields=['key'])
return self.key

def generate_totp(self, request=None):
key = self.bin_key
totp = TOTP(key, self.step, self.t0, self.digits, self.drift)
Expand All @@ -115,9 +120,7 @@ def generate_challenge(self, request=None):
totp = self.generate_totp()

if MULTAUTH_DEBUG:
print('Fake auth message, Google Authenticator, token: %s ' % (totp))

return totp
print('Fake auth message, Google Authenticator, token: %s ' % (totp.token()))

# see django_otp.plugins.otp_totp.models.TOTPDevice
def verify_token(self, token):
Expand All @@ -130,12 +133,12 @@ def verify_token(self, token):
except Exception:
verified = False
else:
totp = generate_totp()
totp = self.generate_totp()
verified = totp.verify(token, self.tolerance, self.last_t + 1)

if verified:
self.last_t = totp.t()
if MULTAUTH_THROTTLE_SYNC:
if MULTAUTH_SYNC:
self.drift = totp.drift
self.throttle_reset(commit=False)
self.save()
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def read(f):

setup(
name='django-multifactor-authentication',
keywords='django authentication multifactor mfa 2fa 3fa user signin signup twillio sendgrid nexmo sns',
keywords='django authentication multifactor mfa 2fa 3fa user signin signup otp google microsoft authenticator authy andotp whatsapp telegram yubikey twillio sendgrid nexmo sns',
version='1.1.0',
url='https://github.com/andrenerd/django-multifactor-authentication',
license='BSD',
Expand Down

0 comments on commit bcab49d

Please sign in to comment.