OAuth 2.0 dan Keamanannya
OAuth 2.0 adalah protokol authorization yang memungkinkan aplikasi pihak ketiga mengakses resource pengguna tanpa mengetahui password-nya. Meskipun OAuth sudah matang, implementasi yang salah bisa membuka celah keamanan serius.
OAuth 2.0 Authorization Code Flow
// 1. Client mengarahkan user ke authorization server
GET https://auth.example.com/authorize?
response_type=code&
client_id=myapp&
redirect_uri=https://myapp.com/callback&
scope=read:profile&
state=random123 // WAJIB untuk mencegah CSRF
// 2. User login dan memberikan izin
// 3. Authorization server redirect ke callback dengan code
GET https://myapp.com/callback?code=AUTH_CODE&state=random123
// 4. Client menukar code dengan access token (server-side)
POST https://auth.example.com/token
{ "grant_type": "authorization_code", "code": "AUTH_CODE", ... }
Vulnerability Umum OAuth
1. Missing State Parameter (CSRF)
Tanpa state parameter, penyerang bisa memaksa korban menghubungkan akun mereka dengan akun penyerang:
// VULNERABLE: tanpa state
GET /authorize?response_type=code&client_id=app&redirect_uri=...
// AMAN: dengan state yang divalidasi
const state = crypto.randomBytes(16).toString("hex");
req.session.oauthState = state;
// Redirect ke authorize dengan state=...
// Di callback, validasi state === req.session.oauthState
2. Open Redirect
Jika redirect_uri tidak divalidasi secara ketat, penyerang bisa mengarahkan authorization code ke server mereka.
3. Token Leakage
- Jangan gunakan Implicit Flow (token di URL fragment) — sudah deprecated
- Gunakan Authorization Code Flow + PKCE untuk semua client
- Jangan simpan token di URL, localStorage, atau tempat yang bisa diakses JavaScript
PKCE (Proof Key for Code Exchange)
// PKCE menambahkan perlindungan untuk authorization code
// 1. Generate code_verifier (random string)
const verifier = crypto.randomBytes(32).toString("base64url");
// 2. Hash menjadi code_challenge
const challenge = crypto.createHash("sha256")
.update(verifier).digest("base64url");
// 3. Kirim challenge di authorize request
GET /authorize?...&code_challenge=xxx&code_challenge_method=S256
// 4. Kirim verifier di token request
POST /token { ..., code_verifier: verifier }
Best Practices OAuth
- Selalu gunakan state parameter dan validasi di callback
- Gunakan PKCE untuk semua client (bukan hanya public client)
- Validasi redirect_uri secara exact match
- Gunakan short-lived access tokens dengan refresh token
- Simpan token di HttpOnly cookie atau secure server-side storage