Securitate
Ce trece prin browser, ce verificăm și ce faci dacă ceva merge prost.
Serverul tău semnează cu cheia privată o aserțiune de câteva sute de octeți despre utilizatorul logat. Ea trece prin browser și ajunge la noi, unde o verificăm înainte să scriem ceva în baza de date. Cheia privată nu pleacă de pe server.
Exemplul de mai jos e real. Cheia a fost generată acum, în browserul tău, iar verificarea folosește WebCrypto, aceeași criptografie ca pe server. Încearcă să o păcălești.
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImp3ayI6.eyJhdWQiOiJodHRwczovL2ZhY3R1cmFyZS5jaGFwcGEucm8i.q3Zk9mVhRSn0bT6kXw1Yc
{ "sub": "user_8842", "aud": "https://facturare.chappa.ro", "exp": "peste 5 min", "ori": "https://app.exemplu.ro", "scope": "documents:read documents:write" }
- Semnătura ES256 se potrivește cu cheia publică din antet
- E pentru facturare.chappa.ro, nu pentru altcineva
- E încă valabilă: trăiește cel mult 15 minute
- Nu a mai fost folosită
- Vine de pe pagina pentru care a fost semnată
Ce trece prin browser
În modurile cu utilizatorii tăi, aserțiunea trece prin pagina ta: în adresa iframe-ului sau printr-un mesaj. Așa funcționează orice autentificare unică între două site-uri, și nu e o slăbiciune, pentru că aserțiunea nu e o cheie și nu se poate refolosi:
- Semnată. Orice schimbare, fie și a unui drept din
scope, strică semnătura. - Scurtă. Trăiește cel mult 15 minute; de obicei o semnezi pentru 2 până la 5.
- De unică folosință. Al doilea drum cu același
jtie refuzat. - Pentru noi și pentru pagina ta. E semnată pentru
facturare.chappa.ro(aud) și, cuori, pentru originea paginii tale: iframe-ul o compară cu pagina care îl afișează.
După ce deschide sesiunea, aserțiunea nu mai contează. Sesiunea trăiește în iframe, pe domeniul nostru, ca un token în memorie, nu ca un cookie; scripturile paginii tale nu o pot citi, iar blocarea cookie-urilor terțe nu o încurcă.
Ce verificăm, în ordine
- Formatul: JWS compact, algoritmul doar ES256.
none, HS256, RS256 sau un antet cucritsunt refuzate, la fel o cheie care conține partea privată. - Semnătura, cu cheia publică din antet sau cu cea înregistrată pentru
kid. Integrarea e identificată de amprenta cheii, nu de ce scrie în aserțiune. - Cheia nu e revocată și integrarea nu e blocată.
- Destinatarul (
aud), timpul (iat,exp, cu 60 de secunde toleranță de ceas) șijtinefolosit. - Originea paginii, față de
oriși de originile permise din portal. - Abia apoi scriem: utilizatorul, firmele, sesiunea.
Dacă ceva merge prost
- Cineva rulează cod în pagina ta (XSS). Poate lua o aserțiune nefolosită și o poate folosi înaintea paginii, tot din pagina ta. Dar un astfel de cod controlează deja sesiunea utilizatorului în aplicația ta: aserțiunea nu îi dă nimic în plus față de ce poate face utilizatorul.
- Cineva prinde o aserțiune nefolosită în afara paginii tale. Verificarea originii o oprește într-un iframe de pe alt site; în rest o limitează viața de câteva minute și folosirea unică. De aceea nu le loga.
- Îți scapă cheia privată. O revoci din portal, iar sesiunile deschise cu ea se închid imediat. Dacă nu ai acces la portal, oricine are cheia o poate revoca (revocarea de urgență).
- Accesul la ANAF nu vine niciodată dintr-o aserțiune: conexiunea cu SPV cere autorizarea reală a firmei, cu certificatul ei (autorizarea ANAF).
Ce faci tu
- Cheia privată doar pe server (ideal KMS/HSM sau un secret manager), permisiuni 0600, nu în repository.
expscurt,jtiunic,subdin sesiunea ta, niciodată din input.- Folosește
oriși, în producție, originile permise din portal. - Verifică
event.originșievent.sourcela mesajele primite; trimite cu targetOrigin exact. - Nu loga aserțiunile; tratează-le ca pe parole cu viață scurtă.
- Sesiunea din iframe e un token în memoria iframe-ului (fără cookie-uri terțe): funcționează în Safari și cu blocarea cookie-urilor terțe.