Skip to content

Commit

Permalink
[fix] CSRF for login and signup (#1536)
Browse files Browse the repository at this point in the history
* [fix] CSRF for login/signup pages

* Add decorators

* Fix tests

* Fix tests

* Add CSRF tests

* Update views.py
  • Loading branch information
makseq committed Sep 28, 2021
1 parent 1073735 commit affafa0
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 5 deletions.
27 changes: 23 additions & 4 deletions label_studio/core/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,35 @@
from django.core.exceptions import MiddlewareNotUsed
from django.middleware.common import CommonMiddleware
from django.conf import settings
from django.utils import timezone

from django.utils.http import escape_leading_slashes
from rest_framework.permissions import SAFE_METHODS
from rest_framework.response import Response
from core.utils.contextlog import ContextLog


def enforce_csrf_checks(func):
""" Enable csrf for specified view func
"""
# USE_ENFORCE_CSRF_CHECKS=False is for tests
if settings.USE_ENFORCE_CSRF_CHECKS:
def wrapper(request, *args, **kwargs):
return func(request, *args, **kwargs)

wrapper._dont_enforce_csrf_checks = False
return wrapper
else:
return func


class DisableCSRF(MiddlewareMixin):
def process_request(self, request):
setattr(request, '_dont_enforce_csrf_checks', True)
# disable csrf for api requests
def process_view(self, request, callback, *args, **kwargs):
if hasattr(callback, '_dont_enforce_csrf_checks'):
setattr(request, '_dont_enforce_csrf_checks', callback._dont_enforce_csrf_checks)
elif request.GET.get('enforce_csrf_checks'): # _dont_enforce_csrf_checks is for test
setattr(request, '_dont_enforce_csrf_checks', False)
else:
setattr(request, '_dont_enforce_csrf_checks', True)


class HttpSmartRedirectResponse(HttpResponsePermanentRedirect):
Expand Down
4 changes: 3 additions & 1 deletion label_studio/core/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'core.middleware.DisableCSRF',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
Expand Down Expand Up @@ -401,6 +401,8 @@
ALLOW_ORGANIZATION_WEBHOOKS = get_bool_env('ALLOW_ORGANIZATION_WEBHOOKS', False)
CONVERTER_DOWNLOAD_RESOURCES = get_bool_env('CONVERTER_DOWNLOAD_RESOURCES', True)
EXPERIMENTAL_FEATURES = get_bool_env('EXPERIMENTAL_FEATURES', False)
USE_ENFORCE_CSRF_CHECKS = get_bool_env('USE_ENFORCE_CSRF_CHECKS', True) # False is for tests


CREATE_ORGANIZATION = 'organizations.functions.create_organization'
GET_OBJECT_WITH_CHECK_AND_LOG = 'core.utils.get_object.get_object_with_check_and_log'
Expand Down
1 change: 1 addition & 0 deletions label_studio/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ filterwarnings =
env =
D:SENTRY_RATE=0
D:SENTRY_DSN=
D:USE_ENFORCE_CSRF_CHECKS=0
5 changes: 5 additions & 0 deletions label_studio/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
boto3.set_stream_logger('botocore.credentials', logging.DEBUG)


@pytest.fixture(autouse=False)
def enable_csrf():
settings.USE_ENFORCE_CSRF_CHECKS = True


@pytest.fixture(autouse=True)
def disable_sentry():
settings.SENTRY_RATE = 0
Expand Down
30 changes: 30 additions & 0 deletions label_studio/tests/csrf.tavern.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
test_name: csrf check
strict: false
marks:
- usefixtures:
- django_live_url
- enable_csrf
stages:
- id: login_csrf
name: Sign up without csrf
request:
url: "{django_live_url}/user/signup?enforce_csrf_checks=1"
data:
email: test_suites_user@heartex.com
password: 12345678
method: POST
response:
status_code: 403

- id: login_csrf
name: Login without csrf
request:
url: "{django_live_url}/user/login?enforce_csrf_checks=1"
data:
email: test_suites_user@heartex.com
password: 12345678
method: POST
response:
status_code: 403

3 changes: 3 additions & 0 deletions label_studio/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from users import forms
from core.utils.common import load_func
from core.middleware import enforce_csrf_checks
from users.functions import proceed_registration
from organizations.models import Organization
from organizations.forms import OrganizationSignupForm
Expand All @@ -30,6 +31,7 @@ def logout(request):
return redirect('/')


@enforce_csrf_checks
def user_signup(request):
""" Sign up page
"""
Expand Down Expand Up @@ -66,6 +68,7 @@ def user_signup(request):
})


@enforce_csrf_checks
def user_login(request):
""" Login page
"""
Expand Down

0 comments on commit affafa0

Please sign in to comment.