Folosește OAuth 2.1 și OpenID Connect, nu scheme de autentificare proprii

Subiect din roadmap-ul Bune practici: securitatea API-urilor · parte din „Autentificare”

Această practică recomandă abandonarea soluțiilor de autentificare personalizate („homegrown”) în favoarea standardelor deschise, OAuth 2.1 și OpenID Connect (OIDC). Riscul principal este introducerea de vulnerabilități critice prin implementări incorecte ale logicii de tokenizare, gestionare a sesiunii sau validare a datelor. Ignorarea acestor standarde expune aplicația la atacuri precum CSRF, token leakage sau impersonare, în timp ce soluțiile standardizate oferă securitate testată comunitar și interoperabilitate nativă.

Cum o aplici

  1. Alege un Identity Provider (IdP): Folosește servicii mature precum Keycloak, Auth0, Azure AD sau Okta, care gestionează deja complexitatea OIDC/OAuth 2.1.
  2. Configurează fluxul corect: Pentru aplicații web moderne (SPA/React/Vue), utilizează Authorization Code Flow with PKCE. Evită Implicit Flow (periclitat) și Resource Owner Password Credentials (nu este recomandat pentru clienți publici).
  3. Validează token-urile la nivel de API: În backend-ul tău, configurează middleware-ul pentru a verifica semnătura (signature) și expirarea (exp claim) a JWT-urilor emise de IdP, nu pentru a gestiona sesiuni locale.
  4. Gestionează accesul granular: Utilizează scope-uri și resurse definite în OIDC pentru a controla permisiunile, nu logică custom în baza de date.

Exemplu

Varianta greșită (Custom Scheme): Stocarea parolelor hash-uite direct în baza de date și generarea manuală a unui token JWT fără verificare a semnăturii externe sau fără PKCE în client.

// GREȘIT: Validare simplistă, fără verificarea semnăturii emițătorului
if (req.headers.authorization === 'Bearer secret-token-123') {
    return next();
}

Varianta corectă (OIDC + PKCE): Clientul solicita un cod de autorizare, îl schimbă pentru un access_token și validarea se face verificând cheia publică a IdP.

// CORECT: Middleware care validează JWT-ul semnat de IdP
const jwt = require('express-jwt');
const jwksRsa = require('jwks-rsa');

const auth = jwt({
  secret: jwksRsa.expressJwtSecret({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 5,
    jwksUri: "https://your-domain.auth0.com/.well-known/jwks.json"
  }),
  audience: 'https://api.yourapp.com',
  issuer: 'https://your-domain.auth0.com/',
  algorithms: ['RS256']
});

app.get('/protected', auth, (req, res) => {
  res.send('Acces permis');
});

Cum verifici

  • Audit de configurare: Verifică dacă fluxul utilizat este authorization_code cu code_challenge (PKCE).
  • Teste de penetrare: Încearcă manipularea token-ului JWT (schimbarea algoritmului la none sau falsificarea semnăturii) pentru a vedea dacă API-ul respinge cererile.
  • Monitorizare: Configurează alerte pentru erori de validare a token-ului (401 Unauthorized) ca indicator al încercărilor de acces neautorizat.

Greșeli frecvente

  1. Utilizarea Implicit Flow: Este considerat nesigur deoarece expune token-urile în URL și history-ul browserului.
  2. Ignorarea PKCE: Fără Proof Key for Code Exchange, un interceptor poate intercepta codul de autorizare și poate schimba token-ul.
  3. Validarea locală a parolelor: Stocarea sau transmiterea parolelor utilizatorului către API-ul de resurse în loc de a delega complet autentificarea către IdP.

Resurse gratuite

Alte subiecte din „Autentificare”