diff --git a/arches/app/views/api/__init__.py b/arches/app/views/api/__init__.py index 50ce89a8c1..376007eb81 100644 --- a/arches/app/views/api/__init__.py +++ b/arches/app/views/api/__init__.py @@ -24,6 +24,7 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.files.base import ContentFile from django.views.decorators.csrf import csrf_exempt +from django.views.decorators.debug import sensitive_variables from django.utils import translation from django.utils.decorators import method_decorator from django_ratelimit.decorators import ratelimit @@ -1127,6 +1128,7 @@ def get(self, request, plugin_id=None): class SearchExport(View): + @sensitive_variables("user_cred") @method_decorator( ratelimit( key="header:http-authorization", rate=settings.RATE_LIMIT, block=False diff --git a/arches/app/views/api/auth.py b/arches/app/views/api/auth.py index 6f95f5b759..27ff81e1e0 100644 --- a/arches/app/views/api/auth.py +++ b/arches/app/views/api/auth.py @@ -4,6 +4,7 @@ from django.contrib.auth import authenticate, login, logout from django.utils.decorators import method_decorator from django.utils.translation import gettext as _ +from django.views.decorators.debug import sensitive_variables, sensitive_post_parameters from django_ratelimit.decorators import ratelimit from arches.app.models.system_settings import settings @@ -18,7 +19,11 @@ class Login(LoginView, APIBase): http_method_names = ["post"] @method_decorator( - ratelimit(key="post:username", rate=settings.RATE_LIMIT, block=False) + ( + sensitive_variables(), + sensitive_post_parameters(), + ratelimit(key="post:username", rate=settings.RATE_LIMIT, block=False), + ) ) def post(self, request): if getattr(request, "limited", False): diff --git a/arches/app/views/auth.py b/arches/app/views/auth.py index 4bc74ac2d1..978542a59f 100644 --- a/arches/app/views/auth.py +++ b/arches/app/views/auth.py @@ -19,7 +19,6 @@ import base64 import io -from django.http import response from arches.app.utils.external_oauth_backend import ExternalOauthAuthenticationBackend import qrcode import pyotp @@ -33,6 +32,7 @@ from django.utils.decorators import method_decorator from django.views.decorators.cache import never_cache from django.views.decorators.csrf import csrf_exempt +from django.views.decorators.debug import sensitive_post_parameters, sensitive_variables from django.utils.html import strip_tags from django.utils.translation import gettext as _ from django.utils.http import urlencode @@ -88,19 +88,23 @@ def get(self, request): ) @method_decorator( - ratelimit( - key="post:username", - rate=( - ( - "{}/{}".format( - int(settings.RATE_LIMIT.split("/")[0]) * 2, - settings.RATE_LIMIT.split("/")[1], + ( + sensitive_variables(), + sensitive_post_parameters(), + ratelimit( + key="post:username", + rate=( + ( + "{}/{}".format( + int(settings.RATE_LIMIT.split("/")[0]) * 2, + settings.RATE_LIMIT.split("/")[1], + ) ) - ) - if isinstance(settings.RATE_LIMIT, str) - else settings.RATE_LIMIT + if isinstance(settings.RATE_LIMIT, str) + else settings.RATE_LIMIT + ), + block=False, ), - block=False, ) ) def post(self, request): @@ -369,7 +373,13 @@ def get(self, request): } return JSONResponse(messages) - @method_decorator(ratelimit(key="user", rate=settings.RATE_LIMIT, block=False)) + @method_decorator( + ( + sensitive_variables(), + sensitive_post_parameters(), + ratelimit(key="user", rate=settings.RATE_LIMIT, block=False), + ) + ) def post(self, request): messages = { "invalid_password": None, @@ -425,7 +435,13 @@ class PasswordResetConfirmView(auth_views.PasswordResetConfirmView): @method_decorator(csrf_exempt, name="dispatch") class UserProfileView(View): - @method_decorator(ratelimit(key="post:username", rate=settings.RATE_LIMIT)) + @method_decorator( + ( + sensitive_variables(), + sensitive_post_parameters(), + ratelimit(key="post:username", rate=settings.RATE_LIMIT), + ) + ) def post(self, request): username = request.POST.get("username", None) password = request.POST.get("password", None) @@ -446,7 +462,13 @@ def post(self, request): @method_decorator(csrf_exempt, name="dispatch") class GetClientIdView(View): - @method_decorator(ratelimit(key="post:username", rate=settings.RATE_LIMIT)) + @method_decorator( + ( + sensitive_variables(), + sensitive_post_parameters(), + ratelimit(key="post:username", rate=settings.RATE_LIMIT), + ) + ) def post(self, request): if settings.OAUTH_CLIENT_ID == "": message = _("Make sure to set your OAUTH_CLIENT_ID in settings.py") @@ -465,7 +487,13 @@ def post(self, request): @method_decorator(csrf_exempt, name="dispatch") class ServerSettingView(View): - @method_decorator(ratelimit(key="post:username", rate=settings.RATE_LIMIT)) + @method_decorator( + ( + sensitive_variables(), + sensitive_post_parameters(), + ratelimit(key="post:username", rate=settings.RATE_LIMIT), + ) + ) def post(self, request): if settings.OAUTH_CLIENT_ID == "": message = _("Make sure to set your OAUTH_CLIENT_ID in settings.py") @@ -573,6 +601,7 @@ def post(self, request): @method_decorator(never_cache, name="dispatch") class TwoFactorAuthenticationLoginView(View): + @method_decorator((sensitive_variables(), sensitive_post_parameters())) def post(self, request): username = request.POST.get("username", None) password = request.POST.get("password", None) @@ -718,6 +747,7 @@ def post(self, request): @method_decorator(csrf_exempt, name="dispatch") class Token(View): + @method_decorator(sensitive_variables()) def get(self, request): if settings.DEBUG: data = { diff --git a/releases/8.0.0.md b/releases/8.0.0.md index 534dd729c2..48649f418f 100644 --- a/releases/8.0.0.md +++ b/releases/8.0.0.md @@ -19,6 +19,7 @@ Arches 8.0.0 Release Notes ### Additional highlights - Add session-based REST APIs for login, logout [#11261](https://github.com/archesproject/arches/issues/11261) +- Auth views now filter out passwords from error reports when running in production [#11652](https://github.com/archesproject/arches/issues/11652) - Improve handling of longer model names [#11317](https://github.com/archesproject/arches/issues/11317) - Support more expressive plugin URLs [#11320](https://github.com/archesproject/arches/issues/11320) - Make node aliases not nullable [#10437](https://github.com/archesproject/arches/issues/10437)