Referință tehnică
Documentație API – Autentificare
Pentru integrarea aplicațiilor partenere. Pentru teste interactive, folosiți API Playground. Gestionarea rolurilor (grupuri de permisiuni) și utilizatorilor per site este documentată la API gestionare site. SSO cross-site (silent authentication) la SSO cross-site hibrid; sesiuni active la Platform API sesiuni.
Introducere
SCMCGate – modul de autentificare centralizată pentru mai multe aplicații. Site-urile externe (parteneri) se autentifică prin API: trimit credențiale, primesc token, validează token-ul la fiecare request protejat.
Cum obține credențialele un partener (inclusiv non-tehnic)?
- Partenerul contactează administratorul SCMCGate (email, telefon).
- Administratorul adaugă site-ul în panou: Admin → Site-uri → Adaugă site (tip API).
- Sistemul generează
client_idșiclient_secret. - Administratorul transmite credențialele partenerului (email, etc.).
- Partenerul le transmite echipei tehnice pentru integrare.
Pentru partener atehnic: doar solicită accesul, primește credențialele și le transmite developerului. Documentația de integrare (/docs/api) este pentru echipa tehnică.
Autentificare: email + token
Login: utilizatorul introduce email + parolă. Backend-ul trimite la API și primește un token.
Request-uri ulterioare: se trimite token-ul în Authorization: Bearer <token>.
1. Verifică GET /api/auth/status – dacă enabled: false, blochează login
2. User introduce email + parolă
3. POST /api/auth/login (client_id, client_secret, email, password) → token
4. La fiecare request: Authorization: Bearer <token> + X-Client-ID
5. GET /api/auth/verify returnează user (id, name, email, roluri, atribuiri pe site)
6. POST /api/auth/change-password — utilizatorul își schimbă parola (Bearer + parola veche + parola nouă)
Endpoint-uri
POST /api/auth/login
Request: {"client_id":"...","client_secret":"...","email":"...","password":"..."}
Response 200: {"token":"...","expires_in":3600,"site":{"id":1,"slug":"...","client_id":"..."},"token_bound_to_site_id":1,"user":{...},"request_id":"..."} — token-ul este legat strict de site.id / client_id. Fiecare răspuns API include request_id (și header X-Request-ID) pentru suport.
401: Credențiale invalide. 403: Autentificarea dezactivată.
GET /api/auth/verify
Headers: Authorization: Bearer <token>, X-Client-ID: <client_id>
Response 200: {"site":{...},"token_bound_to_site_id":1,"user":{...},"request_id":"..."}
POST /api/auth/change-password
Schimbare parolă self-service pentru utilizatorul autentificat cu token Bearer (același flux ca la verify).
Headers: Authorization: Bearer <token>, X-Client-ID: <client_id>, Content-Type: application/json
Body: {"current_password":"...","password":"...","password_confirmation":"..."}
Response 200: {"message":"Password updated successfully.","request_id":"..."}
401: token invalid sau lipsă. 403: site inactiv / user fără acces la site. 422: parola curentă greșită sau parola nouă invalidă (reguli din politica de parole).
Notă: parola este globală pe cont (email unic) — se schimbă pentru toate site-urile unde există acel utilizator. Token-ul Bearer curent rămâne valid după schimbare. Adminii pot seta parola fără parola veche via PATCH /api/site/users/{id} (users.write).
GET /api/auth/status
Query: ?site=slug sau ?client_id=...
Response: {"enabled":true,"site_name":"...","flags":{"catalog_active":true,"auth_enabled":true}}. enabled este false dacă site-ul nu e activ în catalog sau autentificarea e oprită – în ambele cazuri nu permiteți login.
API gestionare site (roluri, companii, grupuri, utilizatori)
Partenerii cu site tip API pot gestiona datele proprii prin REST, sub prefixul /api/site/ (aceleași rute există și sub /api/v2/site/, comportament identic).
Autentificare (două moduri):
- client_secret — header-e
X-Client-IDșiX-Client-Secret(ca laPOST /api/auth/login). Acces complet la toate resursele site-ului. ÎnPOST/PATCHcu JSON puteți include șiclient_id/client_secretîn corp. - Token utilizator (Bearer) —
Authorization: Bearer <token>(de la login) +X-Client-ID(fără secret). Permisiunile sunt reuniunea valorilorapi_permissionsde pe rolurile de site atribuite utilizatorului (configurate în panou la fiecare rol: ex.roles.read,users.write,companies.read,groups.read, sau*pentru tot). Fără permisiuni pe roluri, răspuns 403.
Condiție: site-ul trebuie să fie în producție (login API activ). În mentenanță sau retras, răspuns 403 – aceeași regulă ca la login.
Roluri — roles
CRUD REST (id numeric în URL). Răspunsul listă / detaliu include api_permissions (doar pentru configurare în panou).
Listă: query opționale q (nume/slug), sort (name, slug, created_at, updated_at), dir (asc / desc).
GET /api/site/roles— listăPOST /api/site/roles— body:{"name":"Nume rol","slug":"optional"}(sluggenerat din nume dacă lipsește)GET|PATCH|DELETE /api/site/roles/{id}
Utilizatori — users
GET /api/site/users— paginare:per_page(implicit 50, max 100); filtre:q(nume/email),sort(name,email,created_at,updated_at),dirPOST /api/site/users— creează utilizator și îl leagă de site; body exemplu:
{
"name": "Ion Popescu",
"email": "ion@exemplu.ro",
"password": "ParolaSigura1!",
"password_confirmation": "ParolaSigura1!",
"assignments": [
{ "site_role_id": 2, "is_primary": true, "metadata": {} }
]
}
assignments opțional; fiecare intrare atribuie un rol de site (definit în panou / GET /api/site/roles). site_role_id este ID-ul din acel site — nu se copiază între site-uri.
Același email pe mai multe site-uri: emailul este unic la nivel de cont (users). POST /api/site/users eșuează dacă emailul există deja. Pentru a da acces unui utilizator care există deja (creat de alt site sau din panou), folosiți:
POST /api/site/users/attach— body:{"email":"user@exemplu.ro","assignments":[{"site_role_id":2,"is_primary":true}]}(fără parolă). Leagă contul existent de site-ul curent și creează atribuirile de rol pe acest site. 422 dacă emailul nu există, dacă utilizatorul are deja acces la acest site sau dacăsite_role_idnu aparține site-ului.
GET|PATCH|DELETE /api/site/users/{id}— laPATCH,assignmentsînlocuiește complet atribuirile pe acest site dacă este trimis. Răspunsul includesite_companiesșisite_groups.
Companii — companies
Permisiuni API: companies.read / companies.write. Acțiunile de business pe companie (ca la roluri) sunt în action_keys în body la creare/actualizare.
GET /api/site/companies— listăPOST /api/site/companies— body:{"name":"Nume","slug":"optional","action_keys":["cheie_acțiune"]}GET|PATCH|DELETE /api/site/companies/{id}
Grupuri — groups
Permisiuni API: groups.read / groups.write. La fel ca la companii: action_keys în body.
GET /api/site/groups— listăPOST /api/site/groups— body:{"name":"Nume","slug":"optional","action_keys":[]}GET|PATCH|DELETE /api/site/groups/{id}
Legătură utilizator ↔ companie
Necesită users.write. Utilizatorul trebuie să fie deja pe site (înrolat).
POST /api/site/users/{id}/companies— body:{"site_company_id": 1}(adaugă utilizatorul în companie)DELETE /api/site/users/{id}/companies/{company_id}— scoate utilizatorul din companie
Legătură utilizator ↔ grup
POST /api/site/users/{id}/groups— body:{"site_group_id": 1}DELETE /api/site/users/{id}/groups/{group_id}
La login/verify, site_action_keys reunește acțiunile din roluri, plus acțiunile din toate companiile și toate grupurile la care utilizatorul este legat (reuniune).
Exemplu cURL (listă roluri, client_secret)
curl -s "https://autentificare.scmc.ro/api/site/roles" \
-H "X-Client-ID: YOUR_CLIENT_ID" \
-H "X-Client-Secret: YOUR_CLIENT_SECRET" \
-H "Accept: application/json"
Exemplu cURL (același endpoint, Bearer)
curl -s "https://autentificare.scmc.ro/api/site/roles" \
-H "X-Client-ID: YOUR_CLIENT_ID" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json"
Exemple
cURL Login:
curl -X POST https://autentificare.scmc.ro/api/auth/login \
-H "Content-Type: application/json" \
-d '{"client_id":"YOUR_ID","client_secret":"YOUR_SECRET","email":"user@domain.ro","password":"parola"}'
cURL Verify:
curl -X GET https://autentificare.scmc.ro/api/auth/verify \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Client-ID: YOUR_CLIENT_ID"
cURL Schimbare parolă (self-service):
curl -X POST https://autentificare.scmc.ro/api/auth/change-password \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Client-ID: YOUR_CLIENT_ID" \
-H "Content-Type: application/json" \
-d '{"current_password":"parola_veche","password":"ParolaNouaSigura12!","password_confirmation":"ParolaNouaSigura12!"}'
Coduri eroare
| 200 | Succes |
| 401 | Token invalid, credențiale greșite |
| 403 | Acces interzis (site dezactivat, user fără acces) |
| 422 | Date invalide — JSON: {"message":"...","errors":{"camp":["..."]},"request_id":"..."}; mesajele sunt în limba setată de API_LOCALE (implicit engleză pentru integratori). |
| 500 | Eroare server |
Securitate
- Folosiți HTTPS întotdeauna.
client_secret– doar pe server, niciodată în frontend.- Token – păstrați în cookie HttpOnly sau session, nu în localStorage.
- La reverse proxy (Nginx, Apache), nu logați headere
Authorization,X-Client-Secretsau cookie-uri brute.
Dezactivare autentificare
Când administratorul dezactivează autentificarea pentru site-ul dvs., Login și Verify returnează 403. Niciun utilizator nu poate să se autentifice până când nu este repornită. Verificați GET /api/auth/status la fiecare încercare de login.
Versiune API
Endpoint-urile sunt disponibile și sub prefix /api/v2/auth/... (comportament identic cu /api/auth/...). Păstrați aceeași logică; v2 permite evoluții viitoare fără a întrerupe clienții vechi.
Răspunsul GET /api/auth/status include site_status și flags (catalog activ, login permis).
SSO cross-site hibrid (silent authentication)
Model: formular local pe fiecare app + sesiune browser centrală pe Gate. După login pe un site (ex. FlowSCMC), utilizatorul este autentificat automat pe celelalte (iHRM, Master Data) fără a reintroduce parola.
Site-uri SCMC — mapare cPanel → slug Gate
| App | User cPanel | Slug Gate | Redirect URI callback |
|---|---|---|---|
| FlowSCMC | flowscmc | flowscmc.ro | https://flowscmc.ro/auth/sso/callback |
| iHRM | ihrmro | aplicatia.ihrm.ro | https://aplicatia.ihrm.ro/auth/sso/callback |
| Master Data | masterdata | master-data.ro | https://master-data.ro/auth/sso/callback |
Dev: nou.master-data.ro, testez.ihrm.ro, dezvoltare.master-data.ro — slug și redirect URI distincte în panou Gate.
Flux 1 — Login pe site A
1. POST /api/auth/login (+ sso_return_url, ex. https://flowscmc.net/dashboard)
→ token + bootstrap_url (dacă SSO activ)
2. App salvează token în sesiune
3. Browser → GET /sso/bootstrap?code=... → sesiune Gate
4. Gate redirect la sso_return_url pe domeniul CLIENT (flowscmc.ro/.net/.eu/…)
FlowSCMC multi-domeniu
- Site Gate:
flowscmc.ro— SSO activ. Alias API:flowscmc.net,flowscmc.eu,flowscmc.com,flowscmc.org(acelașiclient_id) - Callback whitelist auto:
https://flowscmc.{ro,net,eu,com,org}/auth/sso/callback - Client:
X-Site-Slug= host vizitat;sso_return_url= dashboard pe același TLD
Flux 2 — Silent SSO pe site B
1. GET /login pe site B → middleware AttemptSilentSso
2. Redirect GET /sso/authorize?prompt=none&client_id=...&redirect_uri=...&state=...
3. Gate: sesiune activă → callback cu code | fără sesiune → error=login_required
4. GET /auth/sso/callback → POST /api/sso/token → token site B → dashboard
Endpoint-uri SSO
GET /sso/authorize— query: client_id, redirect_uri, state, site_slug, prompt (none= silent,login= formular Gate)POST /api/sso/token— grant_type=authorization_code, code, client_id, client_secret, redirect_uri, site_slugGET /sso/bootstrap?code=— activare sesiune Gate după login localGET /sso/logout?return=— logout federatPOST /api/auth/login— câmp opționalsso_return_url; răspuns:bootstrap_code,bootstrap_url
Configurare client (.env)
AUTH_CENTRAL_SSO_ENABLED=true
AUTH_CENTRAL_SSO_CALLBACK=/auth/sso/callback
AUTH_CENTRAL_SITE_SLUG=flowscmc.ro # sau aplicatia.ihrm.ro / master-data.ro
Sesiuni active (Platform API)
Token-urile API (api_tokens) reprezintă sesiunile autentificate per site. SCMC Control le afișează în Acces → Sesiuni active și permite revocarea.
GET /api/v2/platform/sessions?site_slug=flowscmc.ro— listă sesiuni active (user, IP, expiră, ultima utilizare)DELETE /api/v2/platform/sessions/{id}— revocă o sesiunePOST /api/v2/platform/sessions/revoke— body:{"site_slug":"...","email":"..."}sauuser_id
Autentificare: credențiale platformă Kernel (X-Client-ID + X-Client-Secret site Control). La revocare, app client deconectează utilizatorul la următoarea verificare GET /api/auth/verify.
SSO Keycloak (panou web)
Pentru autentificare în panoul central cu Keycloak, folosiți fluxul SSO din pagina de login. API-ul partenerilor rămâne pe /api/auth/*.
Arhitectură (rezumat)
Browser → SCMCGate (Laravel) → API partener
Keycloak → SCMCGate (SSO panou admin)
Partener → SCMCGate API → verificare token
SSO cross-site: Site A login → bootstrap Gate → Site B silent SSO (prompt=none)
SCMC Control → Platform API sessions → vizualizare / revocare sesiuni active
Variabile .env (go-live)
APP_URL,APP_KEY,APP_ENV=production- Conexiune DB principală,
SESSION_DRIVER - Keycloak:
KEYCLOAK_*dacă folosiți SSO METRICS_BEARER_TOKENpentru/internal/metrics/prometheus- Cron:
* * * * * php artisan schedule:run
CDN și asset-uri
Bootstrap și Font Awesome sunt încărcate de pe CDN în layout; pentru producție puteți trece la build local (Vite) și cache la edge.