Flutter & Mobil İle İleri Düzey İki Faktörlü Kimlik Doğrulama Nasıl Yapılır?

Flutter & Mobil İle İleri Düzey İki Faktörlü Kimlik Doğrulama Nasıl Yapılır?
Flutter & Mobil İle İleri Düzey İki Faktörlü Kimlik Doğrulama Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

İleri düzey bir 2FA sistemi kurmak için hem Flutter tarafında hem de sunucu tarafında belirli araçlara ihtiyacınız vardır. Çalışmaya başlamadan önce aşağıdaki ortamın hazır olduğundan emin olun:

  • Flutter SDK: 3.24 ve üzeri sürüm (Dart 3.5+ destekli).
  • Güvenli Depolama: flutter_secure_storage paketi.
  • OTP Kütüphanesi: otp veya dart_otp paketi.
  • Sunucu Desteği: TOTP protokolünü (RFC 6238) destekleyen bir backend (Node.js, Go veya Python).
  • QR Kod Okuyucu: mobile_scanner paketi.

Adım 1: Güvenli Anahtar Üretimi ve Sunucu Entegrasyonu

2FA sürecinin ilk adımı, sunucu tarafında kullanıcıya özel bir "gizli anahtar" (secret key) oluşturmaktır. Bu anahtar, QR kod olarak kullanıcıya sunulur. Aşağıdaki kod, sunucudan gelen gizli anahtarı nasıl güvenli bir şekilde işleyeceğinizi gösterir.


// Sunucudan gelen secret key'i güvenli alanda saklama
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

final storage = const FlutterSecureStorage();

Future saveSecretKey(String secret) async {
  // Veriyi şifreli bir şekilde cihazın anahtar zincirine (KeyChain/Keystore) yazar
  await storage.write(key: 'user_2fa_secret', value: secret);
}

Bu işlem, gizli anahtarın cihazın işletim sistemi tarafından sağlanan donanımsal güvenlik katmanlarında (iOS Keychain veya Android Keystore) saklanmasını sağlar. Asla bu anahtarı SharedPreferences veya düz metin dosyalarında tutmayın.

Adım 2: Flutter ile QR Kod Okuma ve Doğrulama

Kullanıcının Google Authenticator veya benzeri bir uygulama ile tarayacağı QR kodu, aslında bir URI şemasıdır. Flutter uygulamanızda bu işlemi gerçekleştirmek için mobile_scanner paketini kullanabilirsiniz.


// QR kod tarama fonksiyonu
void onDetect(BarcodeCapture capture) {
  final List barcodes = capture.barcodes;
  for (final barcode in barcodes) {
    debugPrint('Taranan URI: ${barcode.rawValue}');
    // Burada alınan URI'yi parse ederek secret key'i çıkartın
  }
}

QR kodu taradıktan sonra, elde edilen veriyi doğrulamak için dart_otp paketini kullanarak yerel olarak bir deneme kodu oluşturabilirsiniz. Bu, kullanıcıya işlemin başarılı olduğunu göstermek için kritik bir adımdır.

Adım 3: TOTP Algoritması ile Kod Üretimi

TOTP, zaman bazlı çalıştığı için cihaz saatine bağımlıdır. Sunucu ve cihaz arasındaki zaman farkı, doğrulama hatalarına yol açabilir. Bu nedenle, kod üretirken zaman senkronizasyonunu yönetmek önemlidir.


import 'package:otp/otp.dart';

String generateCurrentOTP(String secret) {
  return OTP.generateTOTPCode(
    secret,
    DateTime.now().millisecondsSinceEpoch,
    algorithm: Algorithm.SHA1,
    isGoogle: true,
  ).toString();
}

Bu fonksiyon, o anki milisaniye değerini kullanarak 6 haneli bir kod üretir. isGoogle: true parametresi, Google Authenticator standartlarıyla uyumluluğu garanti eder.

Adım 4: İleri Düzey Güvenlik: Biyometrik Doğrulama

Sadece 2FA kodu yeterli değildir. Uygulamanızın güvenliğini artırmak için 2FA kodunu girmeden önce cihazın biyometrik (parmak izi veya yüz tanıma) verisini istemek, "İleri Düzey" bir güvenlik katmanıdır.


import 'package:local_auth/local_auth.dart';

final LocalAuthentication auth = LocalAuthentication();

Future authenticateUser() async {
  return await auth.authenticate(
    localizedReason: '2FA kodunu girmek için kimliğinizi doğrulayın',
    options: const AuthenticationOptions(biometricOnly: true),
  );
}

Bu yöntem, cihaz çalınsa bile yetkisiz kişilerin 2FA kodunu görmesini engeller. Biyometrik veriler asla uygulamanızın sunucusuna gönderilmez; sadece cihazın yerel API'si ile etkileşime girilir.

Karşılaştırma: 2FA Yöntemleri

Yöntem Avantaj Dezavantaj
SMS 2FA Kolay kullanım SIM swap saldırılarına açık
TOTP (Authenticator) Çevrimdışı çalışır Cihaz kaybında yedekleme gerekir
Push Bildirim En güvenli deneyim İnternet bağlantısı zorunlu

Adım 5: Hata Yönetimi ve Kullanıcı Deneyimi

2FA süreçlerinde en sık karşılaşılan hata, "Invalid Code" (Geçersiz Kod) hatasıdır. Bu genellikle cihaz saatinin yanlış olmasından kaynaklanır. Kullanıcıya saati otomatik güncellemesi gerektiğini bildiren bir uyarı göstermek, destek yükünüzü azaltır.


// Hata yakalama bloğu örneği
try {
  await verifyCodeOnServer(userCode);
} on ServerException catch (e) {
  if (e.code == 'INVALID_TIME') {
    showDialog(context: context, builder: (_) => TimeSyncErrorDialog());
  }
}
Kritik Güvenlik Uyarısı: Üretim ortamında (production) asla debugPrint gibi fonksiyonlarla kullanıcıların gizli anahtarlarını veya tokenlarını konsola yazdırmayın. Ayrıca, 2FA kod giriş denemelerini sınırlayın (Rate Limiting); aksi takdirde kaba kuvvet (brute-force) saldırılarına kapı aralamış olursunuz.

Sıkça Sorulan Sorular

TOTP kodları neden bazen çalışmıyor?

En yaygın neden cihazın saat ayarlarının "Otomatik" modda olmamasıdır. TOTP, sunucu saati ile cihaz saatinin senkronize olmasına dayanır.

Kullanıcı telefonunu kaybederse ne yapmalı?

Uygulamanızda mutlaka "Yedek Kodlar" (Backup Codes) oluşturun. Kullanıcıya ilk kurulumda bu kodları bir yere not etmesini hatırlatın.

Flutter Web üzerinde 2FA güvenli mi?

Web üzerinde flutter_secure_storage kullanımı, tarayıcı tabanlı depolama (IndexedDB) kısıtlamaları nedeniyle mobil kadar güvenli değildir. Web için daha sıkı sunucu taraflı oturum yönetimi gereklidir.

Biyometrik doğrulama zorunlu mu?

Zorunlu değildir ancak bankacılık veya hassas veri içeren uygulamalar için "en iyi uygulama" (best practice) olarak kabul edilir.

Sunucu taraflı doğrulama nasıl yapılır?

Sunucuda speakeasy veya otplib gibi kütüphaneler kullanarak, cihazdan gelen kodu sunucudaki gizli anahtar ile karşılaştırmanız gerekir.

2FA Sistemlerinde Performans Optimizasyonu ve Önbellekleme

İleri düzey 2FA uygulamalarında, özellikle yüksek trafikli sistemlerde, sunucu tarafındaki doğrulama süreçleri darboğaz oluşturabilir. TOTP (Time-based One-Time Password) hesaplamaları matematiksel olarak basit olsa da, veritabanı sorguları ve şifrelenmiş anahtarların çözülmesi (decryption) işlemciyi yorabilir. Performansı artırmak için aşağıdaki stratejileri izleyebilirsiniz:

  • Redis ile Önbellekleme: Kullanıcının gizli anahtarını (secret key) her seferinde veritabanından çekmek yerine, Redis gibi bir in-memory veri deposunda şifreli olarak tutun.
  • Zaman Aralığı Toleransı: Kullanıcıların cihaz saatleri ile sunucu saati arasındaki milisaniyelik farkları yönetmek için 30 saniyelik "drift" (kayma) penceresi kullanın.
  • Asenkron Doğrulama: 2FA doğrulama isteğini ana iş parçacığından ayırarak, sunucunun yanıt süresini optimize edin.

Örnek: Redis ile Güvenli Anahtar Erişimi

Aşağıdaki örnekte, bir kullanıcının gizli anahtarının Redis üzerinden nasıl hızlıca doğrulanabileceğini görebilirsiniz:

// Node.js/Express örneği: Redis üzerinden anahtar doğrulama
async function verifyUserSecret(userId, providedToken) {
    const secret = await redis.get(`2fa_secret:${userId}`);
    if (!secret) throw new Error("Anahtar bulunamadı.");

    const isValid = totp.verify({
        token: providedToken,
        secret: decrypt(secret), // Şifreli anahtarı çöz
        window: 1 // 30 saniyelik sapma payı
    });
    
    return isValid;
}

2FA Entegrasyonunda Sık Karşılaşılan Hata Ayıklama Senaryoları

Geliştirme sürecinde en çok karşılaşılan sorunlar genellikle "saat senkronizasyonu" ve "base32 kodlama" hatalarıdır. Uygulamanızın üretim ortamında sorunsuz çalışması için şu hata ayıklama adımlarını izleyin:

  1. Saat Kayması (Clock Drift): Kullanıcının cihaz saati otomatik modda değilse, TOTP kodları geçersiz sayılır. Uygulamanızda kullanıcıyı "Ayarlar > Tarih ve Saat > Otomatik" seçeneğini kontrol etmesi için yönlendiren bir uyarı mekanizması kurun.
  2. Base32 Hataları: Gizli anahtarlar mutlaka Base32 formatında olmalıdır. Eğer anahtarınız geçersiz karakterler içeriyorsa, kütüphaneniz hata verecektir.
  3. Kod Tekrarı (Replay Attack): Bir kez kullanılan TOTP kodunun tekrar kullanılmasını engellemek için, başarılı doğrulama sonrası o kodun "kullanıldı" (used) işaretini veritabanında saklayın.
İpucu: Test aşamasında, sunucu tarafındaki zamanı manuel olarak 30 saniye ileri veya geri alarak, uygulamanızın "drift" toleransını test edin. Bu, gerçek dünya senaryolarında kullanıcı şikayetlerini %80 oranında azaltacaktır.

Test Senaryosu: Geçersiz Kod Denemesi

Uygulamanızın dayanıklılığını test etmek için aşağıdaki gibi bir birim testi (unit test) kurgulayın:

test('Geçersiz 2FA kodu reddedilmeli', () => {
  const secret = 'JBSWY3DPEHPK3PXP'; // Örnek anahtar
  const invalidToken = '000000';
  
  const result = verifyTotp(invalidToken, secret);
  
  expect(result).toBe(false);
});

Sonuç

Flutter ile ileri düzey iki faktörlü kimlik doğrulama sistemi kurmak, uygulamanızın güvenliğini profesyonel seviyeye taşır. Bu rehberde, gizli anahtarların güvenli saklanmasından, biyometrik entegrasyona ve TOTP algoritmasının doğru kullanımına kadar kritik adımları öğrendiniz. Bir sonraki adım olarak, uygulamanızda "Push-based 2FA" sistemini (kullanıcıya onay bildirimi gönderme) araştırmanızı öneririm.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Uygulamanızın canlıya alınmadan önce mutlaka sızma testlerinden geçirilmesi ve güncel güvenlik kütüphanelerinin kullanılması tavsiye edilir. Yazılım güvenliği sürekli değişen bir süreçtir; paketlerinizi düzenli olarak güncel tutun.
Bu yazıya tepkinizi paylaşın:
Selin Korkmaz

Dijital yayıncılık dünyasında ev geliştirme ve kendin yap projeleri üzerine uzmanlaştım. Adım adım rehberler hazırlayarak kullanıcıların teknik becerilerini geliştirmelerine yardımcı oluyorum.

Yorumlar (0)

Yorum Yaz