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
- 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.
- 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.
- 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.
- 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șiclient_credentialssunt activate. - Testare manuală: Încearcă să accesezi endpoint-ul de token cu
grant_type=password. Ar trebui să primești o eroareunsupported_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
- Reutilizarea codului vechi: Copierea de snippet-uri de pe Stack Overflow care folosesc grant-uri depreciate fără a verifica contextul de securitate actual.
- 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.
- Ignorarea validării: Nevalidarea
stateparameter în fluxul authorization code, ceea ce permite atacuri CSRF chiar și cu grant-uri sigure.
Resurse gratuite
Alte subiecte din „Autentificare”
- Folosește OAuth 2.1 și OpenID Connect, nu scheme de autentificare proprii
- Folosește fluxul Authorization Code cu PKCE pentru toți clienții
- Stochează parolele cu Argon2id sau bcrypt, niciodată în clar
- Oferă MFA și passkeys (WebAuthn) pentru conturile utilizatorilor
- Returnează mesaje generice la eșecul autentificării, fără enumerare de conturi
- Folosește token-uri de resetare a parolei unice, aleatorii și cu expirare scurtă
- Tratează cheile API ca secrete: scope limitat, rotație și revocare