def clean_code(self): code = self.cleaned_data['code'] if not bool(match_token(self.request.user, code)): raise forms.ValidationError(_("The 2FA code is invalid")) return code
def post(self, request, *args, **kwargs): token = request.POST.get('token', '').strip().replace(' ', '') valid = False if '_u2f_challenge' in self.request.session and token.startswith('{'): devices = [ DeviceRegistration.wrap(device.json_data) for device in U2FDevice.objects.filter(confirmed=True, user=self.user) ] challenge = self.request.session.pop('_u2f_challenge') try: u2f.verify_authenticate(devices, challenge, token, [self.app_id]) valid = True except Exception: logger.exception('U2F login failed') else: valid = match_token(self.user, token) if valid: auth_login(request, self.user) request.session['pretix_auth_login_time'] = int(time.time()) del request.session['pretix_auth_2fa_user'] del request.session['pretix_auth_2fa_time'] if "next" in request.GET and is_safe_url(request.GET.get("next")): return redirect(request.GET.get("next")) return redirect(reverse('control:index')) else: messages.error(request, _('Invalid code, please try again.')) return redirect('control:auth.login.2fa')
def post(self, request): ret = {"status": False, 'msg': None} username = request.POST.get("username") password = request.POST.get("password") password_len = len(password) valid_code = request.POST.get('valid_code') code_session = request.session.get("valid_code", "") if valid_code and valid_code.upper() == code_session.upper(): if password_len <= 6: ret['msg'] = "密码输入错误,请重新输入" qrcode = password[-6:] password = password[:password_len - 6] u = auth.authenticate(email=username, password=password) if u: if match_token(u, qrcode) != None: auth.login(request, u) request.session['is_login'] = True request.session.set_expiry(3600) login_ip = request.META['REMOTE_ADDR'] models.Loginlog.objects.create(user=request.user, ip=login_ip, action="***login***") ret["status"] = True else: ret['msg'] = "用户名或者密码错误" else: ret['msg'] = "验证码错误" return JsonResponse(ret)
def post(self, request, *args, **kwargs): token = request.POST.get('token', '').strip().replace(' ', '') valid = False if '_u2f_challenge' in self.request.session and token.startswith('{'): devices = [DeviceRegistration.wrap(device.json_data) for device in U2FDevice.objects.filter(confirmed=True, user=self.user)] challenge = self.request.session.pop('_u2f_challenge') try: u2f.verify_authenticate(devices, challenge, token, [self.app_id]) valid = True except Exception: logger.exception('U2F login failed') else: valid = match_token(self.user, token) if valid: auth_login(request, self.user) request.session['pretix_auth_login_time'] = int(time.time()) del request.session['pretix_auth_2fa_user'] del request.session['pretix_auth_2fa_time'] if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None): return redirect(request.GET.get("next")) return redirect(reverse('control:index')) else: messages.error(request, _('Invalid code, please try again.')) return redirect('control:auth.login.2fa')
def _inner(request, domain, *args, **kwargs): domain_obj = Domain.get_by_name(domain) couch_user = _ensure_request_couch_user(request) if (not api_key and not getattr(request, 'skip_two_factor_check', False) and domain_obj and _two_factor_required( view_func, domain_obj, couch_user)): token = request.META.get('HTTP_X_COMMCAREHQ_OTP') if not token and 'otp' in request.GET: with mutable_querydict(request.GET): # remove the param from the query dict so that we don't interfere with places # that use the query dict to generate dynamic filters token = request.GET.pop('otp')[-1] if not token: return JsonResponse(OTP_AUTH_FAIL_RESPONSE, status=401) otp_device = match_token(request.user, token) if not otp_device: return JsonResponse({"error": "OTP token is incorrect"}, status=401) # set otp device and is_verified function on user to be consistent with OTP middleware request.user.otp_device = otp_device request.user.is_verified = lambda: True return fn(request, domain, *args, **kwargs) return fn(request, domain, *args, **kwargs)
def validate_challenge_code(code: str, request: HttpRequest, user: User) -> str: """Validate code-based challenges. We test against every device, on purpose, as the user mustn't choose between totp and static devices.""" device = match_token(user, code) if not device: raise ValidationError(_("Invalid Token")) return code
def _inner(request, domain, *args, **kwargs): domain_obj = Domain.get_by_name(domain) couch_user = _ensure_request_couch_user(request) if ( not api_key and not getattr(request, 'skip_two_factor_check', False) and domain_obj and _two_factor_required(view_func, domain_obj, couch_user) ): token = request.META.get('HTTP_X_COMMCAREHQ_OTP') if not token and 'otp' in request.GET: with mutable_querydict(request.GET): # remove the param from the query dict so that we don't interfere with places # that use the query dict to generate dynamic filters token = request.GET.pop('otp')[-1] if not token: return JsonResponse(OTP_AUTH_FAIL_RESPONSE, status=401) otp_device = match_token(request.user, token) if not otp_device: return JsonResponse({"error": "OTP token is incorrect"}, status=401) # set otp device and is_verified function on user to be consistent with OTP middleware request.user.otp_device = otp_device request.user.is_verified = lambda: True return fn(request, domain, *args, **kwargs) return fn(request, domain, *args, **kwargs)
def login(request): err_msg = '' if request.method == 'GET': return render(request, 'login.html', {'err_msg': err_msg}) if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') password_len = len(password) if password_len <= 6: return render(request, 'login.html', {'err_msg': 'user or password errors'}) qrcode = password[-6:] password = password[:password_len - 6] u = auth.authenticate(username=username, password=password) if u: if match_token(u, qrcode) != None: auth.login(request, u) request.session['is_login'] = True request.session.set_expiry(3600) login_ip = request.META['REMOTE_ADDR'] return redirect('/') else: return render(request, 'login.html', {'err_msg': 'user or password errors'}) return render(request, 'login.html', {'err_msg': err_msg})
def _inner(request, domain, *args, **kwargs): if not api_key and Domain.get_by_name(domain).two_factor_auth: token = request.META.get('HTTP_X_COMMCAREHQ_OTP') if token and match_token(request.user, token): return fn(request, *args, **kwargs) else: return JsonResponse({"error": "must send X-CommcareHQ-OTP header"}, status=401) return fn(request, domain, *args, **kwargs)
def clean_otp_token(self): otp_token = self.cleaned_data["otp_token"] if not django_otp.match_token(self.user, otp_token): raise ValidationError( self.error_messages['token_incorrect'], code='token_incorrect', ) return otp_token
def clean_otp_token(self): otp_token = self.cleaned_data["otp_token"] aidant = self.aidant good_token = match_token(aidant, otp_token) if good_token: return otp_token else: raise ValidationError("Ce code n'est pas valide.")
def post(self, request, *args, **kwargs): token = request.POST.get('token', '').strip().replace(' ', '') valid = False if 'webauthn_challenge' in self.request.session and token.startswith( '{'): challenge = self.request.session['webauthn_challenge'] resp = json.loads(self.request.POST.get("token")) try: devices = [ WebAuthnDevice.objects.get(user=self.user, credential_id=resp.get("id")) ] except WebAuthnDevice.DoesNotExist: devices = U2FDevice.objects.filter(user=self.user) for d in devices: try: wu = d.webauthnuser if isinstance(d, U2FDevice): # RP_ID needs to be appId for U2F devices, but we can't # set it that way in U2FDevice.webauthnuser, since that # breaks the frontend part. wu.rp_id = settings.SITE_URL webauthn_assertion_response = webauthn.WebAuthnAssertionResponse( wu, resp, challenge, settings.SITE_URL, uv_required=False # User Verification ) sign_count = webauthn_assertion_response.verify() except Exception: logger.exception('U2F login failed') else: if isinstance(d, WebAuthnDevice): d.sign_count = sign_count d.save() valid = True break else: valid = match_token(self.user, token) if valid: auth_login(request, self.user) request.session['pretix_auth_login_time'] = int(time.time()) del request.session['pretix_auth_2fa_user'] del request.session['pretix_auth_2fa_time'] if "next" in request.GET and is_safe_url(request.GET.get("next"), allowed_hosts=None): return redirect(request.GET.get("next")) return redirect(reverse('control:index')) else: messages.error(request, _('Invalid code, please try again.')) return redirect('control:auth.login.2fa')
def reverify(request, plan, pk): try: request.session['reverify'] = None if not request.session['reverify']: totp = TOTPDevice.objects.get(user_id=request.user.id) form = otpform(request.POST) temp = totp.config_url.replace("/", "%2F") if request.method == 'POST': if form.is_valid(): otp_token = form.cleaned_data['otp_token'] result = match_token(request.user, otp_token) if not result: errors = form._errors.setdefault( "Incorrect OTP", ErrorList()) return render( request, 'users/otp_setup.html', { 'form': form, 'otpstring': "https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=" + str(temp), 'verification': True, 'plan': plan, 'pk': pk }) request.session['reverify'] = 1 if plan == "confirm_transactions": return HttpResponseRedirect( reverse(plan, kwargs={'pk': pk})) if plan == "confirm_accept_cash_request": return HttpResponseRedirect( reverse(plan, kwargs={'pk': pk})) if plan == "confirm_send_group_request": return HttpResponseRedirect( reverse(plan, kwargs={'pk': pk})) return HttpResponseRedirect(reverse(plan)) else: return redirect(reverse('homepage')) else: return render( request, 'users/otp_setup.html', { 'form': form, 'otpstring': "https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=" + str(temp), 'verification': True, 'plan': plan }) else: return redirect(reverse('homepage')) except: return redirect(reverse('homepage'))
def _inner(request, domain, *args, **kwargs): dom = Domain.get_by_name(domain) if not api_key and dom and dom.two_factor_auth: token = request.META.get('HTTP_X_COMMCAREHQ_OTP') if token and match_token(request.user, token): return fn(request, *args, **kwargs) else: return JsonResponse({"error": "must send X-CommcareHQ-OTP header"}, status=401) return fn(request, domain, *args, **kwargs)
def _verify_token(self, user, token, device=None): if device is not None: device = device if device.verify_token(token) else None else: device = match_token(user, token) if device is None: self.verify() raise forms.ValidationError(_('Invalid token. Please make sure you have entered it correctly.'), code='invalid') return device
def get( request, path, ): token = request.POST.get("token", None) if token: # token if django_otp.match_token(request.user, token): if request.user.is_staff: pde = PDE.objects.all() else: pde = PDE.objects.filter(user=request.user.get_username()) for p in pde: print(p.pde) if p.pde == "pde/files/" + path: with open( os.path.join( os.path.join(settings.MEDIA_ROOT, 'pde/files'), path), "rb") as f: content = f.read() content = Cryptographer.decrypted(content) m = hashlib.md5() m.update(content) message = 'Hi %(username)s,\n\n' \ 'You\'ve verified yourself and just downloaded a PDE file with the following details: \n\n' \ 'File: %(path)s\n' \ 'MD5: %(md5)s\n' \ % {'username': request.user.get_username(), 'path': path, 'md5': m.hexdigest()} print(message) request.user.email_user(subject='PDE Download Success', message=message) response = HttpResponse( content, content_type=magic.Magic( mime=True).from_buffer(content)) response[ 'Content-Disposition'] = 'attachment; filename=' + path return response return HttpResponse(status=401) else: return HttpResponse(status=401) else: context = { 'dfi': request.user, } return render(request, 'pde/otp.html', context)
def _inner(request, domain, *args, **kwargs): dom = Domain.get_by_name(domain) couch_user = _ensure_request_couch_user(request) if not api_key and dom and _two_factor_required( view_func, dom, couch_user): token = request.META.get('HTTP_X_COMMCAREHQ_OTP') if not token: return JsonResponse( {"error": "must send X-CommcareHQ-OTP header"}, status=401) elif not match_token(request.user, token): return JsonResponse( {"error": "X-CommcareHQ-OTP token is incorrect"}, status=401) else: return fn(request, domain, *args, **kwargs) return fn(request, domain, *args, **kwargs)
def change_totp(request, add=False): bad_password = False bad_token = None otp_png = None confirmed = False request.session['add_device'] = add if request.method == 'POST' and 'token' in request.POST: if not django_otp.match_token(request.user, request.POST['token']): bad_token = True if not authenticate(username=request.user.username, password=request.POST['password']): bad_password = True if not (bad_password or bad_token): new_device = add_device(request.user, request.POST['new_name']) request.session['new_device'] = new_device.id otp_png = get_png(request.user, new_device) if request.method == 'POST' and 'new_token' in request.POST: new_device = devices.get(request.user, request.session['new_device']) otp_png = get_png(request.user, new_device) if new_device.verify_token(request.POST['new_token']): new_device.confirmed = True new_device.save() confirmed = True if not request.session['add_device']: devices.delete_all(request.user, keep=new_device) else: bad_token = True return render( request, 'totp-change-form.html', { 'bad_token': bad_token, 'bad_password': bad_password, 'add_device': request.session['add_device'], 'otp_png': otp_png, 'confirmed': confirmed, })
def totp_remove(request): bad_token = False bad_password = False success = False if request.method == 'POST' and 'token' in request.POST: device = django_otp.match_token(request.user, request.POST['token']) if not device: bad_token = True if not authenticate(username=request.user.username, password=request.POST['password']): bad_password = True if not bad_password and not bad_token: devices.delete_all(request.user, keep=device) success = True return render(request, 'totp-remove.html', { 'bad_token': bad_token, 'bad_password': bad_password, 'success': success, })
def validate_code(self, value): device = django_otp.match_token(self.context["user"], value) if device is None: raise serializers.ValidationError(_("This code is invalid")) return device
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 login(request): # import ipdb;ipdb.set_trace() # otp_url = '/otp?%s' % request.META.get('QUERY_STRING', '') r_url = request.GET.get('next', '/') if request.user.is_authenticated(): if r_url.startswith('/admin') and not request.user.is_staff: # 登陆用户无权限访问后台 r_url = '/' return HttpResponseRedirect(r_url) # elif 'login_user_id' in request.session: # # 已登陆但未进行otp验证 # return HttpResponseRedirect(otp_url) html = 'otp.html' if 'login_user_id' in request.session else 'login.html' if 'login_user_id' in request.session: # otp页显示 uid = request.session['login_user_id'] try: user = User.objects.get(id=uid) except: print 'Error: user_id (%d) del ??????!!!!!!!!' % uid del request.session['login_user_id'] return HttpResponseRedirect('/login') userprofile = get_userprofile(user) if userprofile.show_otp: # 首次otp验证或人工设置,显示otp二维码 show_otp = 1 try: totpdevice = user.totpdevice_set.filter(confirmed=1)[0] otp_data = totpdevice.config_url # 二维码对应实际数据otpauth://totp/user?digits= # print otp_data, 444 # 提取secret内容,用于Google Authentication import urlparse result = urlparse.urlparse(otp_data) secret = urlparse.parse_qs(result.query).get('secret', ['Error!']) # 开始生成二维码 import qrcode from io import BytesIO import base64 mio = BytesIO() # 用于替代磁盘临时文件,在内存中保存二维码图片 qr = qrcode.QRCode(version=1, box_size=4, border=1,) qr.add_data(otp_data) qr.make() img = qr.make_image() img.save(mio) base64_data = base64.b64encode(mio.getvalue()) # print base64_data if not base64_data: error_msg = "(用户 %s) T-otp二维码图片生成失败" % user # return render(request, html, locals()) except IndexError: # 正常情况下,totpdevice在userprofile创建后自动生成,无需人工添加 error_msg = "Error: 用户 %s otp设备获取失败,请联系管理员登陆后台查看是否有当前用户对应的“TOTP device”,或者device被禁用" % user if request.method == "POST": totp = request.POST.get("totp") u = request.POST.get("username") p = request.POST.get("password") try: if totp: # otp验证 try: # locals()已有变量userprofile、user userprofile except: # 非法构建表单进行提交 return HttpResponse('', status=404) if match_token(user, totp): if userprofile.show_otp: # 首次otp验证通过后,以后登陆将不再显示二维码 userprofile.show_otp = 0 userprofile.save() # 验证通过 else: error_msg = "(用户 %s) T-otp验证码失败,请等待otp《数字更新》后,重新尝试,<br/>若仍然失败则可能为网站时间和用户手机时间不一致导致,请联系管理员确认CMDB服务器时间是否为标准时间(%s)" % (user, datetime.now()) raise else: # 用户密码验证 user = auth.authenticate(username=u, password=p) if user: userprofile = get_userprofile(user) if userprofile.chk_yx(): error_msg = "账号过期,已停用,请联系管理员处理" raise else: request.session['login_user_id'] = user.id if userprofile.otp: return HttpResponseRedirect(request.get_full_path()) # 重新打开页面,用于判断是否显示二维码 # 管理员已设置当前用户无需进行otp验证 # 验证通过 else: error_msg = "用户名/密码错误,或用户已停用" raise # 用户登陆 auth.login(request, user) # 检查密码过期 if userprofile.chk_expired(): r_url = '/password_change?next=%s' % r_url return HttpResponseRedirect(r_url) except Exception as e: # print e, 22222 pass return render(request, html, locals())
def clean_tfa_code(self): code = self.cleaned_data["tfa_code"] device = django_otp.match_token(self.user, code) if device is None: raise forms.ValidationError(_("This code is invalid")) return device
def run(self): self.verified = match_token(self.user, self.token) connection.close()
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 test_match_token(self): verified = match_token(self.alice, 'bogus') self.assertIsNone(verified) verified = match_token(self.alice, 'alice') self.assertEqual(verified, self.alice.staticdevice_set.first())
def clean_code(self): code = self.cleaned_data['code'] if user_has_device(self.user) and not match_token(self.user, code): raise forms.ValidationError(_("Wrong two factor code informed")) return code