Tmavý režim
JWT Provideři
Konfigurace
JWT provideři se konfigurují v config/default.yaml (nebo production.yaml) pod klíčem token.jwt:
yaml
token:
keyRefreshIntervalMinutes: 60 # Interval refreshe JWKS klíčů
jwt:
- provider: zitadel
baseUrl: http://zitadel:8080
jwk: /oauth/v2/keys
issuer: http://localhost:8080
hostOverride: localhost # Volitelné: přepíše host při fetch klíčů
- provider: amotion
baseUrl: https://auth-dev.am-space.cz
jwk: /oauth/keys
- provider: amotion-dev
baseUrl: https://atrea-auth.uxf.dev
jwk: /oauth/keysGoogle / Microsoft přihlášení
Google a Microsoft nejsou samostatní JWT provideři. Federovaný login přes tyto účty se konfiguruje uvnitř Zitadelu jako externí Identity Provider (IdP). Token, který nakonec dorazí na API, vždy podepisuje Zitadel.
Zitadel (primární provider)
Zitadel je self-hosted OIDC provider, který zajišťuje primární autentizaci pro všechny Atrea aplikace.
Speciální claims
Zitadel přidává do JWT tokenu navíc dynamické claims, kde je část identifikátoru zakódovaná přímo v názvu klíče:
| Vzor claimu | Popis |
|---|---|
urn:zitadel:iam:org:id:{orgId} | ID organizace uživatele — z názvu klíče se extrahuje {orgId} |
urn:zitadel:iam:org:project:{projectId}:roles | Role uživatele v daném Zitadel projektu |
Extrakce se provádí regexem v JWTService — orgId i projectId nejsou hodnoty, ale součást názvu claimu.
Organizace
Při přihlášení přes Zitadel je z tokenu extrahováno orgId. To umožňuje mapování Zitadel organizací na aplikace v Atrea User API (viz config.zitadel.orgToApp).
Login flow (PKCE)
Dev-only endpoint
Endpointy /api/zitadel/login a /api/zitadel/callback jsou určené pro lokální vývoj a testování. Callback vrací tokeny jako JSON odpověď (nikoliv redirect na frontend). V produkci provádí OIDC flow přímo frontend aplikace přes Zitadel.
1. GET /api/zitadel/login?client_id=<clientId>
→ Redirect na Zitadel login stránku (s PKCE)
2. Uživatel se přihlásí v Zitadel
3. GET /api/zitadel/callback?code=<authCode>&state=<state>
→ Výměna auth code za tokeny
→ JSON response: { access_token, id_token, id_token_claims, ... }Webhoky
Zitadel posílá webhooky při událostech uživatele:
| Událost | Akce v API |
|---|---|
user.created | Vytvoří uživatele v DB (pokud neexistuje) |
user.deactivated | Deaktivuje uživatele (active = false) |
user.reactivated | Aktivuje uživatele (active = true) |
user.removed | Deaktivuje uživatele (active = false) — záznam se zachovává pro audit trail |
Webhook endpoint: POST /api/zitadel/webhook
Autentizace: X-Webhook-Secret header
Tělo webhooku
json
{
"eventType": "user.created",
"orgId": "org_abc123",
"user": {
"email": "novy.uzivatel@firma.cz",
"firstName": "Jan",
"lastName": "Novák"
}
}Amotion
Alternativní OAuth2/OIDC server. JWKS endpoint je /oauth/keys. Email se extrahuje z claimu email nebo preferred_username.
V default.yaml jsou dvě varianty: amotion (produkční auth-dev.am-space.cz) a amotion-dev (atrea-auth.uxf.dev) — obě validují tokeny stejným způsobem, liší se pouze JWKS URL.
Google / Microsoft (federovaní přes Zitadel)
Login přes Google nebo Microsoft není konfigurován v Atrea User API. Tito poskytovatelé jsou nastaveni jako externí Identity Provideři uvnitř Zitadelu (Console → Default Settings → Identity Providers). Při přihlášení:
- Uživatel klikne v Zitadel login UI na "Sign in with Google/Microsoft"
- Zitadel provede OAuth flow proti Google/Microsoftu
- Zitadel vytvoří/aktualizuje lokálního uživatele a vydá vlastní JWT
- API přijme Zitadel JWT a verifikuje ho proti Zitadel JWKS
Z pohledu API tedy existuje vždy jediný provider — Zitadel. upn claim zůstává v emailové extrakci pro případy, kdy Zitadel propaguje původní Microsoft UPN do tokenu.
Jak probíhá verifikace
typescript
// JWTService — zjednodušeně
async verifyToken(token: string): Promise<DecodedToken> {
for (const provider of this.providers) {
try {
const decoded = jwt.verify(token, provider.keys, {
algorithms: ['RS256', 'RS384', 'RS512'],
issuer: provider.issuer,
});
return { ...decoded, provider: provider.name };
} catch {
// Zkusí další provider
}
}
throw new ApiException(401, 'Invalid token');
}Tokenem projdou všichni provideři v pořadí konfigurace. První úspěšná verifikace vyhrává.
Přidání nového providera
- Přidejte konfiguraci do
config/default.yaml:
yaml
token:
jwt:
- provider: muj-provider
baseUrl: https://auth.moje-firma.cz
jwk: /oauth/keys
issuer: https://auth.moje-firma.czUjistěte se, že provider vydává JWT s
emailclaimem nebo jiným, ze kterého lze email extrahovat.Restartujte API — klíče se načtou při startu.
Troubleshooting
Token is invalid
- Ověřte, že
issuerv konfiguraci odpovídáissclaimu v tokenu - Ověřte, že JWKS endpoint je dostupný ze serveru
- Zkontrolujte expiraci tokenu (
expclaim)
JWKS fetch failed
- Zkontrolujte dostupnost
baseUrl + jwkendpointu - Pro Zitadel v Dockeru: ujistěte se, že
zitadelhostname je resolvovatelný - Použijte
hostOverridepokud se liší interní a externí hostname
Email extraction failed
- Zkontrolujte, které claims váš provider vydává
- Přidejte logiku extrakce do
JWTService.extractEmail()pokud používáte nestandartní claim