from django.contrib.auth import get_user_model from django.test import override_settings from apps.core.auth_backends import EmailOrUsernameModelBackend from apps.core.entra import ( EntraConfigError, domain_allowed, entra_enabled, extract_identity, load_config, ) def test_auth_backend_rejects_missing_and_unknown_credentials(db): backend = EmailOrUsernameModelBackend() assert backend.authenticate(None, username=None, password=None) is None assert backend.authenticate(None, username="unknown@example.invalid", password="secret") is None def test_auth_backend_rejects_inactive_and_wrong_password(db): user = get_user_model().objects.create_user( username="inactive", email="inactive@example.invalid", password="correct", is_active=False ) backend = EmailOrUsernameModelBackend() assert backend.authenticate(None, username=user.email, password="wrong") is None assert backend.authenticate(None, username=user.email, password="correct") is None def test_auth_backend_handles_duplicate_email_without_ambiguous_login(db): user_model = get_user_model() first = user_model.objects.create_user( username="first", email="shared@example.invalid", password="correct" ) user_model.objects.create_user( username="second", email="shared@example.invalid", password="correct" ) backend = EmailOrUsernameModelBackend() assert backend.authenticate(None, username="shared@example.invalid", password="correct") is None assert backend.authenticate(None, username="first", password="correct") == first @override_settings(ENTRA_ID_ENABLED=True) def test_entra_enabled_reflects_configuration(): assert entra_enabled() is True @override_settings( ENTRA_ID_ENABLED=True, ENTRA_CLIENT_ID="", ENTRA_CLIENT_SECRET="", ENTRA_TENANT_ID="" ) def test_entra_config_fails_closed_when_credentials_are_incomplete(): try: load_config() except EntraConfigError as exc: assert "niet allemaal ingesteld" in str(exc) else: # pragma: no cover - defensive assertion raise AssertionError("Onvolledige Entra-configuratie werd geaccepteerd") @override_settings( ENTRA_CLIENT_ID="client", ENTRA_CLIENT_SECRET="secret", ENTRA_TENANT_ID="tenant", ENTRA_SCOPES=["User.Read"], ENTRA_ALLOWED_DOMAINS=["@Example.COM"], ENTRA_REDIRECT_URI="https://example.invalid/callback", ) def test_entra_config_normalizes_domains_and_identity_claims(): config = load_config() assert config.authority.endswith("/tenant") assert config.allowed_domains == ("example.com",) assert domain_allowed(config, "person@example.com") is True assert domain_allowed(config, "person@other.invalid") is False assert extract_identity( {"id_token_claims": {"preferred_username": " person@example.com ", "name": " Person "}} ) == ("person@example.com", "Person") @override_settings( ENTRA_CLIENT_ID="client", ENTRA_CLIENT_SECRET="secret", ENTRA_TENANT_ID="tenant", ENTRA_ALLOWED_DOMAINS=[], ) def test_entra_allows_any_domain_only_when_allowlist_is_empty(): assert domain_allowed(load_config(), "person@example.invalid") is True