GSSO — Consumatori și contractul cu consumatorii
Acest conținut nu este încă disponibil în limba selectată.
| Cod document | SPEC-GSSO-2026 / Raportul 03 |
| Versiune | 0.1-draft (sursa EN, text care prevalează) |
| Data | 2026-10-05 |
| Statut | Proiect |
| Rapoarte însoțitoare | 00 RFP · 01 ADR · 02 Cerințe · 04 Documentație tehnică · 05 Foaie de parcurs |
Istoricul reviziilor
Section titled “Istoricul reviziilor”| Versiune | Data | Modificări |
|---|---|---|
| 0.1-draft | 2026-10-05 | Inventarul consumatorilor (așa cum a fost constatat la 2026-10-05), realm-ul/clientul/rolul țintă per aplicație, căile de migrare, contractul API/evenimente/starter, lista de verificare pentru conectare |
1. Modelele de integrare actuale
Section titled “1. Modelele de integrare actuale”| Model | Descriere | Problemă |
|---|---|---|
| A — autentificare dublă cu emitere de token-uri | oauth2Login față de Keycloak, apoi OidcAppTokenSuccessHandler emite propriul JWT HS512 al aplicației (copiind ROLE_*) și îl returnează SPA-ului prin /oidc-callback#id_token=. Autentificarea locală admin/admin încă funcționează | Cheie de semnare și parole locale; fără deconectare SSO; revocarea în Keycloak nu are efect; două surse de identitate |
| B — resource server | Aplicația validează token-urile RS256 ale Keycloak prin issuer/JWKS; SPA-ul folosește PKCE sau OAuth2 JHipster | Corect, dar fiecare aplicație are propriul cod și propria mapare a rolurilor |
| C — JWT local (+ MPass SAML) | Utilizatori și parole proprii; MPass prin SAML direct în aplicație | Fără SSO cu gStack |
| D — proiectat, neconstruit | Aplicațiile conform playbook-ului: gateway BFF + microservicii cu OAuth2 prin GSSO | Necesită CAP-GSSO-01..07 |
Ținta pentru toți: GSSO-ADR-009. Aceasta înseamnă un gateway/BFF sau un resource server prin gsso-spring-boot-starter, un SPA prin @gstack/gsso-angular și nicio parolă locală sau token emis local.
2. Inventarul consumatorilor și migrarea
Section titled “2. Inventarul consumatorilor și migrarea”Realm-ul interdictii este realm-ul partajat actual. „Ținta” se referă la realm-ul gstack, dacă nu se precizează altfel.
| Aplicație | Tip | Astăzi (realm / client / model) | Clienți țintă | Roluri țintă (exemple) | Note de migrare | Fază |
|---|---|---|---|---|---|---|
| saas_interdictii | SaaS | interdictii / interdictii-web confidential / A (patch manual necomis, JHipster 8.11 jwt) | interdictii-web (confidential, BFF) sau interdictii-spa (PKCE) + interdictii-api (bearer) | INTERDICTII_ADMIN, INTERDICTII_EMITENT, INTERDICTII_APROBATOR, INTERDICTII_CONSULTANT, INTERDICTII_AUDITOR | Se înlocuiește OidcAppTokenSuccessHandler cu resource server prin starter; se renunță la parolele locale; RolUser ADMIN/EMITENT se mapează la roluri; API-ul public de consultare → clienți de serviciu pentru bănci/ANAF într-un realm tenant- sau gstack | S4 |
| cancelarie | SaaS | interdictii / cancelarie confidential / B (JHipster oauth2, provizionare proprie în identity/) | cancelarie (confidential), cancelarie-api | CANCELARIA_REGISTRATOR, _SEF, _EXECUTOR, _CONTROLOR, _AUDITOR, _ADMIN | Procesul de integrare a angajaților apelează cererile de atribuire din api/v1/app (GSSO-FR-051) în locul admiterii locale; realm-ul local de dezvoltare jhipster este înlocuit de stiva compose GSSO | S4 |
| gregistry | SaaS | interdictii / gregistry-web public PKCE / B (ADR-002) | aceiași identificatori, mutați în gstack | GREGISTRY_ADMIN, GREGISTRY_OPERATOR | Pilot al starter-ului (deja model B); păstrează deconectarea doar locală până când se dorește single logout | S3 |
| gdocs | SaaS | gdocs (profilul oidc) / gdocs-web / A | gdocs-web, gdocs-api, gdocs-service | GDOCS_ADMIN, GDOCS_EDITOR, GDOCS_CITITOR | La fel ca interdictii; realm-ul gdocs este retras | S4 |
| saas_drumuri | SaaS | JWT local + MPass SAML în aplicație / mediul frontend indică greșit către glog-web / C | personal: drumuri-web în gstack; cetățeni: drumuri-public în cetatean | DRUMURI_ADMIN, DRUMURI_OPERATOR, DRUMURI_INSPECTOR | MPass se mută din aplicație în brokerul cetatean; mediul frontend se corectează imediat (identificator de client greșit); gazdă separată routes.tech.esempla.systems → URI-uri de redirecționare | S4 |
| saas_crm | SaaS | doar design / D | crm-gateway (confidential), câte un client de serviciu per microserviciu (crm-core, crm-clienti, crm-comercial, crm-interactiuni, crm-suport, crm-contracte, crm-operational, crm-taskuri, crm-strategie, crm-integrare, crm-cautare, crm-ai), crm-integration-1c | CRM_* (din raportul CRM 02) | CAP-GSSO-01 este blocant pentru CRM F0; token exchange către gDocFlow/gTenders (CAP-GSSO-07) | S1–S3 |
| saas_gdocflow | SaaS | design / D | gdocflow-gateway, clienți de serviciu | GDOCFLOW_* | Țintă și sursă de token exchange | S3 |
| saas_gtenders | SaaS | design / D | gtenders-gateway, clienți de serviciu | GTENDERS_* | Token exchange | S3 |
| saas_gnotify | SaaS/PaaS | realm-ul gnotify (necreat) / OIDC dezactivat / A; folosește client credentials ale clientului glog-ingest | gnotify-web, gnotify-service | GNOTIFY_ADMIN, GNOTIFY_OPERATOR; scope-ul notify:send pentru apelanți | Activare prin starter; GSSO folosește GNotify prin scope-ul gnotify-service | S4 |
| glog | PaaS | interdictii / glog-web PKCE (mapper tenant=demo codificat fix) + serviciul glog-ingest / B (profilul dualauth) | glog-web, glog-api, clienți de ingestie per apelant (<app>-glog) | GLOG_ADMIN, GLOG_AUDITOR; client scopes audit:write, audit:read | Se înlocuiește maparea rol→scope din GlogJwtAuthConverter cu starter-ul + scope-uri explicite; claim-ul tenant provine din mapper-ul GSSO; GSSO însuși devine client de ingestie | S3 |
| paas_gstorage | PaaS | realm-ul gstorage / gstorage-web, gstorage-ingest; alternativă cu cheie API | gstorage-web, gstorage-api, clienți de serviciu <app>-gstorage | GSTORAGE_ADMIN, GSTORAGE_ARCHIVIST; scope-urile `storage:read | write | admin` |
| paas_gflow | PaaS | design / D | gflow-gateway, gflow-server, principali de serviciu per aplicație (<app>-gflow) | GFLOW_ADMIN; grupuri candidate = rolurile consumatorilor | Folosește GET /api/v1/app/roluri/{cod}/utilizatori (GSSO-FR-103); fără token exchange | S3 |
| gportal / GDS | PaaS | fără autentificare (mock-uri) | gportal-web (PKCE) | ROLE_USER | Folosește @gstack/gsso-angular | S4 |
| platform (docs/RAG) | intern | interdictii / gstack-platform PKCE; Python PyJWT + JWKS, necesită ROLE_ADMIN | gstack-platform | PLATFORM_ADMIN | Verificarea rolului se schimbă din ROLE_ADMIN în PLATFORM_ADMIN | S4 |
| gsso_mob (GovSign) | mobil | realm-ul gstack / gstack-govsign-app public PKCE, redirecționare com.govsign.app://callback; aprobare QR per site | govsign-app (public PKCE) în gstack și cetatean | ROLE_USER | Se elimină KEYCLOAK_CLIENT_SECRET din configurația clientului public; autentificarea QR ca authenticator Keycloak (GSSO-FR-068) | S5 |
Site-uri whitelabel (ultra-b2b, ultra-ecom, bts-licitatii, bts-integrare, esempla-govstec, esempla-sistembancar) | site-uri | realm-urile ultra / gstack-ultra (neconfirmat) | câte un realm tenant-<code> pentru fiecare, din șablon | per site | Create prin GSSO din șablon; endpoint-ul de aprobare QR se păstrează până la GSSO-FR-068 | S4 |
| qa_platform | instrument | niciunul (doar credențialele țintei) | client de serviciu qa-runner per mediu | QA_RUNNER | Utilizatorii de test sunt creați prin API-ul GSSO în realm-uri de neproducție | S5 |
2.1 Rețeta de migrare pentru o aplicație cu modelul A
Section titled “2.1 Rețeta de migrare pentru o aplicație cu modelul A”- Se înregistrează platforma, clienții și rolurile în GSSO sau se adoptă din
interdictii(GSSO-FR-007). - Se creează atribuiri care reproduc deținătorii actuali ai rolurilor (
AtribuireAccescu sursaADOPTAT). - Se adaugă
gsso-spring-boot-starter. Pentru perioada de tranziție se seteazăgsso.issuer-uri,gsso.audienceșigsso.role-aliases(de exempluROLE_ADMIN: INTERDICTII_ADMIN). - Se elimină handler-ul de emitere a token-urilor, secretul JWT local, autentificarea locală cu parolă și ruta
/oidc-callback. Pentru un SPA de monolit, se trece la@gstack/gsso-angularîn modul BFF sau PKCE. - Se rulează testele E2E ale aplicației față de stiva compose GSSO, apoi se implementează în spatele unui feature flag care păstrează clientul vechi în paralel pentru o versiune.
- Se elimină
role-aliasesși maparea depreciatăROLE_ADMIN, apoi se șterge clientul vechi.
3. Contractul API (rezumat)
Section titled “3. Contractul API (rezumat)”Calea de bază: https://gsso.gstack.esempla.systems/api/v1 (prin gsso-gateway).
Convenții:
- JSON, erori RFC 7807;
Idempotency-Keype fiecare POST;- paginare cu
page,size,sortșiX-Total-Countîn răspuns; - denumiri de câmpuri de domeniu în limba română.
3.1 Zona app — aplicațiile consumatoare (client credentials, scope-ul gsso:app)
Section titled “3.1 Zona app — aplicațiile consumatoare (client credentials, scope-ul gsso:app)”| Metodă | Cale | Scop | Cer. |
|---|---|---|---|
GET | /app/platforma | propria platformă, cu clienții și rolurile | FR-098 |
PUT | /app/platforma | autoînregistrarea / actualizarea propriei platforme, a clienților și a rolurilor (doar clienții marcați) | FR-099 |
GET | /app/utilizatori?sub=&username=&email=&idnp= | căutare (IDNP doar dacă este permis) | FR-100 |
GET | /app/utilizatori/{sub} | statut (activ, MFA, ultima autentificare), nume, e-mail, unitate organizațională, limbă | FR-101 |
GET | /app/utilizatori/{sub}/roluri | rolurile efective ale platformei apelante, cu limitări și valabilitate | FR-101 |
DELETE | /app/utilizatori/{sub}/sesiuni | încheierea sesiunilor utilizatorului | FR-102 |
GET | /app/roluri/{cod}/utilizatori | utilizatorii care dețin un rol al platformei apelante (paginat) | FR-103 |
POST | /app/atribuiri | solicitarea unei atribuiri pentru un utilizator pe platforma apelantă ({sub, rol, orgUnit?, validPana?, motiv}) → SOLICITATA | FR-051 |
GET | /app/atribuiri/{id} | statutul atribuirii | FR-051 |
3.2 Zona admin — consola (sesiunea utilizatorului prin gsso-gateway)
Section titled “3.2 Zona admin — consola (sesiunea utilizatorului prin gsso-gateway)”Acestea sunt resursele; specificația OpenAPI completă se află la /api/v1/openapi.json:
/admin/realms,/admin/realms/{realm}/adoptie,/admin/realms/{realm}/reconciliere/admin/platforme,/admin/platforme/{cod}/clienti,/admin/platforme/{cod}/roluri/admin/clienti/{id}/secret(rotire)/admin/realms/{realm}/utilizatori,…/{sub},…/{sub}/credentiale,…/{sub}/sesiuni,…/{sub}/actiuni(acțiuni obligatorii),…/{sub}/deblocare/admin/atribuiri(cu/{id}/aprobare,/{id}/respingere,/{id}/revocare)/admin/unitati/admin/realms/{realm}/politica-autentificare/admin/sincronizare/joburi(cu/{id}/reincercare,/{id}/acceptare-drift)/admin/evenimente,/admin/evenimente/verificare-lant/admin/tablou(agregatele tabloului de bord)/admin/rapoarte/acces
3.3 Endpoint-uri operaționale
Section titled “3.3 Endpoint-uri operaționale”/health/live, /health/ready, /metrics, /info, /api/v1/openapi.json.
3.4 Contractul token-ului (realm-ul gstack)
Section titled “3.4 Contractul token-ului (realm-ul gstack)”| Claim | Conținut | Note |
|---|---|---|
iss | https://sso.gstack.esempla.systems/realms/gstack | |
sub | UUID, stabil | GSSO-FR-032 |
aud | audiența (audiențele) platformei țintă | mapper de audiență per platformă |
azp | identificatorul clientului | |
preferred_username, name, email | profil | |
roles | listă plată a rolurilor de realm efective (prefixate cu platforma) + ROLE_USER | filtrată per audiență cu scope-ul gsso-roles-filtered |
roles_scoped | { "<ROLE>": ["<org_unit>", …] } doar pentru atribuirile limitate | GSSO-FR-055 |
org_unit, org_unit_path | unitatea organizațională a utilizatorului | GSSO-FR-054 |
locale | ro / ru / en | |
idnp | doar cu client scope-ul opțional idnp | Q-GSSO-13 |
acr | 1 / 2 / 3 | GSSO-FR-070 |
act | { "sub": "<calling client>" } pe token-urile obținute prin exchange | GSSO-ADR-012 |
tenant | codul realm-ului pentru realm-urile tenant-* (înlocuiește mapper-ul codificat fix din glog) |
Durata de viață a token-ului de acces: 5 min (2 min pentru clienții sensibili). Semnătură: RS256, cu cheile publicate la /protocol/openid-connect/certs.
4. Utilizarea starter-ului
Section titled “4. Utilizarea starter-ului”<dependency> <groupId>systems.esempla.gsso</groupId> <artifactId>gsso-spring-boot-starter</artifactId></dependency># application.yml of a consuming servicegsso: issuer-uri: https://sso.gstack.esempla.systems/realms/gstack audience: crm role-aliases: # transition only (report 03 §2.1) ROLE_ADMIN: CRM_ADMIN client: # optional: outgoing calls id: crm-comercial secret: ${GSSO_CLIENT_SECRET} revocation: kafka-topic: gsso.access-revoked.v1 # deny-list, GSSO-ADR-013@PreAuthorize("hasAuthority('CRM_ADMIN')")public void delete(...) { ... }
GssoPrincipal p = GssoPrincipal.current(); // sub, username, orgUnit, localeRestClient docs = gsso.exchangeClient("gdocflow"); // token exchange (on-behalf-of)RestClient glog = gsso.serviceClient("glog"); // client credentialsAngular:
provideGsso({ mode: 'bff', loginUrl: '/oauth2/authorization/oidc', logoutUrl: '/api/logout' })// or { mode: 'pkce', issuer, clientId }// route guard: canActivate: [gssoRole('CRM_ADMIN')]// template: <button *gssoHasRole="'CRM_ADMIN'">…</button>5. Contractul evenimentelor
Section titled “5. Contractul evenimentelor”Toate evenimentele sunt CloudEvents în mod binar pe Kafka, cu source = gsso și subject = <realm>/<sub>.
| Topic | Producător | Tip | Payload (data) | Consumatori |
|---|---|---|---|---|
gsso.kc-events.v1 | Extensia Keycloak gsso-kafka | md.gstack.gsso.kc.user.<TYPE> / md.gstack.gsso.kc.admin.<OPERATION> | câmpurile evenimentului Keycloak (tip, realm, client, utilizator, ip, eroare, detalii / tipul resursei, cale, reprezentare fără secrete) | doar gsso |
gsso.access-revoked.v1 | gsso | md.gstack.gsso.access.revoked | {sub, realm, roluri[], platforme[], notBefore, motiv} | starter-ul din fiecare aplicație |
gsso.user-changed.v1 | gsso | md.gstack.gsso.user.changed | {sub, realm, campuri[], enabled} | aplicațiile care păstrează în cache datele utilizatorilor |
gsso.grant.v1 | gsso | md.gstack.gsso.grant.<STARE> | {id, sub, rol, platforma, orgUnit, validDe, validPana, stare} | aplicațiile care oglindesc permisiunile (de ex. gFlow) |
Cheia = <realm>:<sub>. Livrarea este at-least-once, așadar consumatorii trebuie să fie idempotenți după id. Fiecare grup de consumatori are un topic DLQ <topic>.dlq.<group>.
6. Convenții de denumire
Section titled “6. Convenții de denumire”| Obiect | Convenție | Exemplu |
|---|---|---|
| Codul platformei | litere mici, [a-z][a-z0-9-]* | crm, interdictii, glog |
| Rol | <PLATFORM_UPPER>_<ROLE> (cratimele devin _) | CRM_ADMIN, INTERDICTII_EMITENT |
| Client SPA | <platform>-web (PKCE) sau <platform>-gateway (BFF) | glog-web, crm-gateway |
| Client backend | <platform>-api (bearer-only) | cancelarie-api |
| Client de serviciu | <service> sau <caller>-<callee> | crm-comercial, gnotify-glog |
| Client scope (serviciu) | <platform>:<verb> sau <object>:<verb> | audit:write, storage:read |
| Realm de tenant | tenant-<code> | tenant-ultra-b2b |
| Audiență | codul platformei | crm |
7. Cote și nivel de serviciu
Section titled “7. Cote și nivel de serviciu”| Element | Valoare implicită |
|---|---|
Limita de rată a API-ului app | 50 cereri/s per client, vârf (burst) 100 |
| Autoînregistrare | maximum 20 de clienți și 200 de roluri per platformă |
| Cereri de atribuire din partea aplicațiilor | 1 000 / zi per platformă |
| Disponibilitate oferită | Keycloak 99,9 %, consolă/API 99,5 % (NFR-AVL) |
| Suport | echipa platformei, în orele de lucru; indisponibilitatea Keycloak = P1 |
| Versionare | api/v1 stabil; o modificare incompatibilă = v2, cu 6 luni de funcționare în paralel |
8. Lista de verificare pentru conectarea unei aplicații noi
Section titled “8. Lista de verificare pentru conectarea unei aplicații noi”- Proprietarul platformei este desemnat; codul platformei este ales (§6).
- Rolurile sunt enumerate cu descrieri în RO/RU/EN; rolurile sensibile sunt marcate; rolurile compozite sunt definite.
- Clienții sunt declarați: tipul de acces, URI-urile de redirecționare (exacte), originile web, URL-ul de deconectare back-channel.
- Clienții de serviciu sunt declarați per serviciu apelant, cu scope-uri; țintele de token exchange sunt enumerate, dacă este necesar.
- Platforma este înregistrată în GSSO (consolă sau
PUT /api/v1/app/platforma), iar statutul ei de sincronizare este sincronizat. - Aplicația folosește
gsso-spring-boot-starter(și@gstack/gsso-angular). Nu există parole locale și nici token-uri emise local. - Validarea audienței este activă. Autorizarea folosește doar rolurile platformei.
- Aplicația este abonată la
gsso.access-revoked.v1(prin starter). - Atribuirile inițiale sunt solicitate și aprobate; utilizatorii de test există în realm-urile de neproducție.
- CSP-ul permite
sso.gstack.esempla.systemsînconnect-srcșiform-action. - Testul E2E de autentificare trece față de stiva compose GSSO. Sonda matricei de autorizare (
/gtestgen) trece. - Aplicația este adăugată în §2 al prezentului raport și în raportul de acces.