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): """ 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 otp_setup(request): dev = TOTPDevice.objects.get(user=request.user) secret = None conf_form = None skeys = None if request.method == 'POST': if 'disable' in request.POST: with get_bound_ldapuser(request) as user: dev.disable(user) elif 'confirm' in request.POST and 'otp_secret' in request.session: secret = request.session['otp_secret'] conf_form = OTPForm(request.POST) try: if not conf_form.is_valid(): raise OkupyError() token = conf_form.cleaned_data['otp_token'] # prevent reusing the same token to login if not RevokedToken.add(token, request.user): raise OkupyError() if not dev.verify_token(token, secret): raise OkupyError() except OkupyError: messages.error(request, 'Token verification failed.') conf_form = OTPForm() else: with get_bound_ldapuser(request) as user: dev.enable(user, secret) secret = None conf_form = None sdev = SOTPDevice.objects.get(user=request.user) skeys = sdev.gen_keys(user) messages.info(request, 'The new secret has been set.') elif 'enable' in request.POST: secret = dev.gen_secret() request.session['otp_secret'] = secret conf_form = OTPForm() elif 'recovery' in request.POST: sdev = SOTPDevice.objects.get(user=request.user) with get_bound_ldapuser(request) as user: skeys = sdev.gen_keys(user) messages.info(request, 'Your old recovery keys have been revoked.') elif 'cancel' in request.POST: messages.info( request, 'Secret change aborted. Previous settings' 'are in effect.') if secret: # into groups of four characters secret = ' '.join([secret[i:i + 4] for i in range(0, len(secret), 4)]) if skeys: # xxx xx xxx def group_key(s): return ' '.join([s[0:3], s[3:5], s[5:8]]) skeys = list([group_key(k) for k in skeys]) return render( request, 'otp-setup.html', { 'otp_enabled': dev.is_enabled(), 'secret': secret, 'conf_form': conf_form, 'skeys': skeys, })
def otp_setup(request): dev = TOTPDevice.objects.get(user=request.user) secret = None conf_form = None skeys = None if request.method == 'POST': if 'disable' in request.POST: with get_bound_ldapuser(request) as user: dev.disable(user) elif 'confirm' in request.POST and 'otp_secret' in request.session: secret = request.session['otp_secret'] conf_form = OTPForm(request.POST) try: if not conf_form.is_valid(): raise OkupyError() token = conf_form.cleaned_data['otp_token'] # prevent reusing the same token to login if not RevokedToken.add(token, request.user): raise OkupyError() if not dev.verify_token(token, secret): raise OkupyError() except OkupyError: messages.error(request, 'Token verification failed.') conf_form = OTPForm() else: with get_bound_ldapuser(request) as user: dev.enable(user, secret) secret = None conf_form = None sdev = SOTPDevice.objects.get(user=request.user) skeys = sdev.gen_keys(user) messages.info(request, 'The new secret has been set.') elif 'enable' in request.POST: secret = dev.gen_secret() request.session['otp_secret'] = secret conf_form = OTPForm() elif 'recovery' in request.POST: sdev = SOTPDevice.objects.get(user=request.user) with get_bound_ldapuser(request) as user: skeys = sdev.gen_keys(user) messages.info(request, 'Your old recovery keys have been revoked.') elif 'cancel' in request.POST: messages.info(request, 'Secret change aborted. Previous settings' 'are in effect.') if secret: # into groups of four characters secret = ' '.join([secret[i:i + 4] for i in range(0, len(secret), 4)]) if skeys: # xxx xx xxx def group_key(s): return ' '.join([s[0:3], s[3:5], s[5:8]]) skeys = list([group_key(k) for k in skeys]) return render(request, 'otp-setup.html', { 'otp_enabled': dev.is_enabled(), 'secret': secret, 'conf_form': conf_form, 'skeys': skeys, })