sso: Add captcha validation on 3 failed attempts

- clearing ip address correctly is not implemented yet
- currently clearing all ip addresses

Signed-off-by: Joseph Nuthalpati <njoseph@thoughtworks.com>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Joseph Nuthalpati 2017-09-05 13:26:43 +05:30 committed by James Valleroy
parent 31cd97e71e
commit f330d09ec9
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
5 changed files with 31 additions and 12 deletions

View File

@ -242,6 +242,7 @@ def configure_django():
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
],
AXES_LOCKOUT_URL='locked',
CACHES={'default':
{'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}},
CAPTCHA_FONT_PATH=['/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf'],

View File

@ -30,6 +30,10 @@ from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import LoginView, LogoutView
from django.shortcuts import render_to_response
from axes.utils import reset
PRIVATE_KEY_FILE_NAME = 'privkey.pem'
SSO_COOKIE_NAME = 'auth_pubtkt'
KEYS_DIRECTORY = '/etc/apache2/auth-pubtkt-keys'
@ -58,22 +62,37 @@ class SSOLoginView(LoginView):
def dispatch(self, request, *args, **kwargs):
response = super(SSOLoginView, self).dispatch(request, *args, **kwargs)
if request.user.is_authenticated:
return set_ticket_cookie(request.user, response)
else:
return response
class CaptchaLoginView(LoginView):
redirect_authenticated_user = True
template_name = 'login.html'
form_class = AuthenticationForm
def dispatch(self, request, *args, **kwargs):
response = super(CaptchaLoginView, self).dispatch(
request, *args, **kwargs)
if request.POST:
if request.user.is_authenticated:
ip = get_ip_address_from_request(request)
reset() # TODO reset(ip=ip)
return set_ticket_cookie(request.user, response)
else: # Redirect user to captcha page
redirect = '' if request.path.rstrip('/').endswith('captcha') else 'captcha'
return HttpResponseRedirect(redirect)
else:
return response
return response
class CaptchaLoginView(SSOLoginView):
form_class = AuthenticationForm
def get_ip_address_from_request(request):
# TODO Not sure if this is the right way to get the client ip
return request.META['HTTP_X_FORWARDED_FOR']
class SSOLogoutView(LogoutView):
"""View to log out of Plinth and remove the auth_pubtkt cookie"""
template_name = 'index.html'
def dispatch(self, request, *args, **kwargs):

View File

@ -23,7 +23,7 @@ from django.urls import reverse_lazy
from stronghold.decorators import public
from plinth.utils import non_admin_view
from plinth.modules.sso.views import SSOLoginView, SSOLogoutView, CaptchaLoginView
from plinth.modules.sso.views import SSOLoginView, SSOLogoutView
from . import views
from axes.decorators import watch_login
@ -49,9 +49,6 @@ urlpatterns = [
non_admin_view(SSOLogoutView.as_view()),
{'next_page': reverse_lazy('index')},
name='logout'),
url(r'^accounts/login/captcha/$',
public(CaptchaLoginView.as_view()),
name='captcha-login'),
url(r'^users/firstboot/$',
public(views.FirstBootView.as_view()),
name='firstboot'),

View File

@ -18,9 +18,10 @@
Django URLconf file containing all urls
"""
from captcha import views as cviews
from django.conf.urls import url, include
from django.conf.urls import url
from django.views.generic import TemplateView
from plinth.modules.sso.views import CaptchaLoginView
from stronghold.decorators import public
from . import views
@ -43,4 +44,5 @@ urlpatterns = [
kwargs={'scale': 2}),
url(r'audio/(?P<key>\w+)/$', public(cviews.captcha_audio), name='captcha-audio'),
url(r'refresh/$', public(cviews.captcha_refresh), name='captcha-refresh'),
url(r'locked/$', public(CaptchaLoginView.as_view()), name='locked_out'),
]

View File

@ -57,7 +57,7 @@ def non_admin_view(func):
def is_user_admin(request, cached=False):
"""Return whether user is an administrator."""
if not request.user.is_authenticated():
if not request.user.is_authenticated:
return False
if 'cache_user_is_admin' in request.session and cached: