def done(self, form_list, **kwargs): """ Finish the wizard. Save all forms and redirect. """ # Remove secret key used for QR code generation try: del self.request.session[self.session_key_name] except KeyError: pass # TOTPDeviceForm if self.get_method() == 'generator': form = [ form for form in form_list if isinstance(form, TOTPDeviceForm) ][0] device = form.save() # PhoneNumberForm / YubiKeyDeviceForm elif self.get_method() in ('call', 'sms', 'yubikey'): device = self.get_device() device.save() else: raise NotImplementedError("Unknown method '%s'" % self.get_method()) django_otp.login(self.request, device) return redirect(self.success_url)
def done(self, form_list, **kwargs): """ Finish the wizard. Save all forms and redirect. """ # Remove secret key used for QR code generation try: del self.request.session[self.session_key_name] except KeyError: pass # TOTPDeviceForm if self.get_method() == 'generator': form = [form for form in form_list if isinstance(form, TOTPDeviceForm)][0] device = form.save() # PhoneNumberForm / YubiKeyDeviceForm elif self.get_method() in ('call', 'sms', 'yubikey'): device = self.get_device() device.save() else: raise NotImplementedError("Unknown method '%s'" % self.get_method()) django_otp.login(self.request, device) return redirect(self.success_url)
def tf_setup(request): if request.method == 'POST': key = request.session.get('tf_key') form = PleioTOTPDeviceForm(data=request.POST, key=key, user=request.user) if form.is_valid(): device = form.save() django_otp.login(request, device) return redirect('two_factor:setup_complete') else: key = random_hex(20).decode('ascii') rawkey = unhexlify(key.encode('ascii')) b32key = b32encode(rawkey).decode('utf-8') request.session['tf_key'] = key request.session['django_two_factor-qr_secret_key'] = b32key return render( request, 'tf_setup.html', { 'form': PleioTOTPDeviceForm(key=key, user=request.user), 'QR_URL': reverse('two_factor:qr') })
def two_factor_form(request, page_action): two_factor_authorization = {} if page_action == '2fa_setup-a2f_configuration': key = random_hex(20).decode('ascii') rawkey = unhexlify(key.encode('ascii')) b32key = b32encode(rawkey).decode('utf-8') request.session['tf_key'] = key request.session['django_two_factor-qr_secret_key'] = b32key two_factor_authorization = ({ 'form': PleioTOTPDeviceForm(key=key, user=request.user), 'QR_URL': reverse('two_factor:qr') }) two_factor_authorization['state'] = 'setup' elif page_action == '2fa_setupnext-a2f_configurationsuivante': key = request.session.get('tf_key') form = PleioTOTPDeviceForm(data=request.POST, key=key, user=request.user) if form.is_valid(): device = form.save() django_otp.login(request, device) two_factor_authorization['default_device'] = True two_factor_authorization['show_state'] = True else: two_factor_authorization['form'] = form two_factor_authorization['QR_URL'] = reverse('two_factor:qr') two_factor_authorization['state'] = 'setup' elif page_action == '2fa_disable-a2f_desactiver': two_factor_authorization = DisableView.as_view(template_name='security_pages.html')(request).context_data two_factor_authorization['state'] = 'disable' elif page_action == '2fa_disableconfirm-a2f_desactiverconfirmer': two_factor_authorization = DisableView.as_view(template_name='security_pages.html')(request) two_factor_authorization['state'] = 'default' two_factor_authorization['show_state'] = 'true' elif page_action == '2fa_showcodes-a2f_afficherlescodes': two_factor_authorization = PleioBackupTokensView.as_view(template_name='backup_tokens.html')(request).context_data two_factor_authorization['default_device'] = 'true' two_factor_authorization['state'] = 'codes' two_factor_authorization['show_state'] = 'true' elif page_action == '2fa_generatecodes-a2f_genererdescodes': two_factor_authorization = PleioBackupTokensView.as_view(template_name='security_pages.html')(request).context_data two_factor_authorization['default_device'] = 'true' two_factor_authorization['show_state'] = 'true' two_factor_authorization['state'] = 'codes' else: two_factor_authorization = PleioProfileView.as_view(template_name='security_pages.html')(request).context_data two_factor_authorization['state'] = 'default' two_factor_authorization['show_state'] = 'true' return two_factor_authorization
def tfa_setup_check(self, request): """Check TFA setup.""" serializer = serializers.CheckTFASetupSerializer( data=request.data, context={"user": request.user}) serializer.is_valid(raise_exception=True) # create static device for recovery purposes device = StaticDevice.objects.create(user=request.user, name="{} static device".format( request.user)) for cpt in range(10): token = StaticToken.random_token() device.token_set.create(token=token) django_otp.login(self.request, request.user.totpdevice_set.first()) return response.Response()
def done(self, form_list, **kwargs): """ Login the user and redirect to the desired page. """ login(self.request, self.get_user()) redirect_to = self.request.POST.get( self.redirect_field_name, self.request.GET.get(self.redirect_field_name, '')) if not is_safe_url(url=redirect_to, allowed_hosts=[self.request.get_host()]): redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL) device = default_device(self.get_user()) if device: django_otp.login(self.request, device) return redirect(redirect_to)
def done(self, form_list, **kwargs): """ Finish the wizard. Save all forms and redirect. """ # TOTPDeviceForm if self.get_method() == 'generator': form = [form for form in form_list if isinstance(form, TOTPDeviceForm)][0] device = form.save() # PhoneNumberForm / YubiKeyDeviceForm elif self.get_method() in ('call', 'sms', 'yubikey'): device = self.get_device() device.save() else: raise NotImplementedError("Unknown method '%s'" % self.get_method()) django_otp.login(self.request, device) return redirect(self.redirect_url)
def do_two_factor_login(request: HttpRequest, user_profile: UserProfile) -> None: device = default_device(user_profile) if device: django_otp.login(request, device)
def form_valid(self, form): """Login user.""" django_otp.login(self.request, form.cleaned_data["tfa_code"]) return HttpResponseRedirect( find_nextlocation(self.request, self.request.user))
def login(request): """ The login page """ user = None oreq = request.session.get('openid_request', None) # this can be POST or GET, and can be null or empty next = request.REQUEST.get('next') or reverse(index) is_otp = False login_form = None login_form_class = OpenIDLoginForm if oreq else LoginForm strong_auth_req = 'strong_auth_requested' in request.session try: if request.method != 'POST': pass elif 'cancel' in request.POST: # note: this wipes request.session _logout(request) if oreq is not None: oresp = oreq.answer(False) return render_openid_response(request, oresp) elif 'otp_token' in request.POST: # if user's not authenticated, go back to square one if not request.user.is_authenticated(): raise OkupyError('OTP verification timed out') is_otp = True otp_form = OTPForm(request.POST) if otp_form.is_valid(): token = otp_form.cleaned_data['otp_token'] else: raise OkupyError('OTP verification failed') dev = django_otp.match_token(request.user, token) if not dev: raise OkupyError('OTP verification failed') django_otp.login(request, dev) else: login_form = login_form_class(request.POST) if login_form.is_valid(): username = login_form.cleaned_data['username'] password = login_form.cleaned_data['password'] else: raise OkupyError('Login failed') """ Perform authentication, if it retrieves a user object then it was successful. If it retrieves None then it failed to login """ try: user = authenticate(username=username, password=password) except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError( "Can't contact the LDAP server or the database") if not user: raise OkupyError('Login failed') if oreq: request.session['auto_logout'] = ( login_form.cleaned_data['auto_logout']) except OkupyError as error: messages.error(request, str(error)) if user and user.is_active: _login(request, user) # prepare devices, and see if OTP is enabled init_otp(request) try: set_secondary_password(request=request, password=password) except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") if (request.user.is_authenticated() and (not strong_auth_req or 'secondary_password' in request.session)): if request.user.is_verified(): return redirect(next) login_form = OTPForm() is_otp = True if login_form is None: login_form = login_form_class() if is_otp or strong_auth_req: ssl_auth_form = None ssl_auth_uri = None else: if 'encrypted_id' not in request.session: # .cache_key is a very good property since it ensures # that the cache is actually created, and works from first # request session_id = request.session.cache_key # since it always starts with the backend module name # and __init__() expects pure id, we can strip that assert(session_id.startswith('django.contrib.sessions.cache')) session_id = session_id[29:] request.session['encrypted_id'] = base64.b64encode( cipher.encrypt(session_id)) # TODO: it fails when: # 1. site is accessed via IP (auth.127.0.0.1), # 2. HTTP used on non-standard port (https://...:8000). ssl_auth_form = SSLCertLoginForm({ 'session_id': request.session['encrypted_id'], 'next': request.build_absolute_uri(next), 'login_uri': request.build_absolute_uri(request.get_full_path()), }) ssl_auth_host = 'auth.' + request.get_host() ssl_auth_path = reverse(ssl_auth) ssl_auth_uri = urljoin('https://' + ssl_auth_host, ssl_auth_path) return render(request, 'login.html', { 'login_form': login_form, 'openid_request': oreq, 'next': next, 'ssl_auth_uri': ssl_auth_uri, 'ssl_auth_form': ssl_auth_form, 'is_otp': is_otp, })
def login(request): """ The login page """ user = None oreq = request.session.get('openid_request', None) # this can be POST or GET, and can be null or empty next = request.REQUEST.get('next') or reverse(index) is_otp = False login_form = None strong_auth_req = 'strong_auth_requested' in request.session if oreq: login_form_class = OpenIDLoginForm elif ('strong_auth_requested' in request.session and request.user.is_authenticated()): login_form_class = StrongAuthForm else: login_form_class = LoginForm try: if request.method != 'POST': pass elif 'cancel' in request.POST: # note: this wipes request.session _logout(request) if oreq is not None: oresp = oreq.answer(False) return render_openid_response(request, oresp) elif 'otp_token' in request.POST: # if user's not authenticated, go back to square one if not request.user.is_authenticated(): raise OkupyError('OTP verification timed out') is_otp = True otp_form = OTPForm(request.POST) if otp_form.is_valid(): token = otp_form.cleaned_data['otp_token'] else: raise OkupyError('OTP verification failed') # prevent replay attacks and race conditions if not RevokedToken.add(token, request.user): raise OkupyError('OTP verification failed') dev = django_otp.match_token(request.user, token) if not dev: raise OkupyError('OTP verification failed') django_otp.login(request, dev) else: login_form = login_form_class(request.POST) if login_form.is_valid(): if login_form_class != StrongAuthForm: username = login_form.cleaned_data['username'] else: username = request.user.username password = login_form.cleaned_data['password'] else: raise OkupyError('Login failed') """ Perform authentication, if it retrieves a user object then it was successful. If it retrieves None then it failed to login """ try: user = authenticate(request=request, username=username, password=password) except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError( "Can't contact the LDAP server or the database") if not user: raise OkupyError('Login failed') if oreq: request.session['auto_logout'] = ( login_form.cleaned_data['auto_logout']) except OkupyError as error: messages.error(request, str(error)) if user and user.is_active: _login(request, user) # prepare devices, and see if OTP is enabled init_otp(request) set_secondary_password(request=request, password=password) if request.user.is_authenticated(): if (strong_auth_req and not 'secondary_password' in request.session): if request.method != 'POST': messages.info( request, 'You need to type in your password' + ' again to perform this action') else: if request.user.is_verified(): return redirect(next) login_form = OTPForm() is_otp = True if login_form is None: login_form = login_form_class() if is_otp or strong_auth_req: ssl_auth_form = None ssl_auth_uri = None ssh_auth_command = None else: encrypted_id = sessionrefcipher.encrypt(request.session) # TODO: it fails when: # 1. site is accessed via IP (auth.127.0.0.1), # 2. HTTP used on non-standard port (https://...:8000). ssl_auth_form = SSLCertLoginForm({ 'session': encrypted_id, 'next': request.build_absolute_uri(next), 'login_uri': request.build_absolute_uri(request.get_full_path()), }) ssl_auth_host = 'auth.' + request.get_host() ssl_auth_path = reverse(ssl_auth) ssl_auth_uri = urljoin('https://' + ssl_auth_host, ssl_auth_path) if settings.SSH_BIND[1] == 22: ssh_port_opt = '' else: ssh_port_opt = '-p %d ' % settings.SSH_BIND[1] ssh_auth_command = 'ssh %sauth+%s@%s' % ( ssh_port_opt, encrypted_id, request.get_host().split(':')[0]) return render( request, 'login.html', { 'login_form': login_form, 'openid_request': oreq, 'next': next, 'ssl_auth_uri': ssl_auth_uri, 'ssl_auth_form': ssl_auth_form, 'ssh_auth_command': ssh_auth_command, 'is_otp': is_otp, })
def form_valid(self, form): login(self.request, self.request.user.otp_device) return super().form_valid(form)
def login(request): """ The login page """ user = None oreq = request.session.get('openid_request', None) # this can be POST or GET, and can be null or empty next = request.REQUEST.get('next') or reverse(index) is_otp = False login_form = None strong_auth_req = 'strong_auth_requested' in request.session if oreq: login_form_class = OpenIDLoginForm elif ('strong_auth_requested' in request.session and request.user.is_authenticated()): login_form_class = StrongAuthForm else: login_form_class = LoginForm try: if request.method != 'POST': pass elif 'cancel' in request.POST: # note: this wipes request.session _logout(request) if oreq is not None: oresp = oreq.answer(False) return render_openid_response(request, oresp) elif 'otp_token' in request.POST: # if user's not authenticated, go back to square one if not request.user.is_authenticated(): raise OkupyError('OTP verification timed out') is_otp = True otp_form = OTPForm(request.POST) if otp_form.is_valid(): token = otp_form.cleaned_data['otp_token'] else: raise OkupyError('OTP verification failed') # prevent replay attacks and race conditions if not RevokedToken.add(token, request.user): raise OkupyError('OTP verification failed') dev = django_otp.match_token(request.user, token) if not dev: raise OkupyError('OTP verification failed') django_otp.login(request, dev) else: login_form = login_form_class(request.POST) if login_form.is_valid(): if login_form_class != StrongAuthForm: username = login_form.cleaned_data['username'] else: username = request.user.username password = login_form.cleaned_data['password'] else: raise OkupyError('Login failed') """ Perform authentication, if it retrieves a user object then it was successful. If it retrieves None then it failed to login """ try: user = authenticate( request=request, username=username, password=password) except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError( "Can't contact the LDAP server or the database") if not user: raise OkupyError('Login failed') if oreq: request.session['auto_logout'] = ( login_form.cleaned_data['auto_logout']) except OkupyError as error: messages.error(request, str(error)) if user and user.is_active: _login(request, user) # prepare devices, and see if OTP is enabled init_otp(request) set_secondary_password(request=request, password=password) if request.user.is_authenticated(): if (strong_auth_req and not 'secondary_password' in request.session): if request.method != 'POST': messages.info(request, 'You need to type in your password' + ' again to perform this action') else: if request.user.is_verified(): return redirect(next) login_form = OTPForm() is_otp = True if login_form is None: login_form = login_form_class() if is_otp or strong_auth_req: ssl_auth_form = None ssl_auth_uri = None ssh_auth_command = None else: encrypted_id = sessionrefcipher.encrypt(request.session) # TODO: it fails when: # 1. site is accessed via IP (auth.127.0.0.1), # 2. HTTP used on non-standard port (https://...:8000). ssl_auth_form = SSLCertLoginForm({ 'session': encrypted_id, 'next': request.build_absolute_uri(next), 'login_uri': request.build_absolute_uri(request.get_full_path()), }) ssl_auth_host = 'auth.' + request.get_host() ssl_auth_path = reverse(ssl_auth) ssl_auth_uri = urljoin('https://' + ssl_auth_host, ssl_auth_path) if settings.SSH_BIND[1] == 22: ssh_port_opt = '' else: ssh_port_opt = '-p %d ' % settings.SSH_BIND[1] ssh_auth_command = 'ssh %sauth+%s@%s' % ( ssh_port_opt, encrypted_id, request.get_host().split(':')[0]) return render(request, 'login.html', { 'login_form': login_form, 'openid_request': oreq, 'next': next, 'ssl_auth_uri': ssl_auth_uri, 'ssl_auth_form': ssl_auth_form, 'ssh_auth_command': ssh_auth_command, 'is_otp': is_otp, })