diff --git a/common b/common index f3c2619adb1..ac9eafa1e57 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit f3c2619adb171d1cbfae9c28922dddc46cd98cd1 +Subproject commit ac9eafa1e57c5ab3cff5af9acad1e93c85989e8c diff --git a/readthedocs/restapi/authentication.py b/readthedocs/restapi/authentication.py new file mode 100644 index 00000000000..d9465c704ac --- /dev/null +++ b/readthedocs/restapi/authentication.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from rest_framework.authentication import SessionAuthentication + + +class CsrfExemptSessionAuthentication(SessionAuthentication): + + """ + Session authentication class exempt of CSRF. + + DRF by default when using a ``SessionAuthentication`` it enforces CSRF. + + See: https://github.com/encode/django-rest-framework/blob/3.9.0/rest_framework/authentication.py#L134-L144 # noqa + """ + + def enforce_csrf(self, request): + return diff --git a/readthedocs/restapi/views/integrations.py b/readthedocs/restapi/views/integrations.py index 7f44fb4f11a..6ab43b75f76 100644 --- a/readthedocs/restapi/views/integrations.py +++ b/readthedocs/restapi/views/integrations.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """Endpoints integrating with Github, Bitbucket, and other webhooks.""" import json @@ -23,6 +21,8 @@ from readthedocs.integrations.utils import normalize_request_payload from readthedocs.projects.models import Project +from ..authentication import CsrfExemptSessionAuthentication + log = logging.getLogger(__name__) @@ -349,7 +349,7 @@ class IsAuthenticatedOrHasToken(permissions.IsAuthenticated): """ def has_permission(self, request, view): - has_perm = (super().has_permission(request, view)) + has_perm = super().has_permission(request, view) return has_perm or 'token' in request.data @@ -422,6 +422,11 @@ class WebhookView(APIView): be. """ + # We want to avoid CSRF checking when authenticating by user/password on + # this API endpoint so we can make a request like: + # curl -X POST -d "branches=branch" -u user:pass -e URL /api/v2/webhook/test-builds/{pk}/ + authentication_classes = [CsrfExemptSessionAuthentication] + VIEW_MAP = { Integration.GITHUB_WEBHOOK: GitHubWebhookView, Integration.GITLAB_WEBHOOK: GitLabWebhookView,