Nu folosi fluxurile Implicit și Resource Owner Password Credentials

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

Această practică se referă la evitarea grant-urilor implicit și Resource Owner Password Credentials (ROPC) în implementarea OAuth 2.0 sau OIDC. Grant-ul implicit a fost depreciat deoarece expune token-urile de acces direct în browser, facilitând furtul prin URL sau consolele web. ROPC este considerat nesigur deoarece cere aplicației să preia și să stocheze parolele utilizatorilor, eliminând stratul de securitate oferit de provider-ul de autentificare și creând un punct unic de eșec pentru credentiale. Ignorarea acestor recomandări te expune la riscuri majore de securitate, inclusiv atacuri de tip cross-site scripting (XSS) și compromiterea conturilor dacă baza ta de date este încălcată.

Cum o aplici

  1. Alege grant-ul corect: Pentru aplicații web moderne (SPA, React, Vue) sau mobile, folosește Grant-ul Authorization Code cu PKCE (Proof Key for Code Exchange). Pentru server-side applications, folosește Client Credentials dacă ai nevoie doar de acces la resurse proprii.
  2. Configurează providerul: Asigură-te că providerul tău de identitate (ex: Auth0, Keycloak, Azure AD) are dezactivate opțiunile pentru implicit și ROPC în setările aplicației tale.
  3. Implementează PKCE: Generarea unei chei temporare (code verifier) și a unui hash (code challenge) pe client previne interceptarea token-urilor în timpul redirecționării.
  4. Redirecționează, nu colectezi: Utilizatorul trebuie redirecționat către pagina de login a providerului, nu către formularul tău. După autentificare, providerul trimite un cod către callback-ul tău, pe care îl schimbi ulterior pentru token-uri.

Exemplu

Varianta greșită (ROPC - Nu face asta):

// Pericol: Aplicația ta primește parola direct
const response = await fetch('/oauth/token', {
  method: 'POST',
  body: new URLSearchParams({
    grant_type: 'password',
    username: user.email,
    password: user.password, // Parola circulă prin rețeaua ta
    client_id: 'my_client_id'
  })
});

Varianta corectă (Authorization Code + PKCE):

// 1. Generează code_verifier și code_challenge
const verifier = generateRandomString();
const challenge = await generateCodeChallenge(verifier);

// 2. Redirecționează utilizatorul la provider
window.location.href = `https://provider.com/authorize?response_type=code&client_id=ID&redirect_uri=CALBACK&code_challenge=${challenge}&code_challenge_method=S256`;

// 3. La returnare, schimbi codul pentru token folosind verifier-ul
const tokenResponse = await fetch('/token', {
  method: 'POST',
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: authCode,
    redirect_uri: CALLBACK,
    code_verifier: verifier, // Secretul nu a părăsit niciodată browserul
    client_id: 'my_client_id'
  })
});

Cum verifici

  • Audit de configurare: Verifică panoul de administrare al providerului de identitate pentru a confirma că doar authorization_code și client_credentials sunt activate.
  • Testare manuală: Încearcă să accesezi endpoint-ul de token cu grant_type=password. Ar trebui să primești o eroare unsupported_grant_type.
  • Analiză de trafic: Folosește instrumente precum Wireshark sau Chrome DevTools (Network tab) pentru a te asigura că parolele nu sunt trimise niciodată în corpul cererilor HTTP către serverul tău backend.

Greșeli frecvente

  1. Reutilizarea codului vechi: Copierea de snippet-uri de pe Stack Overflow care folosesc grant-uri depreciate fără a verifica contextul de securitate actual.
  2. Confuzia între token-uri: Credința că token-ul de acces este suficient de sigur pentru a fi stocat local fără protecția suplimentară oferită de PKCE.
  3. Ignorarea validării: Nevalidarea state parameter în fluxul authorization code, ceea ce permite atacuri CSRF chiar și cu grant-uri sigure.

Resurse gratuite

Alte subiecte din „Autentificare”