Changeset View
Changeset View
Standalone View
Standalone View
swh/web/tests/auth/test_backends.py
Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | def _check_authenticated_user(user, decoded_token, kc_oidc_mock): | ||||
assert user.sub == decoded_token["sub"] | assert user.sub == decoded_token["sub"] | ||||
resource_access = decoded_token.get("resource_access", {}) | resource_access = decoded_token.get("resource_access", {}) | ||||
resource_access_client = resource_access.get(kc_oidc_mock, {}) | resource_access_client = resource_access.get(kc_oidc_mock, {}) | ||||
assert user.permissions == set(resource_access_client.get("roles", [])) | assert user.permissions == set(resource_access_client.get("roles", [])) | ||||
@pytest.mark.django_db | @pytest.mark.django_db | ||||
def test_oidc_code_pkce_auth_backend_success(mocker, request_factory): | def test_oidc_code_pkce_auth_backend_success(mocker, request_factory): | ||||
""" | |||||
Checks successful login based on OpenID Connect with PKCE extension | |||||
Django authentication backend (login from Web UI). | |||||
""" | |||||
kc_oidc_mock = mock_keycloak(mocker, user_groups=["/staff"]) | kc_oidc_mock = mock_keycloak(mocker, user_groups=["/staff"]) | ||||
oidc_profile = sample_data.oidc_profile | oidc_profile = sample_data.oidc_profile | ||||
user = _authenticate_user(request_factory) | user = _authenticate_user(request_factory) | ||||
decoded_token = kc_oidc_mock.decode_token(user.access_token) | decoded_token = kc_oidc_mock.decode_token(user.access_token) | ||||
_check_authenticated_user(user, decoded_token, kc_oidc_mock) | _check_authenticated_user(user, decoded_token, kc_oidc_mock) | ||||
auth_datetime = datetime.fromtimestamp(decoded_token["auth_time"]) | auth_datetime = datetime.fromtimestamp(decoded_token["auth_time"]) | ||||
Show All 13 Lines | def test_oidc_code_pkce_auth_backend_success(mocker, request_factory): | ||||
backend_path = "swh.web.auth.backends.OIDCAuthorizationCodePKCEBackend" | backend_path = "swh.web.auth.backends.OIDCAuthorizationCodePKCEBackend" | ||||
assert user.backend == backend_path | assert user.backend == backend_path | ||||
backend_idx = settings.AUTHENTICATION_BACKENDS.index(backend_path) | backend_idx = settings.AUTHENTICATION_BACKENDS.index(backend_path) | ||||
assert get_backends()[backend_idx].get_user(user.id) == user | assert get_backends()[backend_idx].get_user(user.id) == user | ||||
@pytest.mark.django_db | @pytest.mark.django_db | ||||
def test_oidc_code_pkce_auth_backend_failure(mocker, request_factory): | def test_oidc_code_pkce_auth_backend_failure(mocker, request_factory): | ||||
""" | |||||
Checks failed login based on OpenID Connect with PKCE extension Django | |||||
authentication backend (login from Web UI). | |||||
""" | |||||
mock_keycloak(mocker, auth_success=False) | mock_keycloak(mocker, auth_success=False) | ||||
user = _authenticate_user(request_factory) | user = _authenticate_user(request_factory) | ||||
assert user is None | assert user is None | ||||
@pytest.mark.django_db | @pytest.mark.django_db | ||||
def test_oidc_code_pkce_auth_backend_permissions(mocker, request_factory): | def test_oidc_code_pkce_auth_backend_permissions(mocker, request_factory): | ||||
""" | |||||
Checks that a permission defined with OpenID Connect is correctly mapped | |||||
to a Django one when logging from Web UI. | |||||
""" | |||||
permission = "webapp.some-permission" | permission = "webapp.some-permission" | ||||
mock_keycloak(mocker, user_permissions=[permission]) | mock_keycloak(mocker, user_permissions=[permission]) | ||||
user = _authenticate_user(request_factory) | user = _authenticate_user(request_factory) | ||||
assert user.has_perm(permission) | assert user.has_perm(permission) | ||||
assert user.get_all_permissions() == {permission} | assert user.get_all_permissions() == {permission} | ||||
assert user.get_group_permissions() == {permission} | assert user.get_group_permissions() == {permission} | ||||
assert user.has_module_perms("webapp") | assert user.has_module_perms("webapp") | ||||
assert not user.has_module_perms("foo") | assert not user.has_module_perms("foo") | ||||
@pytest.mark.django_db | @pytest.mark.django_db | ||||
def test_drf_oidc_bearer_token_auth_backend_success(mocker, api_request_factory): | def test_drf_oidc_bearer_token_auth_backend_success(mocker, api_request_factory): | ||||
""" | |||||
Checks successful login based on OpenID Connect bearer token Django REST | |||||
Framework authentication backend (Web API login). | |||||
""" | |||||
url = reverse("api-1-stat-counters") | url = reverse("api-1-stat-counters") | ||||
drf_auth_backend = OIDCBearerTokenAuthentication() | drf_auth_backend = OIDCBearerTokenAuthentication() | ||||
kc_oidc_mock = mock_keycloak(mocker) | kc_oidc_mock = mock_keycloak(mocker) | ||||
access_token = sample_data.oidc_profile["access_token"] | access_token = sample_data.oidc_profile["access_token"] | ||||
decoded_token = kc_oidc_mock.decode_token(access_token) | decoded_token = kc_oidc_mock.decode_token(access_token) | ||||
request = api_request_factory.get(url, HTTP_AUTHORIZATION=f"Bearer {access_token}") | request = api_request_factory.get(url, HTTP_AUTHORIZATION=f"Bearer {access_token}") | ||||
user, _ = drf_auth_backend.authenticate(request) | user, _ = drf_auth_backend.authenticate(request) | ||||
_check_authenticated_user(user, decoded_token, kc_oidc_mock) | _check_authenticated_user(user, decoded_token, kc_oidc_mock) | ||||
# oidc_profile is not filled when authenticating through bearer token | # oidc_profile is not filled when authenticating through bearer token | ||||
assert hasattr(user, "access_token") and user.access_token is None | assert hasattr(user, "access_token") and user.access_token is None | ||||
@pytest.mark.django_db | @pytest.mark.django_db | ||||
def test_drf_oidc_bearer_token_auth_backend_failure(mocker, api_request_factory): | def test_drf_oidc_bearer_token_auth_backend_failure(mocker, api_request_factory): | ||||
""" | |||||
Checks failed login based on OpenID Connect bearer token Django REST | |||||
Framework authentication backend (Web API login). | |||||
""" | |||||
url = reverse("api-1-stat-counters") | url = reverse("api-1-stat-counters") | ||||
drf_auth_backend = OIDCBearerTokenAuthentication() | drf_auth_backend = OIDCBearerTokenAuthentication() | ||||
# simulate a failed authentication with a bearer token in expected format | # simulate a failed authentication with a bearer token in expected format | ||||
mock_keycloak(mocker, auth_success=False) | mock_keycloak(mocker, auth_success=False) | ||||
access_token = sample_data.oidc_profile["access_token"] | access_token = sample_data.oidc_profile["access_token"] | ||||
Show All 9 Lines | request = api_request_factory.get( | ||||
url, HTTP_AUTHORIZATION="Bearer invalid-token-format" | url, HTTP_AUTHORIZATION="Bearer invalid-token-format" | ||||
) | ) | ||||
with pytest.raises(AuthenticationFailed): | with pytest.raises(AuthenticationFailed): | ||||
drf_auth_backend.authenticate(request) | drf_auth_backend.authenticate(request) | ||||
def test_drf_oidc_auth_invalid_or_missing_auth_type(api_request_factory): | def test_drf_oidc_auth_invalid_or_missing_auth_type(api_request_factory): | ||||
""" | |||||
Checks failed login based on OpenID Connect bearer token Django REST | |||||
Framework authentication backend (Web API login) due to invalid | |||||
authorization header value. | |||||
""" | |||||
url = reverse("api-1-stat-counters") | url = reverse("api-1-stat-counters") | ||||
drf_auth_backend = OIDCBearerTokenAuthentication() | drf_auth_backend = OIDCBearerTokenAuthentication() | ||||
access_token = sample_data.oidc_profile["access_token"] | access_token = sample_data.oidc_profile["access_token"] | ||||
# Invalid authorization type | # Invalid authorization type | ||||
request = api_request_factory.get(url, HTTP_AUTHORIZATION="Foo token") | request = api_request_factory.get(url, HTTP_AUTHORIZATION="Foo token") | ||||
with pytest.raises(AuthenticationFailed): | with pytest.raises(AuthenticationFailed): | ||||
drf_auth_backend.authenticate(request) | drf_auth_backend.authenticate(request) | ||||
# Missing authorization type | # Missing authorization type | ||||
request = api_request_factory.get(url, HTTP_AUTHORIZATION=f"{access_token}") | request = api_request_factory.get(url, HTTP_AUTHORIZATION=f"{access_token}") | ||||
with pytest.raises(AuthenticationFailed): | with pytest.raises(AuthenticationFailed): | ||||
drf_auth_backend.authenticate(request) | drf_auth_backend.authenticate(request) | ||||
@pytest.mark.django_db | @pytest.mark.django_db | ||||
def test_drf_oidc_bearer_token_auth_backend_permissions(mocker, api_request_factory): | def test_drf_oidc_bearer_token_auth_backend_permissions(mocker, api_request_factory): | ||||
""" | |||||
Checks that a permission defined with OpenID Connect is correctly mapped | |||||
to a Django one when using bearer token authentication. | |||||
""" | |||||
permission = "webapp.some-permission" | permission = "webapp.some-permission" | ||||
mock_keycloak(mocker, user_permissions=[permission]) | mock_keycloak(mocker, user_permissions=[permission]) | ||||
drf_auth_backend = OIDCBearerTokenAuthentication() | drf_auth_backend = OIDCBearerTokenAuthentication() | ||||
access_token = sample_data.oidc_profile["access_token"] | access_token = sample_data.oidc_profile["access_token"] | ||||
url = reverse("api-1-stat-counters") | url = reverse("api-1-stat-counters") | ||||
request = api_request_factory.get(url, HTTP_AUTHORIZATION=f"Bearer {access_token}") | request = api_request_factory.get(url, HTTP_AUTHORIZATION=f"Bearer {access_token}") | ||||
user, _ = drf_auth_backend.authenticate(request) | user, _ = drf_auth_backend.authenticate(request) | ||||
assert user.has_perm(permission) | assert user.has_perm(permission) | ||||
assert user.get_all_permissions() == {permission} | assert user.get_all_permissions() == {permission} | ||||
assert user.get_group_permissions() == {permission} | assert user.get_group_permissions() == {permission} | ||||
assert user.has_module_perms("webapp") | assert user.has_module_perms("webapp") | ||||
assert not user.has_module_perms("foo") | assert not user.has_module_perms("foo") |