Bezpečnost¶
Azure AD přihlášení¶
Eva.Manager podporuje přihlašování přes Microsoft Azure AD (Entra ID) pomocí OpenID Connect.
Konfigurace¶
"Authentication": {
"Provider": "AzureAd",
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "váš-tenant-id",
"ClientId": "váš-client-id",
"ClientSecret": "${AZURE_AD_CLIENT_SECRET}",
"CallbackPath": "/signin-oidc"
}
}
Registrace aplikace v Azure¶
- Azure Portal → Entra ID → App registrations → New registration
- Název:
EVA Manager - Redirect URI:
https://vasedomena.cz/signin-oidc - Vytvořte Client secret (platnost max. 24 měsíců) → uložte do secrets
Client Secret
Client Secret nikdy neukládejte do appsettings.json v gitu. Používejte proměnnou prostředí AZURE_AD_CLIENT_SECRET.
Viz doc/AzureAD.md pro detailní postup.
JWT konfigurace (API)¶
"Jwt": {
"Issuer": "Eva.Mobile.WebApi",
"Audience": "Eva.Mobile",
"SecretKey": "MinimálněDvacetDvaZnaků!",
"TokenExpirationHours": 8
}
Produkce
SecretKeymusí být nastaven přes proměnnou prostředíJWT_SECRET_KEY- Minimální délka: 32 znaků
- Nikdy nepoužívat výchozí/testovací klíč v produkci
Device Token / QR přihlášení¶
Od v1.0.43 podporují Eva.Mobile.Pwa i Eva.Mobile (MAUI) dlouhodobé přihlášení zařízení bez opakovaného zadávání hesla:
- Přihlášený uživatel si v Eva.Manager na stránce
/securityotevře QR popup (DeviceQrPopup.razor) → volá sePOST /api/device-auth/generate-code, kód platí 10 minut. - Zařízení (PWA kamera/HID skener, nebo MAUI skener) naskenuje kód
EVA-DEV:{code}a zavoláPOST /api/device-auth/activate→ obdrží dlouhodobýDeviceToken(výchozí platnost 90 dní,DeviceToken:ExpirationDays). - Při každém spuštění aplikace se
DeviceTokenvymění za krátkodobý JWT přesPOST /api/device-auth/exchange.
Admin přehled a odvolání tokenů¶
Stránka /security v Eva.Manager zobrazuje grid všech aktivních device tokenů v rámci tenanta (DeviceTokenDataService.GetAllActiveTokensWithUserAsync), včetně e-mailu a jména uživatele a názvu zařízení. Administrátor může kterýkoli token okamžitě odvolat tlačítkem „Odvolat" (AdminRevokeTokenAsync — nastaví RevokedAt, bez načtení entity do paměti). Odvolání respektuje tenant guard — nelze odvolat token jiného tenanta.
Po odvolání vrátí POST /api/device-auth/exchange 401 Unauthorized a klient smaže lokálně uložený token.
Multitenancy — produkční aktivace¶
Od v1.0.43 je v produkčním appsettings.json (Eva.Mobile.WebApi) nastaveno "Multitenancy": { "Enabled": true } — EF Core globální query filtr je aktivní pro všechny ITenantAware entity. Viz Konfigurace — Multitenancy a checklist v CLAUDE.md (sekce „Bezpečnost dat — Tenant sandbox") pro kontrolu při každé nové datové operaci.
Před nasazením
Pokud je Multitenancy.Enabled = false (nebo chybí), globální query filtr se neaplikuje a data všech tenantů jsou viditelná všem uživatelům. U SaaS nasazení vždy ověřte Enabled: true ve WebApi appsettings.
Správa secrets v produkci¶
Doporučený postup¶
| Secret | Způsob uložení |
|---|---|
| DB heslo | Docker .env soubor (mimo git) nebo Docker Secrets |
| JWT Secret | Env proměnná nebo Docker Secrets |
| Azure AD Client Secret | Env proměnná nebo Azure Key Vault |
| DevExpress licence | Env proměnná |
| SMTP heslo | Env proměnná |
Docker Secrets (produkční alternativa)¶
# compose.yml
secrets:
db_password:
file: ./secrets/db_password.txt
services:
api:
secrets:
- db_password
Řízení přístupu — role a menu¶
Blokace eskalace na roli SuperAdmin¶
Uživatel s rolí Admin nemůže přiřadit sobě ani jinému uživateli roli SuperAdmin. Ochrana je dvouvrstvá:
| Vrstva | Popis |
|---|---|
| UI filtr | Role SuperAdmin se nezobrazí v seznamu rolí na stránce /account/manage, pokud přihlášený uživatel sám není SuperAdmin |
| Server-side guard | UpdateAccount() odmítne přiřazení SuperAdmin role s chybovou hláškou, pokud volající není SuperAdmin |
// Server-side guard v EditAccount.razor
if (rolesToAdd.Contains("SuperAdmin") && !_callerIsSuperAdmin)
{
toastMessageService.ShowErrorMessage("Roli SuperAdmin může přiřadit pouze SuperAdmin.");
return;
}
Filtrování menu dle role¶
NavMenu.razor obsahuje metodu FilterMenuByRole(), která upravuje viditelné položky menu dle přihlášené role:
| Role | Viditelné sekce |
|---|---|
| SuperAdmin | Domů, Správa systému (Správa tenantů, Správa licencí, Správa uživatelů, Export/Import dat, SysInfo, Monitoring) |
| Admin / TenantAdmin / ostatní | Celé menu kromě sekce Správa systému |
SuperAdmin tak nemá přístup k evidenci majetku, inventurám ani přesunům — jeho role je čistě systémová.
Auditní záznamy¶
Změny dat majetku jsou zaznamenávány v auditní tabulce:
- Kdo provedl změnu (CreatedBy, ModifiedBy)
- Kdy (CreatedDT, ModifiedDT)
- Přístup přes /articles/audit v Eva.Manager
SQL Injection — ochrana¶
Všechna volání stored procedures jsou parametrizována přes ExecuteSqlInterpolatedAsync():
// Bezpečné — EF Core automaticky parametrizuje
await db.Database.ExecuteSqlInterpolatedAsync(
$"CALL dbo.\"sg_CreateInventoryItems\" ({inventoryId}, {locationId})");
Dapper dotazy používají anonymní parametrové objekty (nikoli string interpolaci).
Citlivé soubory — co necommitovat¶
# Vývojová konfigurace s hesly
src/Eva.Manager/appsettings.Development.json
src/Eva.Mobile.WebApi/appsettings.Development.json
# Certifikáty a klíče
*.pfx
*.key
*.pem
# Claude Code nastavení
.claude/settings.local.json
Warning
Pokud byl secret již commitnut, nestačí ho smazat — zůstane v historii. Je nutné provést git filter-repo a okamžitě rotovat kompromitovaný secret.