Error Handling

Atlantic ID API hata kodları, açıklamaları ve çözüm önerileri.


Error Response Format

{
  "error": "invalid_request",
  "error_description": "Missing required parameter: code_challenge",
  "error_uri": "https://docs.id.codeatlantis.com/errors/invalid_request"
}
Alan Açıklama
error Error code (machine-readable)
error_description Human-readable açıklama
error_uri Dokümantasyon linki (opsiyonel)

OAuth Error Codes

invalid_request

Açıklama: Eksik veya hatalı parametreler

Örnekler:

  • client_id parametresi eksik
  • code_challenge gönderilmemiş (public client)
  • Geçersiz URL format

Çözüm:

// Tüm zorunlu parametreleri kontrol edin
const requiredParams = ['client_id', 'response_type', 'scope', 'redirect_uri'];
requiredParams.forEach(param => {
  if (!authUrl.searchParams.has(param)) {
    throw new Error(`Missing ${param}`);
  }
});

unauthorized_client

Açıklama: Client authentication başarısız

Nedenler:

  • Yanlış client_id
  • Yanlış client_secret (confidential)
  • Client devre dışı bırakılmış

Çözüm:

// Client credentials'ı kontrol edin
console.log('CLIENT_ID:', process.env.CLIENT_ID);
// Developer Console'dan doğrulayın

access_denied

Açıklama: Kullanıcı izni reddetti

Ne Zaman: Kullanıcı "İzin Verme" butonuna bastı

Handling:

const error = new URLSearchParams(window.location.search).get('error');

if (error === 'access_denied') {
  showMessage('Giriş iptal edildi. Tekrar denemek ister misiniz?');
}

unsupported_response_type

Açıklama: response_type desteklenmiyor

Neden: response_type=token veya response_type=id_token gönderilmiş

Çözüm: Sadece code desteklenir

authUrl.searchParams.set('response_type', 'code'); // Daima code

invalid_scope

Açıklama: Scope geçersiz veya izin yok

Örnekler:

  • Var olmayan scope: admin_access
  • Client'a verilmemiş scope

Çözüm:

// Sadece desteklenen scope'ları kullanın
const validScopes = ['openid', 'profile', 'email', 'phone', 'offline_access'];
const requestedScopes = 'openid profile email';

server_error

Açıklama: Atlantic ID'de sunucu hatası

HTTP Status: 500

Ne Yapmalı:

  1. Retry logic (exponential backoff)
  2. Kullanıcıya bilgi ver
  3. Destek ile iletişime geç (eğer devam ederse)
async function retryRequest(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)));
    }
  }
}

temporarily_unavailable

Açıklama: Servis geçici olarak kullanılamıyor

HTTP Status: 503

Ne Yapmalı: Birkaç dakika sonra tekrar dene

if (error.error === 'temporarily_unavailable') {
  setTimeout(() => {
    window.location.reload();
  }, 60000); // 1 dakika sonra
}

Token Endpoint Errors

invalid_grant

Açıklama: Grant geçersiz, expired, veya revoked

Nedenler:

  1. Authorization code zaten kullanılmış
  2. Code süresi dolmuş (5 dakika)
  3. PKCE verifier eşleşmiyor
  4. Yanlış redirect_uri

Çözüm:

// 1. Code tek kullanımlık
// İkinci kez kullanmayın

// 2. Hemen kullanın
const CODE_EXPIRY = 300; // 5 dakika

// 3. Aynı verifier'ı kullanın
const savedVerifier = sessionStorage.getItem('pkce_verifier');

// 4. Redirect URI tam eşleşmeli
const REDIRECT_URI = 'https://myapp.com/callback'; // trailing slash yok!

invalid_client

Açıklama: Client authentication başarısız

Nedenler:

  • Yanlış client_secret
  • Basic Auth hatalı encode edilmiş
  • Public client secret gönderiyor

Çözüm:

// Confidential client - Basic Auth
const auth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
headers: {
  'Authorization': `Basic ${auth}`
}

// Public client - NO secret
body: new URLSearchParams({
  client_id: clientId,
  // client_secret YOK!
})

unsupported_grant_type

Açıklama: Grant type desteklenmiyor

Desteklenen: authorization_code, refresh_token

Desteklenmeyen: password, client_credentials, urn:ietf:params:oauth:grant-type:device_code


HTTP Status Codes

400 Bad Request

Geçersiz istek parametreleri.

{
  "error": "invalid_request",
  "error_description": "Missing code_challenge"
}

401 Unauthorized

Token geçersiz veya expired.

// UserInfo endpoint
{
  "error": "invalid_token",
  "error_description": "The access token is invalid or expired"
}

Çözüm: Refresh token kullan

if (response.status === 401) {
  await refreshAccessToken();
  // Retry request
}

403 Forbidden

Yetersiz scope.

{
  "error": "insufficient_scope",
  "error_description": "The request requires higher privileges"
}

Çözüm: Gerekli scope'la yeniden authorize et


429 Too Many Requests

Rate limit aşıldı.

{
  "error": "rate_limit_exceeded",
  "error_description": "Too many requests. Try again in 45 seconds."
}

Headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1735686045
Retry-After: 45

Handling:

if (response.status === 429) {
  const retryAfter = response.headers.get('Retry-After');
  setTimeout(() => {
    retryRequest();
  }, retryAfter * 1000);
}

500 Internal Server Error

Sunucu hatası (Atlantic ID tarafında).

Ne Yapmalı:

  1. Retry (exponential backoff)
  2. Hata log'la
  3. Destek ile iletişime geç

503 Service Unavailable

Servis geçici olarak down.

Ne Yapmalı: Maintenance olabilir, birkaç dakika sonra dene.


Best Practices

1. User-Friendly Error Messages

function getUserMessage(error) {
  const messages = {
    'access_denied': 'Giriş iptal edildi.',
    'invalid_grant': 'Oturum süresi doldu. Lütfen tekrar giriş yapın.',
    'server_error': 'Bir hata oluştu. Lütfen daha sonra tekrar deneyin.',
    'rate_limit_exceeded': 'Çok fazla istek. Lütfen bekleyin.',
  };

  return messages[error.error] || 'Bir hata oluştu.';
}

2. Retry Logic

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url, options);

      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After') || 5;
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }

      if (response.status >= 500) {
        if (i === maxRetries - 1) throw new Error('Server error');
        await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)));
        continue;
      }

      return response;
    } catch (error) {
      if (i === maxRetries - 1) throw error;
    }
  }
}

3. Error Logging

function logError(error, context) {
  console.error('Atlantic ID Error:', {
    error: error.error,
    description: error.error_description,
    context: context,
    timestamp: new Date().toISOString(),
    user: getCurrentUser()?.id,
  });

  // Sentry, DataDog, vb. ile de gönderebilirsiniz
  // Sentry.captureException(error);
}

4. Graceful Degradation

try {
  await authenticateWithAtlanticId();
} catch (error) {
  if (error.error === 'temporarily_unavailable') {
    // Fallback authentication method
    showLocalLoginForm();
  } else {
    showErrorMessage(getUserMessage(error));
  }
}

Debugging Tips

1. Console'dan Test Etme

Developer Console'da "Test Credentials" ile test edin.

2. Verbose Logging

// Development'ta detaylı log
if (process.env.NODE_ENV === 'development') {
  console.log('Auth URL:', authUrl.toString());
  console.log('PKCE Verifier:', codeVerifier);
  console.log('State:', state);
}

3. JWT Debugging

jwt.io ile token'ları decode edin.

4. Network Tab

Browser DevTools → Network tab'da OAuth requestleri inceleyin.


Destek

Çözemediğiniz bir hata mı var?

İlgili: API Reference, Security