NET Genium podporuje přihlašování uživatelů pomocí účtů spravovaných v Microsoft Entra ID (dříve Azure Active Directory). Pro využití této funkcionality je nutné provést ruční konfiguraci v prostředí Microsoft Entra ID.
Konfigurace se skládá ze dvou částí, které na sebe navazují — autorizace vyžaduje autentizaci, obráceně to neplatí.
Autentizace (kapitoly 1 a 2) ověří, kdo uživatel je, a přihlásí ho do NET Genia. Sama o sobě žádné účty nezakládá ani nemění: uživatel musí být v NET Geniu založen předem a oprávnění má nastavená ručně.
Autorizace (kapitola 3) navíc při každém přihlášení převezme z MS Entra role uživatele a podle nich mu v NET Geniu nastaví skupinu oprávnění a uživatelské skupiny. Volitelně umí uživatele podle jeho role také založit při prvním přihlášení (kapitola 3.5) — účty pak nemusí zakládat administrátor ručně a vznikají podle rolí přidělených v MS Entra.
1. Konfigurace Microsoft Entra ID
- Registrace aplikace „NET Genium“ na webové stránce https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps
- česky: portal.azure.com / Registrace aplikací
- anglicky: portal.azure.com / App registrations
- NET Genium jako název aplikace
- Zjištění ID aplikace (klienta), který je automaticky vytvořen při registraci aplikace
- česky: ID aplikace (klienta)
- anglicky: Application (client) ID
- Nastavení URL NET Genia na hodnotu „https://{url_netgenia}/LoginByMicrosoft.aspx“
- česky: portal.azure.com / Registrace aplikací / NET Genium / Ověřování / Identifikátory URI pro přesměrování
- anglicky: portal.azure.com / App registrations / NET Genium / Authentication / Redirect URIs
- Povolení přístupových tokenů
- česky: portal.azure.com / Registrace aplikací / NET Genium / Ověřování / Implicitní udělení a hybridní toky / Přístupové tokeny (používané pro implicitní toky)
- anglicky: portal.azure.com / App registrations / NET Genium / Authentication / Implicit grant and hybrid flows / Access tokens (used for implicit flows)
- Povolení ID tokenů
- česky: portal.azure.com / Registrace aplikací / NET Genium / Ověřování / Implicitní udělení a hybridní toky / Tokeny ID (používané pro implicitní a hybridní toky)
- anglicky: portal.azure.com / App registrations / NET Genium / Authentication / Implicit grant and hybrid flows / ID tokens (used for implicit and hybrid flows)
- Vytvoření tajného kódu klienta
- česky: portal.azure.com / Registrace aplikací / NET Genium / Certifikáty a tajné kódy / Nový tajný kód klienta
- anglicky: portal.azure.com / App registrations / NET Genium / Certificates & secrets / New client secret
- Nastavení oprávnění API pro Microsoft Graph
- česky: portal.azure.com / Registrace aplikací / NET Genium / Oprávnění rozhraní API / Přidat oprávnění / Microsoft Graph
- anglicky: portal.azure.com / App registrations / NET Genium / API permissions / Add a permission / Microsoft Graph
- Název rozhraní API „Microsoft Graph – User.Read“, typ „Delegováno“
- Pro samotné přihlášení uživatelů toto oprávnění stačí; převzetí rolí z MS Entra popisuje kapitola 3

2. Konfigurace NET Genia
- Vytvoření konfiguračního souboru „NETGenium\Config\MicrosoftOAuth.json“
- Obsah souboru nastavit na: „{"web":{"client_id":" ID aplikace (klienta) ","auth_uri":"https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize","token_uri":"https://login.microsoftonline.com/organizations/oauth2/v2.0/token","client_secret":"tajný kód klienta"}}“
- Vytvoření prázdného souboru „NETGenium\Config\LoginByMicrosoft.txt“
- Jeho existence zapíná volbu přihlášení přes Microsoft na přihlašovací stránce; bez něj se přihlašovací tlačítko nenabídne, i když je konfigurační soubor „MicrosoftOAuth.json“ vyplněný
- Obsah souboru může nést nepovinné parametry autorizace, viz kapitola 3.5
3. Autorizace — převzetí rolí z MS Entra
Vyhodnocení rolí není součástí NET Genia. NET Genium při každém přihlášení zavolá externí funkci „NETGenium.OnBeforeLogin“ a vlastní práci s rolemi nechá na ní:
- NET Genia postavená na produktu ERP mají hotovou implementaci k dispozici v knihovně „ERP.dll“ — stačí ji zapojit do projektu „ngef“ (kapitola 3.4) a nastavit skupiny oprávnění (kapitola 3.3).
- Ostatní NET Genia si autorizaci implementují sama. Klíčové pasáže ze zdrojových kódů knihovny ERP, ze kterých lze vyjít, jsou v kapitole 3.6.
Aby se autorizace vůbec provedla, musí platit současně všechny tyto předpoklady:
- V souboru „ngef.cs“ projektu „ngef“ je zaregistrovaná externí funkce „NETGenium.OnBeforeLogin“ (kapitola 3.4)
- U NET Genií postavených na produktu ERP je v adresáři „NETGenium\bin“ vedle knihovny „ngef.dll“ také knihovna „ERP.dll“
- Je vytvořen konfigurační soubor „NETGenium\Config\LoginByMicrosoft.txt“ (kapitola 2)
- Editační formulář „Skupina oprávnění“ má ovládací prvek „ng_memberof“ a editační formulář „Uživatel“ ovládací prvek „ng_originalnirole“ (kapitola 3.3)
- Alespoň jedna skupina oprávnění má vyplněné pole „Member of“ (kapitola 3.3)
- Uživatel je v NET Geniu založen, nebo je zapnuté automatické zakládání uživatelů (kapitola 3.5)
Nesplnění prvního předpokladu se pozná jedině tím, že se u uživatele po přihlášení nic nezmění. NET Genium volá externí funkci při každém přihlášení, ale její návratovou hodnotu nevyhodnocuje — chybějící registrace proto neskončí chybou ani záznamem v logu.
3.1. Jak autorizace probíhá
Po úspěšném ověření uživatele u Microsoftu a ještě před samotným přihlášením do NET Genia zavolá NET Genium externí funkci „NETGenium.OnBeforeLogin“ a předá jí e-mail uživatele přijatý v tokenu. Implementace v knihovně ERP:
- Načte skupiny oprávnění, které mají vyplněné pole „Member of“ (sloupec „ng_memberof“ tabulky „srightsgroups“). Nemá-li ho vyplněné ani jedna skupina oprávnění, autorizace se neprovede a oprávnění zůstávají nastavená ručně v NET Geniu.
- Z tokenu přijatého od Microsoftu vezme role uživatele — položky „roles“ (aplikační role) a „GroupsName“.
- Pouze tehdy, není-li v tokenu žádná role, zeptá se na skupiny uživatele služby Microsoft Graph na adrese „https://graph.microsoft.com/v1.0/me/transitiveMemberOf“ a použije zobrazované názvy vrácených skupin.
- Každou nalezenou roli porovná na přesnou shodu celého řetězce, včetně velikosti písmen, s polem „Member of“ každé skupiny oprávnění.
- Vyhledá uživatele podle e-mailu ve sloupci „email“ tabulky „susers“. Uživatele, který v NET Geniu neexistuje, založí pouze tehdy, je-li zapnuté automatické zakládání (kapitola 3.5); jinak přihlášení proběhne bez jakékoli změny.
- Nalezenému uživateli nastaví:
- Skupinu oprávnění — a to pouze tehdy, odpovídá-li rolím právě jedna skupina oprávnění. Neodpovídá-li žádná, nebo odpovídají-li dvě a více, skupina oprávnění se vyprázdní.
- Uživatelské skupiny — přepíše je uživatelskými skupinami všech odpovídajících skupin oprávnění.
- Originální role (sloupec „ng_originalnirole“ tabulky „susers“) — seznam rolí přijatých z MS Entra oddělený čárkami.
Nové nastavení se projeví vždy až při dalším přihlášení uživatele — změna role v MS Entra se do právě běžící relace nepromítne.
Upozornění: při přepisu uživatelských skupin se uživateli zároveň smažou jeho oblíbené položky a rozložení portletů na hlavní stránce. Ještě v průběhu téhož přihlášení pak NET Genium uživateli, který žádné oblíbené položky ani portlety nemá, převezme výchozí nastavení z účtu Administrator (uživatel s ID 1) — hlavní stránka tedy nezůstane prázdná, uživatel ale přijde o vlastní úpravy. Nenajde-li se pro uživatele žádná role, ztratí navíc všechny uživatelské skupiny i skupinu oprávnění. Autorizaci proto zkoušejte nejdříve na testovacím účtu.
3.2. Aplikační role v MS Entra
Doporučeným způsobem je použít aplikační role registrované aplikace NET Genium. Role se pak předá přímo v tokenu a NET Genium se službou Microsoft Graph vůbec nekomunikuje — není proto potřeba žádné další oprávnění nad rámec „Microsoft Graph – User.Read“ z kapitoly 1.
- Vytvoření aplikační role
- česky: portal.azure.com / Registrace aplikací / NET Genium / Role aplikace / Vytvořit roli aplikace
- anglicky: portal.azure.com / App registrations / NET Genium / App roles / Create app role
- Hodnota role (anglicky Value) je text, který se objeví v tokenu a který se porovnává s polem „Member of“ skupiny oprávnění v NET Geniu — nikoli zobrazovaný název role
- Povolené typy členů (anglicky Allowed member types) nastavit na „Uživatelé nebo skupiny“ (anglicky „Users/Groups“)
- Přiřazení uživatelů nebo skupin k roli
- česky: portal.azure.com / Podnikové aplikace / NET Genium / Uživatelé a skupiny
- anglicky: portal.azure.com / Enterprise applications / NET Genium / Users and groups
Alternativa, kterou nedoporučujeme — načtení skupin ze služby Microsoft Graph. Použije se automaticky tehdy, když v tokenu žádná role není, a vyžaduje:
- delegované oprávnění „GroupMember.Read.All“ (nebo „Directory.Read.All“) se souhlasem správce
- česky: portal.azure.com / Registrace aplikací / NET Genium / Oprávnění rozhraní API
- anglicky: portal.azure.com / App registrations / NET Genium / API permissions
- rozšíření rozsahu oprávnění v konfiguračním souboru „MicrosoftOAuth.json“ — do objektu „web“ se doplní položka „scope“, například „"scope":"openid email profile GroupMember.Read.All"“; není-li položka uvedena, použije NET Genium rozsah „openid email profile“
Nevýhodou této varianty je, že se porovnávají všechny skupiny, ve kterých je uživatel členem, včetně nepřímého členství — tedy typicky desítky skupin, které s aplikací nijak nesouvisejí. Aplikační role jsou naproti tomu vytvořené přímo pro tuto aplikaci.
3.3. Skupiny oprávnění v NET Geniu
- Do editačního formuláře „Skupina oprávnění“ doplnit textový ovládací prvek s identifikátorem „ng_memberof“ (například s názvem „Member of“)
- Do editačního formuláře „Uživatel“ doplnit textový ovládací prvek s identifikátorem „ng_originalnirole“ (například s názvem „Originální role“) — do něj se zapisují role přijaté z MS Entra
- U každé skupiny oprávnění, která má odpovídat některé roli z MS Entra, vyplnit do pole „Member of“ hodnotu aplikační role; u varianty se službou Microsoft Graph zobrazovaný název skupiny
- Skupinám oprávnění přiřadit uživatelské skupiny — právě ty se uživateli při přihlášení nastaví
Oba ovládací prvky musí existovat, jinak autorizace skončí chybou. Hodnota v poli „Member of“ musí souhlasit přesně, včetně velikosti písmen a mezer, a pole musí být dost dlouhé na to, aby se do něj celá hodnota role vešla.
3.4. Externí funkce NETGenium.OnBeforeLogin
NET Genia postavená na produktu ERP mají hotovou implementaci v knihovně „ERP.dll“ a zapojí ji takto:
- Do projektu „ngef“ přidat referenci na knihovnu „ERP.dll“
- Do souboru „ngef.cs“ zaregistrovat volání:
case "NETGenium.OnBeforeLogin": ERP.Login.OnBeforeLogin(args, conn); return "";
- Zkompilovanou knihovnu „ngef.dll“ i knihovnu „ERP.dll“ nahrát do adresáře „NETGenium\bin“ — nahrání nové knihovny automaticky restartuje webovou aplikaci
Bez této registrace autorizace neproběhne. Přihlášení se chová jako v kapitolách 1 a 2 a oprávnění uživatele se nezmění.
3.5. Automatické zakládání uživatelů
Ve výchozím stavu se uživatel, který v NET Geniu neexistuje, nezakládá — jeho přihlášení proběhne bez jakékoli změny a účet musí založit administrátor.
Zakládání se zapíná parametrem v konfiguračním souboru „NETGenium\Config\LoginByMicrosoft.txt“. Na samostatný řádek se zapíše:
CreateUsers
Soubor může obsahovat i více parametrů, vždy jeden na řádek; na velikosti písmen nezáleží a prázdné řádky se ignorují.
Je-li parametr zapnutý, založí se uživatel při prvním přihlášení, a to pouze tehdy, odpovídá-li některé jeho roli alespoň jedna skupina oprávnění. Bez této podmínky by účet v NET Geniu získal každý, kdo se dokáže přihlásit v tenantu MS Entra, i když mu tam nikdo žádnou roli nepřidělil.
Novému uživateli se vyplní:
- Celé jméno, Jméno a Příjmení — rozpadem položky „name“ z tokenu; není-li jméno dvouslovné, uloží se celé do pole „Příjmení“
- Přihlašovací jméno — odvozené z příjmení a prvního písmene jména; shoduje-li se s existujícím uživatelem, doplní se pořadové číslo
- Email — e-mail přijatý z MS Entra
- Skupina oprávnění, uživatelské skupiny a Originální role — podle rolí z MS Entra, stejně jako u existujícího uživatele
E-mail se záměrně nezkracuje. Je-li pole „Email“ v NET Geniu kratší než e-mail přijatý z MS Entra, skončí zakládání chybou zapsanou do logu (kapitola 3.8) — zkrácený e-mail by uživatele při příštím přihlášení nenašel a účet by vznikal znovu při každém přihlášení.
3.6. Vlastní implementace autorizace
NET Genia, která nejsou postavená na produktu ERP, knihovnu „ERP.dll“ k dispozici nemají a autorizaci si implementují sama — jako vlastní externí funkci zaregistrovanou pod klíčem „NETGenium.OnBeforeLogin“ způsobem popsaným v kapitole 3.4. Následující pasáže ze zdrojových kódů knihovny ERP slouží jako výchozí bod; předpokládají jmenné prostory „NETGenium“, „System.Collections.Generic“, „System.Data“ a „System.Security.Claims“.
Vstupní bod — načtení skupin oprávnění, vyhodnocení rolí z tokenu a zápis k uživateli:
public static void OnBeforeLogin(string[] args, DbConnection conn)
{
string loginby = args[0], s;
if (loginby.Length == 0 || conn.HttpContext.Session["microsoft_access_token"] == null)
{
return;
}
DataTable srightsgroups = Data.Get("SELECT id, ng_memberof FROM srightsgroups WHERE NOT ng_memberof = ''", conn);
if (srightsgroups.Rows.Count == 0)
{
return; // Žádná skupina oprávnění není namapovaná na roli - autorizace zůstává na NET Geniu
}
List<int> rightsgroups = new List<int>(), usergroups = new List<int>();
List<string> roles = new List<string>();
int rightsgroup = 0;
if (conn.HttpContext.Session[s = "microsoft_claims"] != null)
foreach (Claim claim in (Claim[])conn.HttpContext.Session[s])
if (claim.Type == "roles")
{
MatchGroups(s = claim.Value, rightsgroups, usergroups, srightsgroups, conn);
roles.Add(s);
}
if (rightsgroups.Count == 1)
{
rightsgroup = rightsgroups[0];
}
DbRow user = new DbRow("SELECT id, rightsgroup, ng_originalnirole FROM susers WHERE email = " + conn.Format(loginby), conn);
if (user.Read())
using (DbCommand cmd = new DbCommand(conn))
{
UpdateUser(user, usergroups, rightsgroup, string.Join(", ", roles.ToArray()), cmd, conn);
}
}
Porovnání role se skupinami oprávnění a dohledání jejich uživatelských skupin:
private static void MatchGroups(string memberOf, List<int> rightsgroups, List<int> usergroups, DataTable srightsgroups, DbConnection conn)
{
int n;
foreach (DataRow row in srightsgroups.Rows)
if (row["ng_memberof"].ToString() == memberOf)
{
if (!rightsgroups.Contains(n = (int)row["id"]))
{
rightsgroups.Add(n);
}
foreach (int usergroup in Data.GroupsInRightsGroup(n, conn))
if (!usergroups.Contains(usergroup))
{
usergroups.Add(usergroup);
}
}
}
Zápis skupiny oprávnění a uživatelských skupin k uživateli. Knihovna ERP maže spolu s uživatelskými skupinami i oblíbené položky a rozložení portletů daného uživatele:
private static void UpdateUser(DbRow user, List<int> usergroups, int rightsgroup, string memberOf, DbCommand cmd, DbConnection conn)
{
int userid = (int)user["id"];
if (Parser.ToInt32(user["rightsgroup"]) != rightsgroup || user["ng_originalnirole"].ToString() != memberOf)
{
DataSaverSynchro ds = new DataSaverSynchro("susers", userid, conn);
ds.Add("rightsgroup", rightsgroup);
ds.Add("ng_originalnirole", memberOf);
ds.Save(cmd);
}
if (memberOf == "" || Sql.Ids("SELECT groupid FROM susers_rights WHERE userid = " + userid + " ORDER BY id", conn) != Sql.Ids(usergroups.ToArray()))
{
foreach (string table in new string[] { "sfavorites", "sportlets", "susers_rights" })
{
cmd.CommandText = "DELETE FROM " + table + " WHERE userid = " + userid;
cmd.ExecuteNonQuery();
}
foreach (int usergroup in usergroups)
{
DataSaver ds = new DataSaver("susers_rights", 0, cmd);
ds.Add("userid", userid);
ds.Add("groupid", usergroup);
ds.Execute();
}
}
}
Knihovna ERP nad rámec těchto pasáží řeší ještě načtení skupin ze služby Microsoft Graph (kapitola 3.2), automatické zakládání uživatelů (kapitola 3.5), přihlašování přes Active Directory a zápis do logu (kapitola 3.8).
3.7. Otestování autorizace
- V MS Entra přiřadit testovacímu uživateli právě jednu aplikační roli.
- V NET Geniu ověřit, že existuje uživatel se stejným e-mailem a že některá skupina oprávnění má v poli „Member of“ hodnotu té role.
- Přihlásit se testovacím uživatelem přes Microsoft.
- V NET Geniu otevřít záznam uživatele (Nastavení / Uživatelé) a zkontrolovat: #* pole „Skupina oprávnění“ odpovídá roli z MS Entra #* pole „Originální role“ obsahuje hodnotu role přijaté z MS Entra #* uživatelské skupiny odpovídají uživatelským skupinám dané skupiny oprávnění
- Změnit uživateli roli v MS Entra, znovu se přihlásit a ověřit, že se nastavení v NET Geniu změnilo.
Zůstane-li pole „Originální role“ po přihlášení prázdné, nenašla se žádná role — postupovat podle kapitoly 3.8.
3.8. Ladění autorizace
- Zapnout logování „Na disk“ nebo „Do databáze a na disk“
- Vyzkoušet přihlášení
- Analyzovat obsah logového souboru „NETGenium\Logs\Anonymous\{yyyy-MM-dd}\loginbymicrosoft.log“ — do téhož souboru zapisuje jak přihlášení, tak vyhodnocení rolí
Co v logovém souboru hledat:
- Výpis položek tokenu ve tvaru „název: hodnota“. Každá aplikační role se vypíše jako samostatný řádek „roles: hodnota role“. Chybějí-li řádky „roles“, role se v tokenu vůbec nepřenesla — zkontrolovat v MS Entra, že je role uživateli přiřazena (Podnikové aplikace / NET Genium / Uživatelé a skupiny).
- Řádek „OnBeforeLogin: no role found, claim types in session“ — zapíše se pokaždé, když se nenašla žádná role, a vypíše, jaké typy položek token doopravdy obsahoval. Hodnota „none“ znamená, že z přihlášení nedorazily žádné položky.
- Řádky s adresou „https://graph.microsoft.com/v1.0/me/transitiveMemberOf“ a s odpovědí této služby — objeví se jen u varianty bez aplikačních rolí. Text „Uploader.UploadJSon(…) ERROR“ znamená, že volání selhalo, typicky kvůli chybějícímu oprávnění nebo souhlasu správce.
- Chyby samotné funkce se zapisují ve tvaru „OnBeforeLogin(e-mail)“ do denního logového souboru „NETGenium\Logs\{yyyy-MM-dd}.log“ na úrovni „Error“.
Nejčastější situace:
| Projev | Příčina |
| Role je v logu, ale uživatel nemá skupinu oprávnění | Pole „Member of“ neodpovídá přesně hodnotě role — překlep, jiná velikost písmen, mezera navíc, zobrazovaný název role místo její hodnoty, nebo příliš krátké pole „Member of“ |
| Uživatel má uživatelské skupiny, ale prázdnou skupinu oprávnění | Rolím uživatele odpovídají dvě a více skupin oprávnění; přiřadit uživateli jedinou roli |
| Role je v logu, ale u uživatele se nezměnilo nic | E-mail v tokenu neodpovídá poli „Email“ uživatele v NET Geniu, nebo v projektu není zaregistrována externí funkce „NETGenium.OnBeforeLogin“ (kapitola 3.4) |
| Uživatel se nezaložil, přestože je zapnutý parametr CreateUsers | Žádné jeho roli neodpovídá skupina oprávnění, nebo je pole „Email“ kratší než e-mail z MS Entra — pak je v denním logu chyba „OnBeforeLogin(e-mail)“ |
| Uživatel přišel o všechny uživatelské skupiny | Nenašla se žádná role — postupovat podle předchozích bodů této kapitoly |
| Nastavení uživatele se nemění a žádná skupina oprávnění nemá vyplněné pole „Member of“ | Autorizace je záměrně vypnutá a oprávnění zůstávají nastavená ručně v NET Geniu |
4. Postup při ladění chyb nebo v případě nefunkčního přihlašování
4.1. Obecné
- Zapnout logování „Na disk“ nebo „Do databáze a na disk“
- Vyzkoušet přihlášení
- Analyzovat obsah logového souboru „NETGenium\Logs\Anonymous\{yyyy-MM-dd}\loginbymicrosoft.log“
- Podle typu chyby popsané v logovém souboru „loginbymicrosoft.log“
- Změnit obsah konfiguračního souboru „MicrosoftOAuth.json“
- Změnit nastavení v Azure (typicky vypršení platnosti client_secret)
4.2. Response status code does not indicate success: 401 (Unauthorized)
- Vyhledat pokus o přihlášení v logovém souboru „Auth.log“ podle uživatelského účtu a data a času přihlášení.
- Pokud se v souboru „Auth.log“ záznam pokusu o přihlášení nenachází, nedošlo k úspěšné autentizaci uživatele na webových stránkách společnosti Microsoft. V takovém případě je nutné situaci řešit s firmou, která Microsoft Entra ID konfiguruje, aby s uživatelem krok po kroku proces přihlášení vyzkoušela.
- Pokud v souboru „Auth.log“ záznam pokusu o přihlášení existuje, postupovat podle chybového hlášení uvedeného v logu.
4.3. Sorry, but we're having trouble with signing you in
- Ověřit, že jsou v konfiguraci MS Entra zadány všechny varianty přesměrovacích endpointů (s www i bez www).
- Zkontrolovat přesnou shodu URL adres včetně velikosti písmen.
- Pokud se v souboru „Auth.log“ záznam pokusu o přihlášení nenachází, nedošlo k úspěšné autentizaci uživatele na webových stránkách společnosti Microsoft. V takovém případě je nutné situaci řešit s firmou, která Microsoft Entra ID konfiguruje, aby s uživatelem krok po kroku proces přihlášení vyzkoušela.