Skip to content

fix(security): logowanie Microsoft — weryfikacja tenanta, ostrzeżenie bpp.W201, ostrożniejsze wiązanie kont - #894

Merged
mpasternak merged 4 commits into
devfrom
sec/microsoft-tenant
Oct 24, 2026
Merged

mpasternak merged 4 commits into
devfrom
sec/microsoft-tenant

Conversation

@mpasternak

@mpasternak mpasternak commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Co zmieniono

Hardening opcjonalnego logowania Office 365 (django-microsoft-auth, extra office365):

  • Tenant zalecany, nie wymagany (src/django_bpp/settings/base.py, src/bpp/auth/microsoft_conf.py): pusty MICROSOFT_AUTH_TENANT_ID jest normalizowany do common. Gdy ustawiono MICROSOFT_AUTH_CLIENT_ID, a tenant jest pusty albo równy common/organizations/consumers:
    • system check bpp.W201 (Warning, src/bpp/checks.py) z podpowiedzią: GUID katalogu albo domena uczelnia.onmicrosoft.com;
    • komunikat messages.warning dla superusera po zalogowaniu (handler user_logged_in, dispatch_uid="bpp.ostrzez_superusera_o_tenancie_microsoft", src/bpp/apps.py); błędy są logowane i nie blokują logowania.
  • Nowy backend bpp.auth.microsoft.BppMicrosoftAuthenticationBackend (zastępuje w AUTHENTICATION_BACKENDS backend z pakietu):
    • konkretny tenant: sprawdza iss tokenu względem issuer z discovery skonfigurowanego katalogu oraz tid (dla GUID-a również bezpośrednio); token odrzucany jest, zanim powstanie rekord MicrosoftAccount. Gdy zbuforowany dokument discovery nie pasuje do katalogu, cache jest jednorazowo odświeżany;
    • tryb wielokatalogowy (brak konkretnego tenanta): weryfikacja iss/tid jest pomijana, bo nie ma katalogu, względem którego można ją zrobić. Logują się wyłącznie konta Microsoft już powiązane z kontem BPP. Nowe konta nie są zakładane (niezależnie od MICROSOFT_AUTH_AUTO_CREATE) ani wiązane po e-mailu. Użytkownik dostaje neutralny komunikat „Konto Microsoft nie jest powiązane z kontem w BPP — skontaktuj się z administratorem”. Jawny opt-in MICROSOFT_AUTH_MULTI_TENANT_ALLOW_LINKING=True (nowy env, domyślnie False) włącza w tym trybie reguły opisane niżej;
    • reguły wiązania i zakładania kont: pusty e-mail → odmowa; wyszukanie przez email__iexact; więcej niż jedno trafienie → odmowa; istniejące konto is_staff/is_superuser albo z hasłem lokalnym nie jest automatycznie wiązane, chyba że MICROSOFT_AUTH_LINK_BY_EMAIL=True (nowy env, domyślnie False);
    • konta Microsoft już powiązane z użytkownikiem logują się bez zmian.
  • src/django_bpp/external_auth.py, src/django_bpp/views.py: nowa ścieżka backendu w EXTERNAL_AUTH_BACKENDS; dawna jest nadal rozpoznawana.
  • Dokumentacja: docs/administrator/zaawansowane.md, sekcja „Logowanie przez Microsoft”: zalecenie ustawienia tenanta, skutki jego braku i opt-in.

Wpływ na wdrożenia

  • Żadna instalacja nie przestaje startować. Brak tenanta albo common daje tylko ostrzeżenie bpp.W201 i komunikat dla superusera.
  • Instalacje bez konkretnego tenanta: logują się dalej konta Microsoft już powiązane z BPP. Pierwsze logowanie nowego konta Microsoft (założenie konta albo powiązanie po e-mailu) zostanie odrzucone. Aby to zmienić, ustaw MICROSOFT_AUTH_TENANT_ID (zalecane) albo świadomie MICROSOFT_AUTH_MULTI_TENANT_ALLOW_LINKING=True. Konto można też powiązać ręcznie w adminie (Microsoft accounts).
  • Przy obu trybach pierwsze logowanie przez Microsoft na istniejące konto admina albo konto z hasłem lokalnym wymaga ręcznego powiązania w adminie albo ustawienia MICROSOFT_AUTH_LINK_BY_EMAIL=True.
  • Ścieżka backendu się zmieniła, więc użytkownicy zalogowani przez Microsoft muszą jednorazowo zalogować się ponownie.

Testy

src/bpp/tests/test_auth_microsoft.py:

  • funkcje decyzyjne (normalizacja tenanta, claimy, decyzja o wiązaniu), check bpp.W201 (puste, common, organizations, consumers, GUID, domena, opt-in) i komunikat po prawdziwym POST na /admin/login/ (superuser go dostaje, zwykły staff nie, przy GUID-zie nikt, wyjątek w handlerze nie blokuje logowania) — bez markera, biegną w CI;
  • testy backendu mają marker uruchom_tylko_z_microsoft_auth, więc w CI są pomijane. Obejmują konkretny tenant oraz tryb wielokatalogowy: powiązane konto się loguje; niepowiązane jest odrzucane, nie powstaje nowy użytkownik ani wiązanie po e-mailu, także dla kont bez uprawnień; z opt-in obowiązują ostrożne reguły. Lokalnie uruchamiasz je tak:
MICROSOFT_AUTH_CLIENT_ID=test-client MICROSOFT_AUTH_CLIENT_SECRET=x \
  MICROSOFT_AUTH_TENANT_ID=11111111-2222-3333-4444-555555555555 \
  uv run pytest src/bpp/tests/test_auth_microsoft.py src/bpp/tests/test_konta_bez_uczelni.py

Wyniki lokalne (test_auth_microsoft.py + test_konta_bez_uczelni.py):

  • tenant jako GUID: 74 passed;
  • tenant common: 74 passed;
  • pusty tenant: 74 passed;
  • bez microsoft_auth: 49 passed, 25 skipped.

Pokrewne moduły (checks, szyfrowanie sekretów, auth_server, password middleware, context processor, smart password change): 67 passed bez microsoft_auth i 67 passed z common.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UJ23Rb1c5UtxHTfAke9ENQ

@gitguardian

gitguardian Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 3 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
38940246 Triggered Generic Password ca40250 src/bpp/tests/test_auth_microsoft.py View secret
38949182 Triggered Username Password 4ce6391 src/bpp/tests/test_auth_microsoft.py View secret
38940246 Triggered Generic Password ca40250 src/bpp/tests/test_auth_microsoft.py View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

mpasternak and others added 4 commits October 24, 2026 22:45
…t Microsoft

- logowanie Office 365 wymaga MICROSOFT_AUTH_TENANT_ID wskazującego konkretny
  katalog Entra ID (GUID lub domena); puste/common/organizations/consumers
  -> ImproperlyConfigured przy starcie,
- nowy backend bpp.auth.microsoft.BppMicrosoftAuthenticationBackend
  (zamiast backendu z pakietu) sprawdza claimy iss/tid tokenu względem
  skonfigurowanego katalogu,
- nowe konto Microsoft nie jest automatycznie wiązane po e-mailu
  z istniejącym kontem staff/superuser lub z hasłem lokalnym, chyba że
  MICROSOFT_AUTH_LINK_BY_EMAIL=True (domyślnie False); konta już
  powiązane logują się bez zmian,
- dawna ścieżka backendu nadal rozpoznawana jako zewnętrzna (polityka haseł),
- dokumentacja w docs/administrator/zaawansowane.md, testy, newsfragment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UJ23Rb1c5UtxHTfAke9ENQ
…covery

- nowe konto Microsoft bez (lub z pustym) adresem e-mail nie jest ani
  wiązane, ani zakładane,
- wyszukanie istniejącego użytkownika bez rozróżniania wielkości liter;
  więcej niż jedno trafienie -> odmowa; backend nie deleguje już
  wiązania/zakładania do pakietu,
- gdy zbuforowany dokument OpenID discovery nie odpowiada skonfigurowanemu
  katalogowi, cache jest jednorazowo odświeżany,
- testy i doprecyzowana dokumentacja.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UJ23Rb1c5UtxHTfAke9ENQ
…ie błąd startu

Pusty lub ogólny MICROSOFT_AUTH_TENANT_ID (common/organizations/consumers)
nie blokuje już startu. Zamiast ImproperlyConfigured: system check
bpp.W201 i komunikat dla superusera po zalogowaniu z podpowiedzią
(GUID lub domena katalogu). Backend w trybie wielokatalogowym pomija
weryfikację iss/tid, ale zachowuje ostrożne wiązanie kont. Przy
konkretnym tenancie - pełna weryfikacja jak dotąd.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UJ23Rb1c5UtxHTfAke9ENQ
…ązanych

Bez konkretnego MICROSOFT_AUTH_TENANT_ID logują się wyłącznie konta
Microsoft już powiązane z kontem BPP: bez zakładania nowych kont i bez
wiązania po adresie e-mail (także dla kont bez uprawnień), z neutralnym
komunikatem dla użytkownika. Jawny opt-in
MICROSOFT_AUTH_MULTI_TENANT_ALLOW_LINKING=True przywraca ostrożne reguły
wiązania. Treść bpp.W201 i komunikatu dla superusera opisuje ten tryb.
Przy konkretnym tenancie zachowanie bez zmian.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UJ23Rb1c5UtxHTfAke9ENQ
@mpasternak
mpasternak force-pushed the sec/microsoft-tenant branch from 9af6e94 to 5503435 Compare October 24, 2026 20:45
@mpasternak mpasternak changed the title fix(security): logowanie Microsoft — wymagany konkretny tenant, ostrożniejsze wiązanie kont fix(security): logowanie Microsoft — weryfikacja tenanta, ostrzeżenie bpp.W201, ostrożniejsze wiązanie kont Oct 24, 2026
assert wynik[0].id == W_TENANT_ID == "bpp.W201"
assert isinstance(wynik[0], checks.Warning)
assert "MICROSOFT_AUTH_TENANT_ID" in wynik[0].hint
assert "onmicrosoft.com" in wynik[0].hint
)
komunikaty = _komunikaty(_zaloguj(client, "szef"))
assert any(
OSTRZEZENIE in m and "onmicrosoft.com" in m and "są wyłączone" in m
@mpasternak
mpasternak merged commit fb5b440 into dev Oct 24, 2026
25 of 27 checks passed
@mpasternak
mpasternak deleted the sec/microsoft-tenant branch October 24, 2026 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants