Token Broker — automatické prihlásenie
Token Broker je model pre doplnky, ktoré bežia priamo vnútri KROS platformy: používateľ klikne raz v obchode doplnkov a je automaticky prihlásený vo vašom doplnku, jeho firmy sa prepoja a doplnok dostane access token na KROS OpenAPI. Ide o server-to-server protokol s podpísaným JWT, jednorazovým launch code a zdieľaným API kľúčom — nie o samoobslužný model, ktorý by ste si mohli nasadiť sami.
Vyžaduje dohodu s KROSom
Token Broker nie je samoobslužný model — aby ste doplnok mohli zaradiť do obchodu doplnkov a napojiť ho na tento protokol, potrebujete dohodu s KROSom (pridelenie pluginId, API kľúča a JWKS URL prebieha mimo tejto dokumentácie). Ozvite sa na integracie@kros.sk.
Čo to rieši
V obchode doplnkov v KROS aplikácii klikne používateľ na jedno tlačidlo a tromi vecami naraz: je automaticky prihlásený vo vašom doplnku bez zadávania hesla, jeho firma (alebo firmy) v KROSe sa prepoja s doplnkom, a doplnok dostane access token na KROS OpenAPI, ktorým môže volať KROS v mene tejto firmy.
Prehliadač používateľa nikdy nevidí tento access token na KROS OpenAPI — prenáša sa výhradne server-to-server, medzi KROS Gatewayom a vaším doplnkom. Prehliadač nesie iba jednorazový, krátko platný code, ktorým sa na konci toku vytvorí prihlásená relácia.
Roly a hranice
KROS vlastní celý front-end tok a podpisovanie tokenov. Vy implementujete iba stranu doplnku — tri HTTP endpointy.
| Komponent | Vlastník | Zodpovednosť |
|---|---|---|
| KROS Frontend | KROS | tlačidlo v obchode doplnkov, zavolá launch, spracuje presmerovanie |
| KROS Gateway + Token Broker | KROS | podpis RS256 JWT, JWKS endpoint, orchestrácia výmeny tokenov, rate limiting |
| Access token provider | KROS | vydá access token na KROS OpenAPI pre dvojicu (firma, doplnok) |
| Váš doplnok | Partner | tri HTTP endpointy (token-exchange, token-delivery, callback); overí API kľúč a podpis JWT; založí alebo prihlási používateľa; bezpečne uloží access token |
| KROS OpenAPI | KROS | dátové API, ktoré doplnok volá získaným access tokenom |
Celý tok
Kompletná sekvencia od kliknutia až po prihlásenú reláciu vo vašom doplnku:
sub, plugin_id a tenant_ids; 2) zavolá POST /api/auth/token-exchange na vašom doplnku s hlavičkou X-Plugin-Api-Key a telom { token }; 3) doplnok overí API kľúč konštantným časom; 4) overí podpis JWT cez JWKS (len RS256); 5) vygeneruje jednorazový launch code (64 znakov, TTL 30 s) a vráti { launchCode, requestAccessToken }; 6) ak requestAccessToken je true, Gateway zavolá POST /api/auth/token-delivery; 7) doplnok bezpečne uloží accessToken pre každú firmu a vráti 200 OK; 8) Gateway presmeruje prehliadač (302) na {BaseUrl}/auth/callback?code=…; 9) prehliadač zavolá GET /auth/callback?code=… priamo na doplnku; 10) doplnok overí a atomicky skonzumuje code (ochrana proti opakovanému použitiu); 11) vytvorí cookie reláciu; 12) odpovie Set-Cookie a presmeruje na dashboard doplnku.Endpointy, ktoré implementujete
Tieto tri cesty sú fixné konštanty protokolu, nie sú konfigurovateľné. KROS ich skladá ako {BaseUrl}/api/auth/token-exchange, {BaseUrl}/api/auth/token-delivery a {BaseUrl}/auth/callback, kde BaseUrl je HTTPS adresa vášho doplnku dohodnutá s KROSom.
| Metóda | Cesta | Auth | Popis |
|---|---|---|---|
| POST | /api/auth/token-exchange |
X-Plugin-Api-Key |
prijme JWT, vráti launch code |
| POST | /api/auth/token-delivery |
X-Plugin-Api-Key |
prijme access token(y) |
| GET | /auth/callback?code=… |
anonymné (presmerovanie prehliadača) | overí code, vytvorí reláciu |
POST /api/auth/token-exchange
X-Plugin-Api-Key: VLOZ_SEM_API_KEY
Content-Type: application/json
{ "token": "<RS256 JWT>" }
Identita používateľa a firmy nie sú samostatné polia tela požiadavky — sú to claimy v samotnom JWT (nižšie).
- Overte
X-Plugin-Api-Keyporovnaním s konštantným časom — inak401. - Overte JWT: podpis cez JWKS,
iss,aud,exp, algoritmus obmedzený len na RS256,plugin_idzodpovedá vášmu — inak401. - Prečítajte
subatenant_ids. - Vygenerujte jednorazový launch code (64 znakov, TTL 30 s) a uložte ho spolu s
(userId, tenantIds, pluginId). - Rozhodnite, či potrebujete access token (
requestAccessToken) — typickytrue, ak ho pre danú firmu ešte nemáte.
{ "launchCode": "<64-znakový kód>", "requestAccessToken": true }
400 = chýba token. 401 = zlý API kľúč alebo neplatný podpis JWT.
JWT claimy
| Claim | Hodnota | Poznámka |
|---|---|---|
iss |
plugin-broker |
presná fixná hodnota |
aud |
plugin |
presná fixná hodnota |
sub |
ID používateľa | jedna varianta gateway posiela e-mail, druhá posiela numerické ID — pozri Dve varianty gateway |
plugin_id |
napr. fiskalpro |
musí sa zhodovať s vaším prideleným pluginId |
tenant_ids |
JSON pole stringov, napr. ["123456","789012"] |
firmy, pre ktoré launch nesie oprávnenie; [] = iba prihlásenie bez tenantov |
jti |
GUID | unikátne ID tokenu |
iat, nbf, exp |
čas | platnosť 15 minút (default); povolený clock skew 30 s |
Algoritmus obmedzte výhradne na RS256
JWT knižnice bežne dovolia overiť podpis podľa algoritmu, ktorý si token sám deklaruje v hlavičke — to je klasická zraniteľnosť JWT (útočník si nastaví alg na niečo slabšie alebo na none). Pri validácii tokenu z Token Brokera preto explicitne obmedzte prijímaný algoritmus na RS256 a nikdy nedôverujte hodnote alg z hlavičky prichádzajúceho tokenu.
tenant_ids — pole, plurál
Claim sa volá tenant_ids a je to JSON pole stringov. Singulárny tenant_id v protokole neexistuje. Zámena za singulár je zdokumentovaný zdroj chýb u partnerov — kód, ktorý číta tenant_id, dostane undefined a launch pre viacero firiem potichu prestane fungovať.
POST /api/auth/token-delivery
Zavolá sa iba ak ste v odpovedi na token-exchange vrátili requestAccessToken: true.
X-Plugin-Api-Key: VLOZ_SEM_API_KEY
Content-Type: application/json
{
"userId": "user@example.com",
"tokens": [
{ "tenantId": "123456", "name": "Moja Firma s.r.o.", "accessToken": "<opaque-token>" },
{ "tenantId": "789012", "name": "Druhá Firma a.s.", "accessToken": "<opaque-token>" }
],
"pluginId": "fiskalpro"
}
- Overte
X-Plugin-Api-Key. - Overte, že
pluginIdzodpovedá vášmu — inak400. - Prázdne pole
tokens→ vráťte200ako no-op. - Pre každý záznam bezpečne uložte
accessTokenpod kľúčom(userId, tenantId, pluginId); záznamy s prázdnymtenantIdaleboaccessTokenpreskočte. - Vráťte
200.
accessToken je nepriehľadný secret
accessToken slúži na volanie KROS OpenAPI v mene danej firmy a je to opaque secret — nikdy ho nelogujte a nikdy ho nevystavujte do prehliadača. Ukladajte ho rovnako bezpečne, ako by ste ukladali heslo alebo API kľúč.
GET /auth/callback?code=…
Sem KROS na konci launchu presmeruje prehliadač používateľa.
- Overte a atomicky skonzumujte
code— je single-use, to je jeho jediná ochrana proti replay útoku. Neplatný, expirovaný alebo už použitý kód →400. - Z uloženého záznamu (
userId,tenantIds,pluginId) vytvorte reláciu (napr. prihlásením s cookie). - Presmerujte na hlavnú obrazovku doplnku (
302).
Bezpečnosť
- Konštantný čas pri porovnaní API kľúča. Bežné porovnanie reťazcov (
==) sa spravidla zastaví na prvom nezhodnom znaku, čím cez čas odpovede prezradí kľúč po jednotlivých bajtoch. Použite funkciu na porovnanie s konštantným časom vo vašom jazyku (napr.CryptographicOperations.FixedTimeEqualsv .NET,crypto.timingSafeEqualv Node.js,hmac.compare_digestv Pythone). - RS256-only validácia JWT cez JWKS, s rotáciou kľúča podľa
kid— presne preto existuje JWKS endpoint namiesto natvrdo zadaného verejného kľúča. - Launch code: kryptograficky náhodný, 64 znakov, single-use, TTL 30 s. Pri distribuovanom nasadení (viac inštancií doplnku) použite úložisko s atomickým „získaj a zmaž" (napr. Redis), aby dve inštancie nemohli ten istý kód skonzumovať dvakrát súčasne.
- HTTPS všade — v produkcii povinné, HTTP iba lokálne pri vývoji.
- Rate limiting na oboch auth endpointoch — presné limity pre tento povrch nemáme potvrdené, pozri poznámku v Chyby a limity.
- Žiadne tajomstvá do logov — access tokeny, telá JWT ani API kľúč sa nelogujú. Chybové hlášky smerom von držte generické, detaily len na strane servera.
Čo dodá KROS a čo dodáte vy
KROS vám dodá:
| Údaj | Príklad |
|---|---|
pluginId | fiskalpro |
| JWKS URL | https://api-esw.kros.sk/plugins/.well-known/jwks.json |
API kľúč (X-Plugin-Api-Key) | VLOZ_SEM_API_KEY — doručí sa bezpečným kanálom, nikdy e-mailom v čistom texte |
Očakávané iss / aud | plugin-broker / plugin (fixné) |
| Base URL KROS OpenAPI a spôsob autentifikácie access tokenom | dodá KROS pri onboardingu |
| Prostredia | test/staging/produkčné hostname |
Vy dodáte KROS:
| Pole | Príklad | Popis |
|---|---|---|
| Name | FiskalPro | zobrazovaný názov doplnku |
| Description | Elektronická fakturácia | krátky popis |
| BaseUrl | https://fiskalpro.example.com | HTTPS base URL doplnku |
| ApiKey | VLOZ_SEM_API_KEY | hodnota pre hlavičku X-Plugin-Api-Key |
| TokenExchangeTimeoutSeconds | 10 | 1–300 |
| TokenDeliveryTimeoutSeconds | 10 | 1–300 |
Chybové stavy
| Situácia | Kto | HTTP | Dôsledok |
|---|---|---|---|
| Doplnok nie je na strane KROS zaregistrovaný | KROS Gateway | 404 | launch zlyhá |
| Podpisovací kľúč nie je nakonfigurovaný | KROS Gateway | 503 | launch zlyhá |
| Nepovolený tenant v launch požiadavke | KROS Gateway | 403 | launch zlyhá |
Timeout na token-exchange | KROS Gateway | 504 | launch zlyhá |
Transportná/JSON chyba alebo prázdny launchCode z token-exchange | KROS Gateway | 502 | launch zlyhá |
token-delivery zlyhalo | KROS Gateway | 502 | launch zlyhá (ak bol access token vyžiadaný) |
Zlý X-Plugin-Api-Key | váš doplnok | 401 | launch zlyhá |
Neplatný podpis JWT alebo nezhoda plugin_id | váš doplnok | 401 | launch zlyhá |
Neplatný, expirovaný alebo už použitý code | váš doplnok | 400 | callback zlyhá |
| Rate limit | oba | 429 | požiadavka odmietnutá |
Ak provider vráti pre všetky firmy prázdne tokeny, token-delivery sa preskočí a launch napriek tomu pokračuje — používateľ sa prihlási bez aktívneho pripojenia na KROS OpenAPI. Váš doplnok musí tento stav zvládnuť gracefully, nie ho vyhodnotiť ako chybu launchu.
Implementačný checklist
Dve varianty gateway
Protokol, ktorý doplnok implementuje, je identický bez ohľadu na to, ktorá KROS gateway launch spúšťa — líšia sa len tým, akú hodnotu nesie claim sub, a tým, ako presne používateľ launch spustil:
- Jedna varianta je produkčné zapojenie do KROS Fakturácie:
subnesie e-mail používateľa, tenanti sú firmy s príslušnou licenciou a access token zodpovedá licenčnému oprávneniu na KROS OpenAPI danej firmy. - Druhá varianta je samostatná (štandalón) brána s vlastným prihlásením:
subnesie numerické ID z tohto prihlásenia.
Váš doplnok sa nemusí starať, ktorá z nich launch spustila — vidí vždy len token-exchange, token-delivery, callback a JWKS endpoint, so zhodným tvarom požiadaviek a odpovedí.
Nie ste v .NET?
Protokol je zámerne jazykovo nezávislý — je postavený na JSON, JWT a JWKS, teda na formátoch a štandardoch, ktoré má knižnicu takmer každý ekosystém. Ak váš doplnok nie je v .NET, nepotrebujete žiadnu konkrétnu knižnicu ani balík — implementujte priamo tri kontrakty popísané vyššie (token-exchange, token-delivery, callback) pomocou bežnej JWT knižnice vo vašom jazyku, ktorá vie overiť RS256 podpis cez JWKS.