|
9 | 9 | from django.contrib.sessions.middleware import SessionMiddleware |
10 | 10 | from unittest.mock import MagicMock |
11 | 11 | from django.http import HttpRequest |
12 | | -from django.test.client import RequestFactory |
| 12 | +from django.test.client import RequestFactory, Client |
13 | 13 | from django.urls import NoReverseMatch |
14 | 14 | from saml2 import BINDING_HTTP_POST |
15 | 15 |
|
| 16 | +from django_saml2_auth.errors import INACTIVE_USER |
16 | 17 | from django_saml2_auth.exceptions import SAMLAuthError |
17 | 18 | from django_saml2_auth.saml import ( |
18 | 19 | decode_saml_response, |
@@ -771,3 +772,76 @@ def test_get_metadata_success_with_custom_trigger(settings: SettingsWrapper): |
771 | 772 | get_metadata(domain="not-mapped-example.com") |
772 | 773 |
|
773 | 774 | assert str(exc_info.value) == "Domain not-mapped-example.com not mapped!" |
| 775 | + |
| 776 | + |
| 777 | +@pytest.mark.django_db |
| 778 | +@responses.activate |
| 779 | +def test_acs_view_with_use_jwt_both_redirects_user_and_sets_cookies( |
| 780 | + settings: SettingsWrapper, |
| 781 | + monkeypatch: "MonkeyPatch", # type: ignore # noqa: F821 |
| 782 | +): |
| 783 | + """Test Acs view when USE_JWT is set, the user is redirected and cookies are set""" |
| 784 | + responses.add(responses.GET, METADATA_URL1, body=METADATA1) |
| 785 | + settings.SAML2_AUTH = { |
| 786 | + "DEFAULT_NEXT_URL": "default_next_url", |
| 787 | + "USE_JWT": True, |
| 788 | + "JWT_SECRET": "JWT_SECRET", |
| 789 | + "JWT_ALGORITHM": "HS256", |
| 790 | + "FRONTEND_URL": "https://app.example.com/account/login/saml", |
| 791 | + "TRIGGER": { |
| 792 | + "BEFORE_LOGIN": None, |
| 793 | + "AFTER_LOGIN": None, |
| 794 | + "GET_METADATA_AUTO_CONF_URLS": GET_METADATA_AUTO_CONF_URLS, |
| 795 | + }, |
| 796 | + } |
| 797 | + monkeypatch.setattr( |
| 798 | + Saml2Client, "parse_authn_request_response", mock_parse_authn_request_response |
| 799 | + ) |
| 800 | + client = Client() |
| 801 | + response = client.post("/acs/", {"SAMLResponse": "SAML RESPONSE", "RelayState": "/"}) |
| 802 | + |
| 803 | + # Response includes a redirect to the single page app, with the JWT in the query string. |
| 804 | + assert response.status_code == 302 |
| 805 | + assert "https://app.example.com/account/login/saml?token=eyJ" in getattr(response, "url") |
| 806 | + # Response includes a session id cookie (i.e. the user is logged in to the django admin console) |
| 807 | + assert response.cookies.get("sessionid") |
| 808 | + |
| 809 | + |
| 810 | +@pytest.mark.django_db |
| 811 | +@responses.activate |
| 812 | +def test_acs_view_use_jwt_set_inactive_user( |
| 813 | + settings: SettingsWrapper, |
| 814 | + monkeypatch: "MonkeyPatch", # type: ignore # noqa: F821 |
| 815 | +): |
| 816 | + """Test Acs view when USE_JWT is set that inactive users can not log in""" |
| 817 | + responses.add(responses.GET, METADATA_URL1, body=METADATA1) |
| 818 | + settings.SAML2_AUTH = { |
| 819 | + "DEFAULT_NEXT_URL": "default_next_url", |
| 820 | + "USE_JWT": True, |
| 821 | + "JWT_SECRET": "JWT_SECRET", |
| 822 | + "JWT_ALGORITHM": "HS256", |
| 823 | + "FRONTEND_URL": "https://app.example.com/account/login/saml", |
| 824 | + "TRIGGER": { |
| 825 | + "BEFORE_LOGIN": None, |
| 826 | + "AFTER_LOGIN": None, |
| 827 | + "GET_METADATA_AUTO_CONF_URLS": GET_METADATA_AUTO_CONF_URLS, |
| 828 | + }, |
| 829 | + } |
| 830 | + post_request = RequestFactory().post(METADATA_URL1, {"SAMLResponse": "SAML RESPONSE"}) |
| 831 | + monkeypatch.setattr( |
| 832 | + Saml2Client, "parse_authn_request_response", mock_parse_authn_request_response |
| 833 | + ) |
| 834 | + created, mock_user = user.get_or_create_user( |
| 835 | + {"username": "test@example.com", "first_name": "John", "last_name": "Doe"} |
| 836 | + ) |
| 837 | + mock_user.is_active = False |
| 838 | + mock_user.save() |
| 839 | + monkeypatch.setattr(user, "get_or_create_user", (created, mock_user)) |
| 840 | + |
| 841 | + middleware = SessionMiddleware(MagicMock()) |
| 842 | + middleware.process_request(post_request) |
| 843 | + post_request.session.save() |
| 844 | + |
| 845 | + result = acs(post_request) |
| 846 | + assert result.status_code == 500 |
| 847 | + assert f"Error code: {INACTIVE_USER}" in result.content.decode() |
0 commit comments