Keycloak autentizace
Keycloak autentizace
Section titled “Keycloak autentizace”Keycloak je OIDC identity provider platformy Sencai. Řeší registraci uživatelů, přihlašování, JWT tokeny, TOTP/2FA a SSO integrace.
Klíčové údaje
Section titled “Klíčové údaje”- Verze: Latest
- Realm:
sencai - Port: 8080 (pouze interní port kontejneru, bez vlastního externího host portu — dostupný výhradně přes Traefik
PathPrefix('/kc')na sdíleném web entrypointu) - Databáze: MySQL (keycloak-db:3307)
- URL (interní):
http://keycloak:8080/kc - Admin (lokálně, přes Traefik):
http://app.sencai.localhost/kc/admin(přihlašovací údaje: admin/admin)
Clients
Section titled “Clients”Keycloak má nakonfigurováno více clientů:
| Client ID | Typ | Účel | Grant Type |
|---|---|---|---|
sencai-frontend | Public | Nuxt/Vue frontend | authorization_code |
sencai-backend | Confidential | Strapi backend | client_credentials |
sencai-admin | Confidential | Admin UI | authorization_code |
admin-cli | Confidential | Admin API (master realm) | password |
JWT tokeny
Section titled “JWT tokeny”Životnost tokenu
Section titled “Životnost tokenu”- Access Token: 12 hodin (
KC_ACCESS_TOKEN_LIFESPAN=12h) na úrovni realmu. Samotný Nuxt frontend si ale vydává vlastní, kratší cookiesaccess_token/id_token(15 min) a 30denní cookierefresh_token(httpOnly) — viz níže. - Refresh Token: 30 dní (httpOnly cookie)
Refresh flow na frontendu
Section titled “Refresh flow na frontendu”Platformní frontend (sencai.space-frontend) obnovuje access token proaktivně, místo aby čekal na jeho expiraci:
- Nuxt plugin
auth-refresh-scheduler.client.tsdekóduje claimexpaktuálního access tokenu a naplánuje refresh 60 sekund před expirací. Plán se přeplánuje při každé změně tokenu (login, refresh, logout) a pozastaví se, dokud je karta prohlížeče skrytá. - Samotný refresh je v auth store řešen jako single-flight akce: souběžní volající sdílí jeden probíhající refresh, dočasné chyby se opakují a odhlášení (redirect na
/auth/loginssessionExpired=1) vyvolá pouze skutečná401z refresh endpointu. - Na straně serveru
POST /api/auth/refresh(Nuxt server route) přečte httpOnly cookierefresh_token, vymění ji u Keycloak token endpointu (grant_type=refresh_token) a z odpovědi znovu nastaví cookiesaccess_token,refresh_tokenaid_token.
Obsah access tokenu (RS256)
Section titled “Obsah access tokenu (RS256)”{ "sub": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "name": "John Doe", "family_name": "Doe", "given_name": "John", "email_verified": true, "preferred_username": "user@example.com", "iat": 1234567890, "exp": 1234571490, "iss": "http://keycloak:8080/kc/realms/sencai", "aud": "sencai-frontend", "typ": "Bearer"}Validace
Section titled “Validace”Strapi validuje token přes JWKS (JSON Web Key Set) endpoint:
http://keycloak:8080/kc/realms/sencai/.well-known/openid-configurationhttp://keycloak:8080/kc/realms/sencai/protocol/openid-connect/certsProvisioning uživatelů
Section titled “Provisioning uživatelů”Registrace (Strapi → KC)
Section titled “Registrace (Strapi → KC)”- Uživatel se zaregistruje přes formulář na frontendu
- Strapi
POST /api/registrations - Strapi webhook spustí:
POST webhook-publisher:1347 - Event:
{ eventName: 'registration.create', entity: registration, ... } - RabbitMQ → auth-service-consumer
- auth-service-consumer zavolá KC admin API:
POST /admin/realms/sencai/users{"username": "550e8400-...", // UUID z KC sub"email": "user@example.com","firstName": "John","lastName": "Doe","enabled": true,"requiredActions": ["VERIFY_EMAIL"]}
- KC automaticky odešle verifikační email
- Uživatel klikne na odkaz → email je ověřen
- Admin ve Strapi UI nastaví
Registration.emailVerified = true - Strapi lifecycle hook se spustí → webhook-publisher
- auth-service-consumer odstraní required action
VERIFY_EMAIL - Uživatel se může přihlásit
Přihlášení (dokončení profilu při prvním loginu)
Section titled “Přihlášení (dokončení profilu při prvním loginu)”- Uživatel se přihlásí přes KC login formulář
- KC vydá JWT
- Frontend přesměruje na
/auth/callbacks code + state - Frontend vymění code za JWT
- Strapi middleware keycloak-jwt ověří JWT
- Middleware zkontroluje, že existuje Strapi User se shodným emailem
- Pokud chybí
namenebosurname: přesměrování na/auth/complete-profile - Uživatel vyplní profil →
POST /api/auth/complete-profile - Strapi aktualizuje Usera → lifecycle hook → webhook-publisher → KC sync
- Atributy Strapi Usera a KC uživatele jsou sladěny
- Přesměrování na
/gravity/dashboard
SSO integrace
Section titled “SSO integrace”Keycloak umožňuje federovat externí identity providery:
Google OIDC
Section titled “Google OIDC”- KC Admin → Realm Settings → Identity Providers → Create → Google
- Zadat Google OAuth přihlašovací údaje (client_id, client_secret)
- Uložit
- Přihlašovací stránka zobrazí tlačítko Google
- Uživatel klikne → přesměrování na Google login
- Google přesměruje zpět s access tokenem
- KC vytvoří/napojí uživatele
SAML 2.0 (korporátní)
Section titled “SAML 2.0 (korporátní)”- KC Admin → Identity Providers → Create → SAML v2.0
- Nahrát SAML metadata firmy nebo nakonfigurovat ručně
- Nakonfigurovat mapování assertion (email → KC email atd.)
- SAML IdP firmy přesměruje na KC assertion consumer URL
- KC napojí uživatele na účet Sencai
Custom OIDC
Section titled “Custom OIDC”Keycloak umí federovat libovolný OIDC provider (Okta, Azure AD, vlastní):
- KC Admin → Identity Providers → Create → OpenID Connect v1.0
- Zadat Authorization URL, Token URL, Logout URL
- Přidat přihlašovací údaje clienta
- Namapovat claimy na atributy KC uživatele
- Uložit
Nastavení TOTP/2FA
Section titled “Nastavení TOTP/2FA”Zapnutí 2FA pro uživatele
Section titled “Zapnutí 2FA pro uživatele”- Uživatel jde do Account Settings → Security → 2FA
- Klikne na Enable 2FA
- Zobrazí se QR kód (obsahuje secret + issuer)
- Uživatel jej naskenuje v Google Authenticator / Authy / 1Password
- Uživatel zadá 6místný kód z aplikace
- KC ověří kód a zapne TOTP
- Zobrazí se recovery kódy (uložit pro obnovu účtu)
Konfigurace Keycloaku
Section titled “Konfigurace Keycloaku”TOTP využívá knihovnu Speakeasy:
Required Action: Configure OTPAlgorithm: TOTP (time-based)Digit: 6Period: 30sRequired Actions
Section titled “Required Actions”KC může uživatele donutit dokončit určité akce:
| Action | Spuštěno | Detaily |
|---|---|---|
VERIFY_EMAIL | Při registraci | Uživatel musí kliknout na verifikační odkaz v emailu |
UPDATE_PROFILE | Nastaví admin | Uživatel musí při dalším přihlášení vyplnit jméno/příjmení |
CONFIGURE_OTP | Nastaví admin | Uživatel si musí nastavit 2FA |
terms_and_conditions | Custom | Uživatel musí odsouhlasit obchodní podmínky |
Když se uživatel s nedokončenými required actions přihlásí, KC jej před vydáním access tokenu přesměruje do action flow.
Přístup k Admin API
Section titled “Přístup k Admin API”Grant Type: password
Section titled “Grant Type: password”Pro potřeby auth-service-consumer při správě KC uživatelů:
POST http://keycloak:8080/kc/realms/master/protocol/openid-connect/tokenContent-Type: application/x-www-form-urlencoded
grant_type=password&client_id=admin-cli&client_secret=<SECRET>&username=admin&password=adminOdpověď:
{ "access_token": "eyJ...", "expires_in": 3600, "token_type": "Bearer"}Poté použít token pro volání admin API:
POST http://keycloak:8080/kc/admin/realms/sencai/usersAuthorization: Bearer eyJ...
{ "username": "user", "email": "user@example.com", ... }Témata (Themes)
Section titled “Témata (Themes)”Sencai upravuje KC přihlašovací, registrační a emailové šablony:
Soubory: auth-service/themes/
login/— HTML/CSS přihlašovacího formulářeregister/— Registrační formulářemail/— Emailové šablony (verifikace, reset hesla)
Nahrát přes KC Admin → Realm Settings → Themes.
Synchronizace Keycloak ↔ Strapi
Section titled “Synchronizace Keycloak ↔ Strapi”Strapi → KC (zápis)
Section titled “Strapi → KC (zápis)”Strapi User.afterCreate/Update → webhook-publisher (event: user.update) → RabbitMQ user.events → auth-service-consumer → KC admin API: PUT /admin/realms/sencai/users/{id} → atributy v KC aktualizoványKC → Strapi (čtení)
Section titled “KC → Strapi (čtení)”Při přihlášení Strapi ověří, jestli je profil uživatele kompletní. Pokud ne:
keycloak-jwt middleware → fetchKcUserById(decoded.sub) → runWithoutKcSync(syncKcUserToStrapi) → Strapi User aktualizován z KC → žádná zpětná smyčka (runWithoutKcSync brání aktualizaci KC)Řešení problémů
Section titled “Řešení problémů”Q: KC hlásí 503 při startu
A: Keycloak potřebuje 30–90s na start. Počkejte a zkuste znovu. Zkontrolujte logy: docker logs keycloak
Q: Chyba JWT „invalid algorithm”
A: Strapi admin panel používá HS256 tokeny. Middleware musí dekódovat hlavičku, zkontrolovat alg a přeskočit tokeny, které nejsou RS256.
Q: „Account is not fully set up”
A: Uživatel má required action UPDATE_PROFILE. Zkontrolujte, že jsou v atributech KC uživatele vyplněny firstName/lastName.
Q: KC URL vrací 404
A: Ujistěte se, že je přítomen prefix /kc: KEYCLOAK_URL=http://keycloak:8080/kc (včetně koncového /kc).
Q: Token endpoint vrací 404
A: Token endpoint je na /kc/realms/sencai/protocol/openid-connect/token. Ověřte celou URL včetně prefixu /kc.