Source code for django_otp.plugins.otp_email.models

from __future__ import absolute_import, division, print_function, unicode_literals

from binascii import unhexlify

from django.core.mail import send_mail
from django.db import models
from django.template.loader import render_to_string
from django.utils.encoding import force_text

from django_otp.models import Device
from django_otp.oath import totp
from django_otp.util import hex_validator, random_hex

from .conf import settings


def default_key():
    return force_text(random_hex(20))


def key_validator(value):
    return hex_validator()(value)


[docs]class EmailDevice(Device): """ A :class:`~django_otp.models.Device` that delivers a token to the user's registered email address (``user.email``). This is intended for demonstration purposes; if you allow users to reset their passwords via email, then this provides no security benefits. .. attribute:: key *CharField*: A hex-encoded secret key of up to 40 bytes. (Default: 20 random bytes) """ key = models.CharField(max_length=80, validators=[key_validator], default=default_key, help_text='A hex-encoded secret key of up to 20 bytes.') @property def bin_key(self): return unhexlify(self.key.encode()) def generate_challenge(self): token = totp(self.bin_key) body = render_to_string('otp/email/token.txt', {'token': token}) send_mail(settings.OTP_EMAIL_SUBJECT, body, settings.OTP_EMAIL_SENDER, [self.user.email]) message = "sent by email" return message def verify_token(self, token): try: token = int(token) except Exception: verified = False else: verified = any(totp(self.bin_key, drift=drift) == token for drift in [0, -1]) return verified