def otp_config(request): """View to manage two-factor (OTP) auth. - Show QR code if the device is not confirmed. - Allow user to confirm their code, if it not confirmed. Then mark the device as confirmed. - If device is already confirmed, then don't show the QR code since that would risk it being lost. However, do show it if the user has logged in using OTP (user.is_verified) and you have just verified your token. """ if request.user.is_anonymous(): return HttpResponse("Forbidden: must be logged in", status=403) context = c = {} # Get devices devices = list(django_otp.devices_for_user(request.user, confirmed=None)) # conf # and unconf If there is more than one device, log an error. # FIXME: this does not support one-time passwords and multiple # devices yet. if len(devices) > 1: logger.critical("User has more than one OTP device: %s", request.user.id) # If the user has no devices, create one now. if len(devices) == 0: from django_otp.plugins.otp_totp.models import TOTPDevice device = TOTPDevice(user=request.user, confirmed=False, name='Auto device') device.save() # If everything is normal, then select the user's device. else: device = devices[0] c['confirmed'] = device.confirmed # Attempt to verify code or confirm the unconfirmed device. if request.method == 'POST': form = c['otp_form'] = OTPVerifyForm(request.POST) form.is_valid() # validate form - validation is null op. success = c['success'] = device.verify_token( form.cleaned_data['otp_token']) # Success: if the device is unconfirmed, then confirm it. It # can then be used for logging in, etc. if success: # Do device confirmation if not device.confirmed: device.confirmed = True device.save() c['confirmed'] = device.confirmed message = c['message'] = 'Code verified.' else: message = c['message'] = 'Code not successful.' # Note that there is no other special action on success. # Reset the form - don't display code again or anything. form = c['otp_form'] = OTPVerifyForm() else: form = c['otp_form'] = OTPVerifyForm() return TemplateResponse(request, 'koota/otp.html', context)
def save(self, user): totp_device = TOTPDevice(name=self.cleaned_data["name"], user=user) totp_device.confirmed = False totp_device.save() return totp_device