OAuth 2.0 bir authorization framework''üdür — uygulamaların 3. parti kaynaklara (Google, GitHub) kullanıcı adına erişmesini sağlar. OpenID Connect (OIDC) bunun üzerine authentication katmanı ekler. Modern web auth''un standardı budur. Bu yazı kavramları netleştirir ve Authorization Code Flow''u adım adım anlatır.

Roller

İlgili rehberler: SSL sertifikası nasıl alınır · OWASP Top 10 2026 · JWT güvenlik · SQL injection önleme · Parola hash (BCrypt, Argon2)

  • Resource Owner: Son kullanıcı
  • Client: Uygulamanız — kullanıcı adına hareket eder
  • Authorization Server: Kimlik sağlayıcı (Google, Auth0, Keycloak)
  • Resource Server: API (GitHub API, Google Drive API)

Flow Türleri

  • Authorization Code + PKCE: Modern web ve mobil için standart
  • Client Credentials: Server-to-server (UI yok)
  • Device Code: TV, CLI gibi browser''sız cihazlar
  • Implicit: Deprecated, asla kullanmayın
  • Password: Deprecated, asla kullanmayın

Authorization Code Flow (PKCE ile)

┌─────────┐  1. Login butonuna tıkla
│ Client  │ ────────────────────────────┐
│ (Web)   │                              ↓
└─────────┘              2. Browser redirect →
     ↑                 /authorize?client_id=X&redirect_uri=...
     │                 &code_challenge=HASH&state=RANDOM
     │                                    │
     │              ┌─────────────────────┴──┐
     │              │ Authorization Server    │
     │              │ (kullanıcı login olur)  │
     │              └─────────────────────┬──┘
     │                                    │
     │    3. Redirect back with code       │
     │ ←──────────────────────────────────┘
     │    /callback?code=XXX&state=RANDOM
     │
     │    4. Token exchange (server-side)
     └──────→ POST /token
              code=XXX&code_verifier=ORIGINAL
              → { access_token, refresh_token, id_token }

PKCE Neden Şart?

Public client (browser, mobile)''ın client_secret''ini güvenle saklayamazsınız. PKCE (Proof Key for Code Exchange): her login''de random bir code_verifier üret, onun SHA256 hash''ini code_challenge olarak /authorize''a gönder. Token exchange''te orijinal code_verifier''ı gösterince auth server doğrular.

// 1) PKCE challenge üret
import { randomBytes, createHash } from 'crypto';

const codeVerifier = randomBytes(32).toString('base64url');
const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');

// Session'da sakla
session.codeVerifier = codeVerifier;
session.state = randomBytes(16).toString('hex');

// 2) Redirect URL oluştur
const params = new URLSearchParams({
    response_type: 'code',
    client_id: CLIENT_ID,
    redirect_uri: REDIRECT_URI,
    scope: 'openid profile email',
    code_challenge: codeChallenge,
    code_challenge_method: 'S256',
    state: session.state
});
res.redirect(`https://auth.example.com/authorize?${params}`);

// 3) /callback endpoint
app.get('/callback', async (req, res) => {
    const { code, state } = req.query;
    if (state !== session.state) return res.status(400).send('Invalid state');

    // Token exchange
    const tokenRes = await fetch('https://auth.example.com/token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: new URLSearchParams({
            grant_type: 'authorization_code',
            code,
            redirect_uri: REDIRECT_URI,
            client_id: CLIENT_ID,
            code_verifier: session.codeVerifier
        })
    });
    const { access_token, id_token, refresh_token } = await tokenRes.json();
    // id_token → OIDC user info
    // access_token → API çağrıları
    // refresh_token → access_token yenilemek için
});

OIDC: id_token

OAuth sadece yetki verir, kim olduğunu söylemez. OIDC id_token (JWT) ile kullanıcı kimliğini taşır. Içinde: sub (user id), email, name, iss (issuer), aud (audience), exp (expiry).

import { jwtVerify, createRemoteJWKSet } from 'jose';

const JWKS = createRemoteJWKSet(new URL('https://auth.example.com/.well-known/jwks.json'));

const { payload } = await jwtVerify(id_token, JWKS, {
    issuer: 'https://auth.example.com',
    audience: CLIENT_ID
});
// payload.sub, payload.email, payload.name

// Kendi DB'nize kullanıcıyı kaydet veya getir
let user = await db.users.findOne({ oauthSub: payload.sub });
if (!user) {
    user = await db.users.create({
        oauthSub: payload.sub,
        email: payload.email,
        name: payload.name
    });
}
// Session veya JWT oluştur (kendi tokenın)

Scopes

Scope''lar access_token''ın hangi kaynaklara erişebileceğini belirler. Minimum gerekli scope''u iste — least privilege.

# OIDC temel
openid               # zorunlu — id_token için
profile              # name, picture
email                # email, email_verified

# Provider-specific
read:user            # GitHub
https://www.googleapis.com/auth/drive.readonly  # Google Drive

Refresh Token

async function refreshAccessToken(refreshToken) {
    const res = await fetch('https://auth.example.com/token', {
        method: 'POST',
        body: new URLSearchParams({
            grant_type: 'refresh_token',
            refresh_token: refreshToken,
            client_id: CLIENT_ID
        })
    });
    if (!res.ok) throw new Error('Refresh failed');
    return await res.json();  // yeni { access_token, refresh_token (rotated) }
}

// Access token expire olunca otomatik yenile
if (tokenExpiresAt < Date.now()) {
    const newTokens = await refreshAccessToken(session.refreshToken);
    session.accessToken = newTokens.access_token;
    session.refreshToken = newTokens.refresh_token;  // rotated
    session.tokenExpiresAt = Date.now() + newTokens.expires_in * 1000;
}
Uyarı
Refresh token rotation — auth server her kullanımda yeni refresh verir, eskiyi iptal eder. Eski refresh tekrar kullanılırsa kompromizasyon alarmı ver ve tüm oturumları sonlandır.

Güvenlik Kontrol Listesi

  • state parametresi CSRF için zorunlu
  • PKCE public client''ta zorunlu
  • HTTPS tüm endpoint''lerde
  • id_token signature ve iss/aud mutlaka doğrula
  • Refresh token HttpOnly cookie''de veya secure backend''de
  • Logout: front-channel veya back-channel — sessionId iptal

Sosyal Login Hızlı Kurulum

Tüm flow''u kendiniz yazmak yerine hazır library''ler: Passport.js (Node), NextAuth.js / Auth.js, Lucia Auth, Clerk, Supabase Auth. 10 satır config ile Google/GitHub/Apple login.

Web Güvenliği ve Uygulama Savunması

Modern web güvenliği katmanlı savunma (defense-in-depth) ile yapılır: TLS 1.3 ve HSTS ile şifreli iletişim, WAF (Web Application Firewall) ile OWASP Top 10 saldırılarına karşı koruma, BCrypt veya Argon2id ile parola hash'leme, JWT token'larında imza doğrulama (HMAC veya RSA), CSRF token + SameSite cookie ile cross-site istek koruması ve Content Security Policy ile XSS azaltma. SQL injection önleme için prepared statement, brute force için fail2ban veya rate limiting, DDoS koruması için Cloudflare/Anti-DDoS sağlayıcı zorunludur. Güvenlik açığı taraması (Burp Suite, OWASP ZAP) ve düzenli güvenlik denetimi; üretim ortamında veri sızıntısı ve hesap ele geçirme risklerini büyük ölçüde azaltır.

Auth sistemi entegrasyonu

OAuth, SSO ve Keycloak gibi identity provider kurulumu için iletişime geçin

WhatsApp