Skip to content

Commit

Permalink
Add configuration to require POST only authentication requsts (#493)
Browse files Browse the repository at this point in the history
* Add configuration to require POST only authentication requsts

* Rework configuration check

* Extract decorator

* Re-use require_POST from Django

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
sultaniman and pre-commit-ci[bot] authored Sep 7, 2023
1 parent 3798bc1 commit a5137ed
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ changelog.sh
.python-version

files/local.env
.venv/
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed
- Uses Django native JSON field
- Introduce configuration to request POST only requests for social authentication

## [5.2.0](https://github.com/python-social-auth/social-app-django/releases/tag/5.2.0) - 2023-03-31

Expand Down
15 changes: 15 additions & 0 deletions social_django/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.conf import settings
from django.http import Http404
from django.urls import reverse
from django.views.decorators.http import require_POST
from social_core.exceptions import MissingBackend
from social_core.utils import get_strategy, module_member, setting_name

Expand All @@ -12,6 +13,8 @@
STORAGE = getattr(
settings, setting_name("STORAGE"), "social_django.models.DjangoStorage"
)
REQUIRE_POST = setting_name("REQUIRE_POST")

Strategy = module_member(STRATEGY)
Storage = module_member(STORAGE)

Expand Down Expand Up @@ -48,3 +51,15 @@ def wrapper(request, backend, *args, **kwargs):
return wrapper

return decorator


def maybe_require_post(func):
@wraps(func)
def wrapper(request, backend, *args, **kwargs):
require_post = getattr(settings, REQUIRE_POST, False)
if require_post:
return require_POST(func)(request, backend, *args, **kwargs)

return func(request, backend, *args, **kwargs)

return wrapper
3 changes: 2 additions & 1 deletion social_django/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from social_core.actions import do_auth, do_complete, do_disconnect
from social_core.utils import setting_name

from .utils import psa
from .utils import maybe_require_post, psa

NAMESPACE = getattr(settings, setting_name("URL_NAMESPACE"), None) or "social"

Expand All @@ -17,6 +17,7 @@


@never_cache
@maybe_require_post
@psa(f"{NAMESPACE}:complete")
def auth(request, backend):
return do_auth(request.backend, redirect_name=REDIRECT_FIELD_NAME)
Expand Down
7 changes: 7 additions & 0 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ def test_begin_view(self):
response = self.client.get(url)
self.assertEqual(response.status_code, 404)

def test_require_post_works(self):
with override_settings(SOCIAL_AUTH_REQUIRE_POST=True):
response = self.client.get(
reverse("social:begin", kwargs={"backend": "facebook"})
)
self.assertEqual(response.status_code, 405)

@mock.patch("social_core.backends.base.BaseAuth.request")
def test_complete(self, mock_request):
url = reverse("social:complete", kwargs={"backend": "facebook"})
Expand Down

0 comments on commit a5137ed

Please sign in to comment.