Güvenlik Best Practices

Production ortamı için Atlantic ID entegrasyonunda güvenlik kontrolü.


Pre-Production Checklist

✅ PKCE

  • [ ] Public client'larda PKCE zorunlu
  • [ ] S256 method kullanılıyor (plain değil)
  • [ ] Her request için yeni verifier
  • [ ] Verifier güvenli saklanıyor

✅ State & Nonce

  • [ ] State parametresi kullanılıyor (CSRF)
  • [ ] State server-side/session'da saklanıyor
  • [ ] Nonce kullanılıyor (ID token replay)
  • [ ] Kriptografik random generator

✅ HTTPS

  • [ ] Production'da sadece HTTPS
  • [ ] Valid SSL certificate
  • [ ] Redirect URI'ler HTTPS (localhost hariç)
  • [ ] TLS 1.2+ kullanılıyor

✅ Token Storage

  • [ ] Backend'de güvenli session storage
  • [ ] Frontend'de httpOnly cookie
  • [ ] LocalStorage KULLANILMIYOR
  • [ ] Token'lar asla URL'de değil

✅ Token Validation

  • [ ] ID token backend'de doğrulanıyor
  • [ ] İmza kontrol ediliyor (JWKS)
  • [ ] iss, aud, exp validate ediliyor
  • [ ] Client-side decode asla güvenilmiyor

✅ Client Secret (Confidential)

  • [ ] Secret environment variable'da
  • [ ] Git'e commit edilmemiş
  • [ ] Frontend'de yok
  • [ ] Production/dev farklı secret'lar

✅ Redirect URIs

  • [ ] Tüm URI'ler console'da kayıtlı
  • [ ] Wildcard yok (https://*.example.com ❌)
  • [ ] Exact match (trailing slash dikkat)
  • [ ] Open redirect vulnerability yok

✅ Scope Minimization

  • [ ] Sadece gerekli scope'lar isteniyor
  • [ ] offline_access gerçekten gerekli mi?
  • [ ] Kullanıcıya açık bilgilendirme

Common Vulnerabilities

1. Authorization Code Interception

Risk: Code URL'de yakalanabilir

Korunma:

  • ✅ PKCE kullan
  • ✅ HTTPS zorunlu
  • ✅ Short-lived codes (5 dk)

2. CSRF Attack

Risk: Saldırgan kendi code'unu kurbanın session'ına bağlayabilir

Korunma:

  • ✅ State parametresi
  • ✅ State server-side validate et
  • ✅ SameSite cookie attribute

3. Open Redirect

Risk: redirect_uri manipulation

Korunma:

  • ✅ Exact match kontrolü
  • ✅ Whitelist approach
  • ✅ No wildcard URIs

4. Token Leakage

Risk: Token'lar log'lara, referrer'a düşebilir

Korunma:

  • ✅ Never in URL/query params
  • ✅ Never in localStorage
  • ✅ httpOnly, secure cookies
  • ✅ Short-lived access tokens

5. XSS Attacks

Risk: JavaScript ile token çalınması

Korunma:

  • ✅ httpOnly cookies
  • ✅ Content Security Policy
  • ✅ Input sanitization
  • ✅ Modern framework kullan (React, Vue)

6. Replay Attacks

Risk: Eski token'ların yeniden kullanılması

Korunma:

  • ✅ Nonce (ID token'da)
  • ✅ Short token lifetime
  • ✅ Token rotation (refresh)

Token Security

Access Token

Storage:

// ✅ Good: httpOnly cookie
res.cookie('access_token', token, {
  httpOnly: true,
  secure: true, // HTTPS only
  sameSite: 'lax',
  maxAge: 900000 // 15 min
});

// ❌ Bad: localStorage
localStorage.setItem('access_token', token);

Usage:

// ✅ Good: Backend sends in header
fetch('/api/data', {
  credentials: 'include' // Sends cookie
});

// ❌ Bad: Frontend manually sends
fetch('/api/data', {
  headers: {
    'Authorization': `Bearer ${localStorage.getItem('token')}`
  }
});

Refresh Token

Rules:

  1. Server-side only (asla frontend'e verme)
  2. Database'de hash'lenmiş sakla
  3. Rotation kullan (her kullanımda yenile)
  4. Revocation mekanizması

Example:

// ✅ Good
app.post('/api/refresh', async (req, res) => {
  const refreshToken = req.session.refreshToken;

  // Validate & exchange
  const tokens = await atlanticId.refresh(refreshToken);

  // Save new refresh token
  req.session.refreshToken = tokens.refresh_token;

  // Send new access token
  res.cookie('access_token', tokens.access_token, {
    httpOnly: true,
    secure: true,
    maxAge: 900000
  });
});

Client Secret Protection

Environment Variables

// ✅ Good
const CLIENT_SECRET = process.env.ATLANTIC_ID_SECRET;

// ❌ Bad
const CLIENT_SECRET = 'sec_abc123def456';

.env File

# .env
ATLANTIC_ID_CLIENT_ID=cli_abc123
ATLANTIC_ID_CLIENT_SECRET=sec_def456
ATLANTIC_ID_REDIRECT_URI=https://myapp.com/callback

.gitignore:

.env
.env.local
.env.production

Secret Rotation

  1. Developer Console'da yeni secret oluştur
  2. Her iki secret da geçici olarak çalışır
  3. Tüm instancelarda yeni secret'a geç
  4. Eski secret'ı devre dışı bırak

Session Management

Session Security

// Express.js
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: true, // HTTPS only
    httpOnly: true,
    sameSite: 'lax',
    maxAge: 86400000 // 24 hours
  },
  store: new RedisStore({ /* ... */ })
}));

Session Fixation Prevention

// After successful login
req.session.regenerate((err) => {
  req.session.userId = user.id;
});

CORS Configuration

// ✅ Good: Whitelist
app.use(cors({
  origin: [
    'https://myapp.com',
    'https://www.myapp.com'
  ],
  credentials: true
}));

// ❌ Bad: Allow all
app.use(cors({
  origin: '*',
  credentials: true // Bu çalışmaz zaten
}));

Rate Limiting

Application Level

const rateLimit = require('express-rate-limit');

const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 min
  max: 5, // 5 attempts
  message: 'Too many login attempts'
});

app.post('/auth/callback', authLimiter, handleCallback);

Atlantic ID Level

Atlantic ID otomatik rate limiting uygular:

  • 100 req/min auth endpoints
  • 50 req/min token endpoint
  • 429 response → exponential backoff

Logging & Monitoring

What to Log

Log:

  • Login attempts (success/fail)
  • Token refresh events
  • Logout events
  • Failed verifications
  • Rate limit hits

Never Log:

  • Access tokens
  • Refresh tokens
  • ID tokens
  • Client secrets
  • Authorization codes
  • PKCE verifiers

Example

logger.info('User login', {
  userId: user.sub,
  clientId: 'cli_abc123',
  timestamp: Date.now(),
  // NO TOKENS!
});

Production Deployment

Pre-Launch

  1. [ ] Security audit yapıldı
  2. [ ] Penetration test yapıldı
  3. [ ] SSL certificate geçerli
  4. [ ] Secrets rotate edildi (dev→prod)
  5. [ ] Rate limiting test edildi
  6. [ ] Error handling test edildi
  7. [ ] Monitoring kuruldu
  8. [ ] Backup/recovery planı var

Post-Launch

  1. Monitor logs daily
  2. Review access patterns
  3. Track failed auth attempts
  4. Update dependencies
  5. Rotate secrets quarterly

Security Headers

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      connectSrc: ["'self'", "https://id.codeatlantis.com"]
    }
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true
  }
}));

Incident Response

Token Compromised

  1. Immediate:

    • Revoke all tokens for affected user
    • Force re-authentication
    • Log incident
  2. Investigation:

    • Check access logs
    • Identify breach source
    • Assess damage
  3. Remediation:

    • Rotate client secrets
    • Update security measures
    • Notify affected users (if required)

Code

// Revoke all user tokens
await atlanticId.revokeAllUserTokens(userId);

// Force logout
req.session.destroy();

// Log
logger.error('Token compromise detected', {
  userId,
  clientId,
  timestamp: Date.now()
});

Compliance

KVKK / GDPR

  • [ ] Kullanıcı onayı alınıyor
  • [ ] Data minimization (scope)
  • [ ] User data deletion API
  • [ ] Privacy policy link
  • [ ] Terms of service

PCI DSS (Eğer ödeme varsa)

  • [ ] Token'lar encrypted
  • [ ] Access logs tutluyor
  • [ ] Regular security audits
  • [ ] Incident response plan

Useful Tools

Testing

  • OWASP ZAP - Security scanner
  • Burp Suite - Web vulnerability scanner
  • jwt.io - JWT debugger

Monitoring

  • Sentry - Error tracking
  • DataDog - APM & monitoring
  • CloudFlare - DDoS protection

Sorunuz mu var? developers@codeatlantis.com