# Automatické přihlašování proti Active Directory (Windows Authentication)

### Princip a protokoly

<div id="bkmrk-automatick%C3%A9-p%C5%99ihl%C3%A1%C5%A1e">Automatické přihlášení je zapnuté jen tehdy, když jsou v konfiguraci nastavené obě volby `LDAP:active = true` a `LDAP:automaticLogin = true`. Současné zapnutí `LDAP:active` a `KeyCloak:active` aplikace odmítne už při startu. Výchozím schématem ověření je pak Negotiate (balíček `Microsoft.AspNetCore.Authentication.Negotiate`). Prohlížeč a server se přes něj domluví na protokolu Kerberos, a když to nejde, automaticky přejdou na NTLM. Aplikace zpracuje všechny tři typy identity, které mohou přijít: `Kerberos`, `NTLM` i `Negotiate`.</div><div id="bkmrk-aplikace-b%C4%9B%C5%BE%C3%AD-na-ser">Aplikace běží na serveru Kestrel. Windows ověření proto provádí sama aplikace, ne IIS. Při nasazení pod IIS by ověření převzalo IIS a muselo by tam být zapnuté Windows Authentication. Ověření přes URL klíč (schéma `URLKEY`) funguje dál. Pokud v požadavku klíč chybí, aplikace vyvolá výzvu k ověření přes Negotiate.</div><div id="bkmrk-po%C5%BEadavky-na-infrast">Požadavky na infrastrukturu (nejsou součástí kódu):</div>- <div role="presentation">server musí být členem domény,</div>
- <div role="presentation">pro Kerberos musí být na účtu, pod kterým aplikace běží, zaregistrovaný SPN `HTTP/&lt;hostname&gt;`. Bez něj se použije NTLM,</div>
- <div role="presentation">adresa aplikace musí být v prohlížeči klienta v zóně Místní intranet (případně povolená politikou), jinak prohlížeč nepošle přihlašovací údaje automaticky,</div>
- <div role="presentation">licence musí obsahovat modul `ActiveDirectory`. Bez něj se automatické přihlášení nezdaří.</div>

### Získání a uložení uživatele při přihlášení

<div id="bkmrk-po-%C3%BAsp%C4%9B%C5%A1n%C3%A9m-windows-">Po úspěšném Windows ověření převede `ClaimsTransformation` doménovou identitu na aplikačního uživatele. Volá k tomu `UserActiveDirectoryManager.NtlmCheckAndSyncLoginAgainstActiveDirectory`. Pro každé připojení k AD z tabulky `ActiveDirectories` (připojení přes servisní účet) proběhne:</div>1. <div role="presentation">Dohledání uživatele v AD podle `sAMAccountName`. Zkouší se jméno s doménou (`DOMENA\uzivatel`) i bez ní.</div>
2. <div role="presentation">Zjištění členství ve všech AD skupinách, které jsou namapované na skupiny Infoportu.</div>
3. <div role="presentation">Kontrola `LDAP:OnlyActiveDirectoryGroups`: pokud je volba zapnutá a uživatel není v žádné namapované AD skupině, nepřihlásí se a do DB se nezapíše.</div>
4. <div role="presentation">Uložení do DB Infoportu:</div>

- <div role="presentation">neexistujícího uživatele aplikace založí (výchozí `RepositoryId = 1`),</div>
- <div role="presentation">existujícímu aktualizuje e-mail, jméno a příjmení podle AD,</div>
- <div role="presentation">dříve smazaného uživatele obnoví, pokud je v AD stále platný.</div>


5. <div role="presentation">Synchronizace skupin a rolí: uživatele přidá do skupin Infoportu podle aktuálního členství v AD skupinách, nebo ho z nich odebere. Stejně upraví i roli `Repository` v příslušných repozitářích.</div>
6. <div role="presentation">Kontrola přístupu do repozitáře a přihlášení:</div>

- <div role="presentation">pokud uživatel nemá přístup do svého aktuálního repozitáře, přepne se do prvního repozitáře, kam přístup má (přes vlastní claimy nebo členství ve skupině),</div>
- <div role="presentation">pokud takový repozitář neexistuje, aplikace ho odhlásí,</div>
- <div role="presentation">jinak se vytvoří aplikační přihlášení (`SignInAsync`, cookie `Identity.Application`).</div>


### Vztah k jobu na AD synchronizaci

<div id="bkmrk-automatick%C3%A9-p%C5%99ihl%C3%A1%C5%A1e-0">Automatické přihlášení nevyžaduje, aby běžel job na synchronizaci AD (`SynchronizeADUsersJob`). Uživatel se založí, aktualizuje a zařadí do skupin přímo při přihlášení. K přihlášení stačí:</div>- <div role="presentation">licence s modulem `ActiveDirectory`,</div>
- <div role="presentation">připojení k AD nastavené v administraci (Active Directory Manager),</div>
- <div role="presentation">mapování AD skupin na skupiny Infoportu, rovněž nastavené ručně v administraci,</div>
- <div role="presentation">dostupné AD v okamžiku přihlášení.</div>

<div id="bkmrk-job-je-dopl%C5%88kov%C3%BD.-d%C3%A1">Job je doplňkový. Dávkově synchronizuje všechny členy namapovaných skupin, takže uživatelé existují v Infoportu dřív, než se poprvé přihlásí, a lze jim předem nastavovat práva. Změny v AD (odchody, změny členství) se díky němu promítnou i u uživatelů, kteří se nepřihlašují.</div>### Omezení a známá rizika

- <div role="presentation">Výkon: převod identity proběhne při každém ověření požadavku přes Negotiate. Každý takový průchod znamená dotaz do AD, zápisy do DB a nové přihlášení. Při vyšší zátěži to může zatížit AD i databázi.</div>
- <div role="presentation">Nedostupné AD: když se uživatele nepodaří dohledat (AD je nedostupné nebo chybí připojení), aplikační přihlášení se nevytvoří a uživatel zůstane jen s Windows identitou. V logu se objeví záznam „Transformation is neded, but it has not been done“.</div>

### Opravené nedostatky (říjen 2026)

- <div role="presentation">Přepnutí repozitáře při přihlášení (`ClaimsTransformation`): kvůli chybějícím složeným závorkám se uživatel považoval za úspěšně přepnutého, i když nebyl členem žádné skupiny repozitáře. Neoprávněný uživatel se proto neodhlásil. Zároveň se kontrolovala jen první skupina každého repozitáře. Oprava: přepnutí proběhne jen při skutečném členství a na odhlášení se čeká, než se dokončí.</div>
- <div role="presentation">Volba `OnlyActiveDirectoryGroups` (`UserActiveDirectoryManager`): podmínka zjišťovala jen to, jestli existuje nějaké mapování AD skupin, ne jestli je v nich uživatel. Do DB se tak zakládal kterýkoli doménový účet. Oprava: uživatel se přeskočí, pokud není členem žádné namapované AD skupiny.</div>

- - - - - -

<div id="bkmrk-v-ru%C4%8Dn%C3%ADm-ldap-p%C5%99ihl%C3%A1">V ručním LDAP přihlášení (`AccountController`) zůstává jedna drobnost: po nalezení skupiny se pokračuje v procházení dalších repozitářů. Uživatel se tak může přepnout víckrát a platí poslední vhodný repozitář místo prvního. </div>