livrare lot 2
This commit is contained in:
commit
8ecc78e729
763 changed files with 164593 additions and 0 deletions
362
backend/services/gateway-auth-layer/didiKeycloak/INDEX.md
Normal file
362
backend/services/gateway-auth-layer/didiKeycloak/INDEX.md
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
# didiKeycloak - Index
|
||||
|
||||
> **Deployment LOCAL (activ)**: Keycloak ruleaza ca un singur container `didi-keycloak` pe masina de deployment. Nu exista cluster SSO / Swarm.
|
||||
>
|
||||
> - Imagine: `quay.io/keycloak/keycloak:26.0`, pornit cu `start-dev --import-realm`.
|
||||
> - Port: `28080` (host) -> `8080` (container), servit sub calea relativa `/auth` (`KC_HTTP_RELATIVE_PATH=/auth`).
|
||||
> - `KC_HOSTNAME_STRICT=false`, `KC_PROXY_HEADERS=xforwarded` — hostname derivat din headerele proxy-ului din fata.
|
||||
> - **Doua realm-uri** importate din `realm-import/`: `didi-clients` (useri finali) + `didi-admins` (operatori: admin / moderator / senior_moderator).
|
||||
> - Temele custom sunt bind-mount-uite din folderul acesta in `/opt/keycloak/themes/`.
|
||||
> - Master credentials: `admin/admin123` (`KEYCLOAK_ADMIN` / `KEYCLOAK_ADMIN_PASSWORD`).
|
||||
|
||||
Serviciul de autentificare si autorizare al platformei DIDI. Bazat pe Keycloak, gestioneaza utilizatori, roluri, grupuri, clienti OAuth2 si token-uri JWT. Include teme custom de login si template-uri email in romana.
|
||||
|
||||
**Imagine**: quay.io/keycloak/keycloak:26.0 (container local `didi-keycloak`)
|
||||
**Container**: didi-keycloak (activ, pe masina de deployment)
|
||||
**Port**: 28080 (host) -> 8080 (container), sub `/auth`
|
||||
**Realm-uri**: `didi-clients` (useri) + `didi-admins` (operatori)
|
||||
**Baza de date**: PostgreSQL `didi-postgres:5432/DIDI` (`KC_DB=postgres`, user `bos_interface`)
|
||||
|
||||
---
|
||||
|
||||
## Ce face
|
||||
|
||||
1. **Autentificare OAuth2/OIDC** -- login, logout, refresh token, SSO
|
||||
2. **Management utilizatori** -- creare, roluri, grupuri, tier-uri
|
||||
3. **Emitere token-uri JWT** -- access token (10 min), refresh token, SSO session (2h)
|
||||
4. **Validare JWT** -- Kong valideaza token-urile emise de Keycloak
|
||||
5. **Securitate cont** -- brute force (lockout dupa 5 incercari esuate), MFA TOTP, password policy
|
||||
6. **Deep linking mobil** -- redirectare catre app mobila dupa verificare email
|
||||
7. **Teme custom** -- login page dark purple, emailuri in romana
|
||||
|
||||
---
|
||||
|
||||
## Structura fisierelor
|
||||
|
||||
```
|
||||
realm-import/
|
||||
didi-clients-realm.json -- Configurare completa realm (clienti, roluri, grupuri, utilizatori)
|
||||
themes/
|
||||
didi-clients-theme/ -- Tema principala (dark purple)
|
||||
login/
|
||||
theme.properties -- Configurare tema login
|
||||
register.ftl -- Formular inregistrare
|
||||
login-reset-password.ftl -- Resetare parola
|
||||
login-verify-email.ftl -- Pagina verificare email
|
||||
info.ftl -- Routing mobil/web dupa actiuni
|
||||
register-commons.ftl -- Macro acceptare termeni
|
||||
messages/
|
||||
messages_en.properties -- Etichete UI engleza
|
||||
resources/
|
||||
css/login.css -- Stil dark purple (784 linii)
|
||||
js/placeholders.js -- Placeholders formulare
|
||||
email/
|
||||
theme.properties -- Configurare tema email
|
||||
html/
|
||||
email-verification.ftl -- Template verificare email (romana, dark theme)
|
||||
executeActions.ftl -- Template actiuni (dark purple gradient)
|
||||
text/
|
||||
email-verification.ftl -- Versiune text plain
|
||||
didi-ai-theme/ -- Tema alternativa (white, blue accents)
|
||||
login/
|
||||
theme.properties
|
||||
resources/
|
||||
css/login.css
|
||||
img/logo.png
|
||||
didi-backend-theme/ -- Tema backend (white, "didi - Backend")
|
||||
login/
|
||||
theme.properties
|
||||
resources/
|
||||
css/login.css
|
||||
img/logo.png
|
||||
```
|
||||
|
||||
Zero cod custom backend. Doar configurare realm JSON + teme FreeMarker/CSS.
|
||||
|
||||
---
|
||||
|
||||
## Clienti OAuth2 (4)
|
||||
|
||||
| Client ID | Tip | Scop | Flow-uri | PKCE |
|
||||
|-----------|-----|------|----------|------|
|
||||
| didi-web-app | Public | Frontend web utilizatori | Standard + Direct Access | nu |
|
||||
| admin-dashboard | Public | Dashboard admin React | Standard + Direct Access | S256 |
|
||||
| orchestrator-api | Confidential | Serviciu backend orchestrator | Direct Access + Service Account | nu |
|
||||
| kong-api-gateway | Bearer Only | Gateway JWT validation | Service Account only | nu |
|
||||
|
||||
### didi-web-app
|
||||
- Redirect URIs: localhost:3001, localhost:5173, localhost:13001, localhost:33001 (+ 127.0.0.1)
|
||||
- Web Origins: aceleasi + wildcard
|
||||
- Scopes: web-origins, acr, profile, roles, email
|
||||
|
||||
### admin-dashboard
|
||||
- Root URL: http://localhost:13003
|
||||
- PKCE: S256 (obligatoriu)
|
||||
- Redirect URIs: localhost:13003, localhost:3003, localhost:33003, localhost:33001, localhost:3001, 127.0.0.1:13003, 127.0.0.1:3003, 127.0.0.1:33003, 127.0.0.1:33001, 10.11.50.11:33003, 10.11.50.11:3003
|
||||
- Post Logout: localhost:13003, localhost:3003, localhost:33003, 10.11.50.11:33003
|
||||
|
||||
### orchestrator-api
|
||||
- Secret: nmmImrmPAcADuPh-ZTqLY7GDhCAjfXsolDOM6TxZbHg
|
||||
- Service Account: activat
|
||||
- Bearer Only: implicit (confidential)
|
||||
|
||||
### kong-api-gateway
|
||||
- Secret: Fu1rJ8QsjCj4j4_qZiMXyx6Ewo3xC2ik7X5m_MvSLOE
|
||||
- Bearer Only: da (nu face login, doar valideaza)
|
||||
- Service Account: activat
|
||||
|
||||
---
|
||||
|
||||
## Roluri (doua realm-uri)
|
||||
|
||||
Operatorii (admin / moderator / senior_moderator) traiesc in realm-ul **`didi-admins`**; realm-ul **`didi-clients`** contine doar capabilitati de user si tier-uri de abonament.
|
||||
|
||||
### Realm `didi-admins` (operatori)
|
||||
|
||||
| Rol | Scop |
|
||||
|-----|------|
|
||||
| admin | Acces complet la platforma + admin dashboard |
|
||||
| moderator | HIL moderator -- poate revendica si rezolva intrari din coada (admin dashboard /moderation) |
|
||||
| senior_moderator | Senior HIL moderator -- poate escalada si forta gold atom in brain |
|
||||
|
||||
### Realm `didi-clients` (useri finali)
|
||||
|
||||
| Rol | Scop |
|
||||
|-----|------|
|
||||
| viewer | Poate vizualiza rezultate analize |
|
||||
| analyst | Poate crea si gestiona analize |
|
||||
| api_user | Poate accesa endpoint-uri API |
|
||||
| free_tier | Privilegii tier gratuit |
|
||||
| paid_tier | Privilegii tier platit |
|
||||
| enterprise_tier | Privilegii tier enterprise |
|
||||
|
||||
Roluri implicite la inregistrare (didi-clients): viewer + free_tier
|
||||
|
||||
---
|
||||
|
||||
## Grupuri (6)
|
||||
|
||||
| Grup | Roluri | Tier | Limita zilnica | Rate limit |
|
||||
|------|--------|------|----------------|------------|
|
||||
| free-users | free_tier, viewer, api_user | free | 10 | 10/min |
|
||||
| paid-users | paid_tier, viewer, analyst, api_user | paid | 100 | 60/min |
|
||||
| enterprise-users | enterprise_tier, viewer, analyst, api_user | enterprise | nelimitat | 600/min |
|
||||
| administrators | admin, analyst, viewer, api_user, enterprise_tier | admin | nelimitat | nelimitat |
|
||||
|
||||
| Grup | Roluri | Scop |
|
||||
|------|--------|------|
|
||||
| moderators-team | moderator | HIL review staff |
|
||||
| senior-moderators-team | moderator + senior_moderator | Lead moderators with brain gold-promotion authority |
|
||||
|
||||
Atributele de grup (tier, daily_limit, rate_limit) sunt disponibile in token-ul JWT si pot fi folosite de Kong/backend pentru rate limiting.
|
||||
|
||||
---
|
||||
|
||||
## Acces admin dashboard
|
||||
|
||||
| Pagina admin dashboard | viewer / paid_tier / etc | moderator | senior_moderator | admin |
|
||||
|---|---|---|---|---|
|
||||
| /admin/* (any) | 403 (Unauthorized page -> public app) | Dashboard + History + Moderation | same + force_gold_brain | tot |
|
||||
| /users, /framework, /llm-components, /providers | nu | nu | nu | da |
|
||||
| /history | nu | da | da | da |
|
||||
| /moderation/* | nu | da | da | da |
|
||||
|
||||
Note: `viewer` este rolul implicit asignat la toate signup-urile (`defaultRoles: [viewer, free_tier]`). End-userii (clientii) primesc acest rol; ei NU vad niciodata admin dashboard.
|
||||
|
||||
---
|
||||
|
||||
## Utilizatori pre-configurati (5)
|
||||
|
||||
| Email | Parola | Grup | Rol principal |
|
||||
|-------|--------|------|---------------|
|
||||
| admin@didi.local | admin123 | administrators | admin |
|
||||
| demo@didi.local | Demo123! | free-users | viewer |
|
||||
| free@didi.local | password123 | free-users | free_tier |
|
||||
| paid@didi.local | password123 | paid-users | paid_tier |
|
||||
| enterprise@didi.local | password123 | enterprise-users | enterprise_tier |
|
||||
|
||||
Toti au emailVerified: true. Parolele nu sunt temporare.
|
||||
|
||||
---
|
||||
|
||||
## Setari token
|
||||
|
||||
| Parametru | Valoare |
|
||||
|-----------|---------|
|
||||
| Access Token Lifespan | 600s (10 minute) |
|
||||
| Access Token Implicit | 900s (15 minute) |
|
||||
| SSO Session Idle | 7200s (2 ore) |
|
||||
| SSO Session Max | 86400s (24 ore) |
|
||||
| Algoritm semnatura | RS256 |
|
||||
|
||||
---
|
||||
|
||||
## Securitate
|
||||
|
||||
Aplicata pe **ambele realm-uri** (`didi-clients` + `didi-admins`).
|
||||
|
||||
### Brute force protection
|
||||
- Activat (`bruteForceProtected: true`)
|
||||
- Max incercari esuate: 5 (`failureFactor`)
|
||||
- Timp asteptare: 60s (increment) / min quick-login wait 60s / quick-login check 1000ms
|
||||
- Max wait: 900s (15 minute)
|
||||
- Fereastra glisanta: 43200s (12 ore)
|
||||
- Lockout permanent: dezactivat
|
||||
|
||||
### MFA / TOTP (livrabil Lot 2)
|
||||
- Politica OTP: `otpPolicyType=totp` (HmacSHA1, 6 cifre, perioada 30s) — pe ambele realm-uri.
|
||||
- Required action `CONFIGURE_TOTP` **enabled** pe realm-ul `didi-admins` (operatorii sunt fortati sa configureze TOTP; userii noi de admin primesc `CONFIGURE_TOTP` in `requiredActions` la prima logare, alaturi de `UPDATE_PASSWORD`).
|
||||
- Realm-ul `didi-clients` are politica TOTP configurata (MFA disponibil pentru enrolment).
|
||||
|
||||
### Password policy (ambele realm-uri)
|
||||
```
|
||||
length(10) and digits(1) and upperCase(1) and lowerCase(1) and notUsername and passwordHistory(3)
|
||||
```
|
||||
Minim 10 caractere, cel putin o cifra, o majuscula, o minuscula, parola != username, fara reutilizarea ultimelor 3 parole.
|
||||
|
||||
### Setari realm
|
||||
- Inregistrare: dezactivata (registrationAllowed: false)
|
||||
- Login cu email: da
|
||||
- Email ca username: da
|
||||
- Verificare email: dezactivata (verifyEmail: false)
|
||||
- Editare username: nu
|
||||
- Emailuri duplicate: nu
|
||||
- Remember me: da
|
||||
- Reset parola: da
|
||||
|
||||
---
|
||||
|
||||
## Teme
|
||||
|
||||
### didi-clients-theme (principala, dark purple)
|
||||
- Background: #050510 (foarte inchis)
|
||||
- Accent: #A855F7 -> #7C3AED -> #6D28D9 (gradient purple)
|
||||
- Card: glassmorphism (backdrop blur, border semi-transparent)
|
||||
- Logo: "didi" (48px, font Outfit)
|
||||
- Subtitle: "Misinformation Detection Platform"
|
||||
- Font: Outfit (display) + Inter (body)
|
||||
- Butoane: gradient purple cu glow la hover
|
||||
- Responsive: suporta mobile (100dvh)
|
||||
|
||||
### didi-ai-theme (alternativa)
|
||||
- Background: alb
|
||||
- Accent: #0052CC (albastru)
|
||||
- Subtitle: "didi - AI Platform"
|
||||
|
||||
### didi-backend-theme (alternativa)
|
||||
- Background: alb
|
||||
- Accent: #0052CC (albastru)
|
||||
- Subtitle: "didi - Backend"
|
||||
|
||||
---
|
||||
|
||||
## Template-uri email
|
||||
|
||||
### email-verification.ftl
|
||||
- Limba: romana
|
||||
- Titlu: "Verifica adresa de email"
|
||||
- Stil: dark purple gradient header
|
||||
- URL custom: https://didi365.eu/api/auth/verify-email?key=...
|
||||
- Afiseaza timpul de expirare (convertit din secunde)
|
||||
- Deep link mobil: didi://email-verified, com.didi365.app://email-verified
|
||||
|
||||
### executeActions.ftl
|
||||
- Stil: dark purple gradient
|
||||
- Suporta actiuni multiple
|
||||
- Deep linking mobil
|
||||
|
||||
### info.ftl (routing dupa actiuni)
|
||||
- Detecteaza client ID (didi-mobile-app vs didi-web-app)
|
||||
- Mobile: deep link cu fallback dupa 1.5-3s
|
||||
- Web: redirect la /email-verified dupa 2s
|
||||
- Butoane: "Deschide in aplicatie" / "Continua in browser"
|
||||
|
||||
---
|
||||
|
||||
## Fluxul de autentificare
|
||||
|
||||
```
|
||||
Utilizator deschide aplicatia
|
||||
|
|
||||
v
|
||||
Redirect la Keycloak login (tema didi-clients-theme)
|
||||
|
|
||||
v
|
||||
Utilizatorul introduce email + parola
|
||||
|
|
||||
v
|
||||
Keycloak valideaza + emite JWT (access token 10 min, refresh token)
|
||||
|
|
||||
v
|
||||
Redirect inapoi la aplicatie cu authorization code
|
||||
|
|
||||
v
|
||||
Aplicatia schimba codul in token-uri (PKCE pentru admin-dashboard)
|
||||
|
|
||||
v
|
||||
Requesturi API cu Authorization: Bearer {access_token}
|
||||
|
|
||||
v
|
||||
Kong valideaza JWT-ul (plugin jwt, consumer didi-keycloak-users, RS256, match pe iss)
|
||||
|
|
||||
v
|
||||
Backend-ul decodeaza JWT pentru user_id/email (fara re-validare)
|
||||
|
|
||||
v
|
||||
La fiecare 30s, aplicatia face refresh token daca expira in < 70s
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cum comunica cu restul platformei
|
||||
|
||||
| Cine | Ce face | Cum |
|
||||
|------|---------|-----|
|
||||
| admin-dashboard | Login/logout utilizator | OAuth2 Standard Flow + PKCE |
|
||||
| didi-web-app (frontend) | Login/logout utilizator | OAuth2 Standard Flow |
|
||||
| Kong | Valideaza JWT pe fiecare request (RS256, match pe iss) | plugin jwt + consumer didi-keycloak-users |
|
||||
| didiFramework (auth.ts) | Auto-inregistrare utilizator, Keycloak Admin API | Direct Access + Admin credentials |
|
||||
| didiFramework (admin.ts) | Lista utilizatori, update emailVerified | Keycloak Admin API |
|
||||
| agent-v3 | Decodeaza JWT din header (sub, email) | Doar decodare, fara validare (Kong a validat deja) |
|
||||
|
||||
---
|
||||
|
||||
## Admin API folosit de automatizari
|
||||
|
||||
- Admin API base: `http://localhost:28080/auth/admin/realms/{didi-clients|didi-admins}/` (Keycloak local, sub `/auth`)
|
||||
- Master token via `POST /auth/realms/master/protocol/openid-connect/token` cu `client_id=admin-cli, username=admin, password=admin123`
|
||||
- Folosit de fluxul de auto-inregistrare didiFramework + scripturi viitoare de automatizare.
|
||||
|
||||
---
|
||||
|
||||
## Roluri JWT in token-urile clientilor
|
||||
|
||||
Token-ul JWT contine acum array-ul `realm_access.roles`, parsat de agent-v3 (`req.jwtRoles`) pentru verificarile de rol pe endpoint-urile de moderare. Token-ul se reimprospateaza automat la fiecare 30s (comportament existent).
|
||||
|
||||
---
|
||||
|
||||
## Baza de date
|
||||
|
||||
Keycloak foloseste PostgreSQL local, aceeasi instanta ca restul platformei:
|
||||
- `KC_DB=postgres`
|
||||
- `KC_DB_URL=jdbc:postgresql://didi-postgres:5432/DIDI` (schema `public`)
|
||||
- User: `bos_interface`
|
||||
- Schema proprie Keycloak (gestionata automat)
|
||||
|
||||
Datele stocate: realm config, utilizatori, sesiuni, events, client sessions.
|
||||
|
||||
---
|
||||
|
||||
## Audit si evenimente
|
||||
|
||||
- Evenimente utilizator: activate (jboss-logging)
|
||||
- Evenimente admin: activate cu detalii
|
||||
- Logare: in stdout Docker (accesibil prin docker logs)
|
||||
|
||||
## Recent Changes
|
||||
|
||||
- **MFA / TOTP (livrabil Lot 2)**: `otpPolicyType=totp` pe ambele realm-uri; required action `CONFIGURE_TOTP` enabled pe `didi-admins` (operatorii sunt fortati sa configureze TOTP la prima logare, alaturi de `UPDATE_PASSWORD`).
|
||||
- **Password policy** pe ambele realm-uri: `length(10) and digits(1) and upperCase(1) and lowerCase(1) and notUsername and passwordHistory(3)`.
|
||||
- **Realm `didi-admins` (operatori)**: 3 roluri `admin` / `moderator` / `senior_moderator`; clienti publici `admin-dashboard` + `ai-platform-dashboard`; useri de test `moderator.test@didi.local`, `senior.moderator.test@didi.local`.
|
||||
- **Realm `didi-clients` (useri finali)**: capabilitati `viewer`, `analyst`, `api_user` + tier-uri `free_tier`, `paid_tier`, `enterprise_tier`; clienti `didi-web-app`, `admin-dashboard`, `orchestrator-api`, `kong-api-gateway`.
|
||||
- **Deployment local**: container unic `didi-keycloak` (`quay.io/keycloak/keycloak:26.0`, `start-dev --import-realm`), port `28080` sub `/auth`, `KC_HOSTNAME_STRICT=false`, `KC_PROXY_HEADERS=xforwarded`, DB `didi-postgres:5432/DIDI`. Fara cluster SSO / Swarm / Infinispan.
|
||||
Loading…
Add table
Add a link
Reference in a new issue