Türkiye için tasarlanmış SMS-OTP altyapısı. Mevcut auth yapınıza iki endpoint'le bağlanır.
Evraksız, beklemesiz — hemen başlayın. Başlık onayı, BTK süreci, operatör anlaşması gerekmez; SMS'i biz değil, kullanıcınız kendi hattından gönderir. API anahtarınızı alın, çağırın.
Veri Türkiye'de kalır. Numara, kod, oturum — hepsi İstanbul'daki altyapımızda işlenir; kayıtlarda maskelenir, işi bittiği anda silinir.
Suistimale kapalı. Dışarıya asla SMS göndermeyiz: SMS bombardımanına yapısal bağışıklık, gönderici bazlı hız sınırı, ön ödemeli kredi. Faturanız patlamaz.
İlk 250 başarılı doğrulama ücretsiz — kredi kartı gerekmez.
curl -X POST https://otp.mioe.com.tr/auth/init \ -H "X-API-Key: $API_KEY" \ -d '{ "phone": "+905xxxxxxxxx" }' # → { "code": "WXKZ", "otp": "482910", # "sessionId": "1cce6791…" }
verified callback# Kullanıcı kodu SMS'le gönderince: POST /sms-login/cb X-Login-Signature: t=1746635012,v1=8c5d… { "type": "verified", "phone": "+905321112233" }
Başlık onayı, BTK süreci, operatör API entegrasyonu — bu modelde hiçbiri
size düşmez: dışarıya SMS göndermiyoruz; numarayı ve operatör tarafını biz
işletiyoruz. Siz yalnızca iki ucu bağlayın — /auth/init'i çağırın,
imzalı verified callback'ini karşılayın. 250 doğrulamalık ücretsiz
denemeyle dakikalar içinde canlıya çıkın; Better Auth gibi hazır auth
çözümlerine doğrudan uyar.
Doğrulama verisi — numara, kod, oturum — İstanbul'daki altyapımızda işlenir ve saklanır; yedekler dahil yurt dışına çıkmaz, KVKK Madde 9 kapsamında yurt dışı aktarımı hiç doğmaz. Üstelik veri en az düzeyde tutulur: kayıtlarda numaralar maskelenir, işi biten oturumlar en geç 60 dakika içinde silinir. KVKK Aydınlatma Metni ve Veri İşleme Sözleşmesi hazırdır.
Sistem kendi başına asla SMS göndermez — kötüye kullanılabilecek bir "kod gönder" ucu yoktur; SMS bombardımanı ve toll fraud yapısal olarak imkânsızdır. Gelen SMS tarafında operatör IP allowlist'i, gönderici bazlı deneme sınırı ve HMAC imzalı callback'ler yerleşiktir. Krediler ön ödemelidir: bir gecede sürpriz faturayla uyanmazsınız.
Klasik SMS-OTP'de kodu kullanıcıya biz yollarız, kullanıcı da ekrana yazar —
oysa ekrana yazılan bir kod paylaşılabilir, ele geçirilebilir, oltalanabilir.
Biz yönü tersine çevirdik: kodu sizin ekranınızda gösteriyoruz;
kullanıcı onu kendi telefonundan kısa numaramıza SMS olarak gönderiyor.
Mesaj gerçekten o hattan çıkmadıkça doğrulama kabul edilmez — asıl güvenlik
tam burada. Mobil operatör, göndericinin o numara olduğuna şahitlik eder; biz de
oturumu eşleştirip uygulamanıza HMAC-SHA256 imzalı bir
verified webhook'u iletiriz.
Karttaki kodu gösterilen numaraya göndermek için mobilde SMS gönder düğmesine dokunun; masaüstünde QR kodu telefonunuza okutun.
Mobil ağ, SMS'in bu numaradan geldiğine şahitlik etti. Tarayıcı kaynaklı hiçbir alan bu zincirde yer almadı. Bu numara yalnızca bu oturumda, yalnızca bu ekranda gösteriliyor — herkese açık değil.
60 saniye içinde eşleşen bir SMS ulaşmadı. Yeni bir kod alıp tekrar deneyebilirsiniz.
Bağlantıda bir sorun oluştu.
Form tabanlı OTP'de kullanıcı kodu okur ve ekrana yazar. Biz işin yönünü çeviriyoruz — mobil operatör, kullanıcının kim olduğuna doğrudan şahitlik ediyor.
POST /auth/init. Yanıt: 4 harfli prefix + 6 haneli OTP + 60 sn ömürlü oturum kimliği.
Ekrandaki WXKZ 482910 kombinasyonunu kısa numaraya gönderir — bu gönderim, kimliğinin ispatıdır.
GSM operatörü (veya seçtiğiniz sağlayıcı) bize POST eder. Prefix + OTP eşleşirse oturum doğrulanır.
callback_url'nize yalnızca verified — sessionId ve doğrulanan phone birlikte, HMAC imzalı. Eşleşme olmazsa hiçbir şey göndermeyiz.
SMS'in göndericisini mobil ağ belirler — form değil. Tarayıcıdan gelen hiçbir bilgiye güvenilmez. Bu, telefon doğrulamasını sahteciliğe yapısal olarak kapatır.
Her eşleşme sorgusu expires_at > now ister; 60 saniyelik pencere dolduğunda OTP
sunucu tarafında eşleşmeyi bırakır ve silinir — ne saat kayması ne de açık unutulmuş oturum kalır.
Backend'iniz hiçbir form alanına güvenmez. Sadece X-Login-Signature başlığını
webapp'ınıza özel HMAC secret'la doğrular — gövdenin doğruluğuna biz kefiliz.
Telefon doğrulaması ancak sahtesi üretilemiyorsa işe yarar. Bu yüzden tarayıcının söylediği hiçbir şeye değil, mobil operatörün şahitliğine güveniyoruz.
Korumasız bir ters OTP'nin, klasik (sistemin SMS gönderdiği) OTP'ye göre yapısal olarak daha geniş bir sahtecilik yüzeyi vardır — çünkü kimlik ispatı, operatörün ilettiği bir iddiaya dayanır. Biz bu yüzeyi, her üretim ortamında gerçekten çalışan dört katmanla kapatıyoruz: operatörün doğrulanmış ağına kilitli IP allowlist, ayrı bir paylaşılan header secret, gönderici numarası başına deneme sınırı ve HMAC imzalı geri çağrılar. Sonuç: klasik OTP'nin zayıf noktalarını taşımayan, daha güvenli bir sistem.
| Risk / kriter | Klasik OTP (SMS ile gönderim) | Korumasız ters OTP (sertleştirme yok) | Bizim sistemimiz |
|---|---|---|---|
| Kimlik ispatı nereye dayanır | Kullanıcının kodu doğru okuyup tarayıcıya yazması | Operatörün "bu SMS bu numaradan geldi" şahitliği — doğrulanmamış | Aynı şahitlik + o iddianın gerçekten operatörün kendi ağından geldiğinin doğrulanması |
| Sahte webhook / API isteğiyle backend'i kandırma | Uygulanamaz — böyle bir "kimden geldi" güven noktası yok | Ucuz saldırı — secret URL'i bilen herkes sahte istek atabilir | Kapalı — yalnızca operatörün doğrulanmış IP aralığından, ayrıca doğru paylaşılan token'la gelen istekler kabul edilir |
| Deneme / brute-force / spoof probing | Genelde hız sınırlama var, uygulamaya bağlı değişir | Yok | Var — gönderen numarası başına deneme penceresi, eşik aşılınca otomatik durdurma |
| Gerçek zamanlı oltalama (OTP-relay dolandırıcılığı) | Yüksek risk — bugün SMS-OTP ele geçirmelerinin çoğu bu yolla oluyor | Daha düşük — kodu yazmak yerine aktif SMS göndermek gerekir | Daha da düşük — üstüne tek kullanımlık kod + sunucu tarafında kesin uygulanan 60 saniyelik pencere; ele geçse bile hızla geçersizleşir |
| SMS bombardımanı / toll fraud (rastgele numaraya SMS bastırma) | Var — "kod gönder" uç noktası kötüye kullanılıp maliyet/taciz yaratabilir | Yapısal olarak bağışık | Yapısal olarak bağışık — sistem hiçbir zaman kendi inisiyatifiyle SMS göndermez |
| Geri çağrı bütünlüğü / tekrar oynatma | Uygulamaya bağlı, genelde zayıf | Garanti yok | HMAC-SHA256 imzalı ve zaman damgalı geri çağrı, tek kullanımlık OTP |
| SIM-swap / SS7 mesaj yönlendirme | Klasik zayıf nokta — mesaj başka bir cihaza sessizce yönlendirilebilir | Benzer operatör seviyesi risk | Hiçbir OTP modelinin tek başına ortadan kaldıramadığı tek katman — ama IP allowlist + hız sınırı bunu HTTP seviyesinde istismar etmeyi de zorlaştırır |
| Savunma katmanları (özet) | Genelde yalnızca hız sınırlama + captcha | Yok | Operatör IP allowlist'i · paylaşılan header secret · gönderici bazlı hız sınırı · HMAC imzalı geri çağrı · kiracı başına izolasyon |
Bu sertleştirmelerle birlikte ters yönlü OTP, klasik (SMS gönderen) OTP'den daha güvenlidir. Korumasız ters OTP'nin tek gerçek açığı — webhook/API sahteciliği — operatörün doğrulanmış ağına kilitli IP allowlist ve ayrı bir paylaşılan token ile pratikte kapatılmıştır; kalan tek risk katmanı (operatör seviyesi SIM-swap/SS7) zaten klasik OTP'nin de taşıdığı bir risktir.
Buna karşılık ters yönlü OTP, klasik modelin gerçek dünyada en çok istismar edilen iki zayıf noktasına — gerçek zamanlı OTP oltalamasına (phishing) ve SMS bombardımanı / toll fraud'a — karşı yapısal olarak bağışık ya da çok daha dirençlidir. Aynı operatör seviyesi riski taşırken, klasik OTP'nin taşıdığı bu iki ek riski taşımıyoruz — üstelik dört bağımsız savunma katmanıyla.
Webapp'ınızı oluştururken hangisini kullanacağınızı seçersiniz; sonradan değiştirmek tek tıklama.
4 harfli prefix, tüm webapp'ları aynı kısa numarada toplar.
<prefix> <otp> yazar. Toplam 11 karakter.Numara doğrudan webapp'ınıza bağlıdır, prefix gerekmez.
Twilio, Vonage veya kendi SMSC'nizi webapp'ınıza özel inbound URL'ine bağlayın.
Bir uca /auth/init'i çağırıyorsunuz, diğer uçta bizden imzalı bir POST bekliyorsunuz.
POST /auth/init HTTP/1.1 Host: otp.mioe.com.tr X-API-Key: lvsr_a3f…b21 Content-Type: application/json { "phone": "+905321112233" }
sessionId, code (prefix), otp ve
dedicated modda inboundNumber döner.
POST /sms-login/cb HTTP/1.1 X-Login-Signature: t=1746635012,v1=8c5d… Content-Type: application/json { "type": "verified", "sessionId": "1cce6791…", "phone": "+905321112233", "verifiedAt": "2026-05-07T16:00:42Z" }
v1 == HMAC_SHA256(secret, t + "." + rawBody) —
sabit zamanlı kıyaslama şart. Kullanıcının oturumunu callback'teki
phone ile açın, istemcinin bildirdiği
numarayla değil — oturum → numara bağını biz imzalıyoruz.
Kullanıcıya OTP kodunu gösterdikten sonra SMS göndermeyi kolaylaştırmanın en iyi yolu masaüstünde QR kodu, mobilde SMS butonu sunmaktır. Yukarıdaki canlı demo da bu yaklaşımı kullanır.
Masaüstü tarayıcılarda kullanıcı telefonuyla QR kodu okutarak SMS uygulamasını numara ve mesaj doldurulmuş halde açar. Tek adımda göndermeye hazır.
Mobil cihazlarda <a href="sms:…"> bağlantısı
telefonun SMS uygulamasını doğrudan açar. Kullanıcı sadece
"Gönder"e basar.
Android kamera uygulamaları sms: protokolünü doğrudan
açamaz. QR'a HTTPS yönlendirme linki koyun; sayfa
açılınca sms:'e yönlendirir.
sms: şeması// SMS URI formatı: sms:+90XXXXXXXXXX?body=WXKZ%20482910 // HTML'de kullanımı: <a href="sms:+90..?body=WXKZ%20482910"> SMS gönder </a> // JS ile oluşturmak: var smsUri = 'sms:' + number + '?body=' + encodeURIComponent( code + ' ' + otp );
?body= veya ?&body= — iOS ve Android'in
her ikisi de bu formatı kabul eder.
// QR içine konan URL (sms: değil!): https://yourapp.example/sms-redirect ?to=+90XXXXXXXXXX&body=WXKZ%20482910 // Yönlendirme sayfasının JS'i: var p = new URLSearchParams(location.search); var uri = 'sms:' + encodeURIComponent(p.get('to')) + '?body=' + encodeURIComponent(p.get('body')); // Otomatik yönlendir: window.location.href = uri;
sms: URI →
SMS uygulaması açılır.
navigator.userAgent ile mobil/masaüstü ayırın. Mobilde SMS butonu, masaüstünde QR gösterin.
QR kodu içine sms: URI'si değil, kendi sitenizde bir HTTPS yönlendirme sayfası URL'i koyun. Android kamera uygulamaları sms: protokolünü tanımaz.
/auth/init çağrısını backend proxy'niz üzerinden yapın. API anahtarı yalnızca sunucu tarafında kalmalıdır.
Doğrulama sonucu imzalı callback ile backend'inize ulaşır, tarayıcıya değil. Bunu kendi arayüzünüze nasıl yansıtacağınız tamamen size kalmıştır — bu entegrasyonun kapsamı dışındadır.
Gelen SMS'in göndericisini mobil ağ belirler. Tarayıcıdan gelen hiçbir alan bu zincirde yer almaz.
Her webhook X-Login-Signature taşır. Backend, ham gövdeyi sizin secret'ınızla doğrulayana kadar olayı gerçek kabul etmez.
verified geri çağrısı sessionId ve doğrulanan phone'u birlikte, imzanın altında taşır. Kullanıcının oturumunu bu imzalı numarayla açarsınız; istemci "hangi numara doğrulandı" diyemez, dolayısıyla kendi numarasını doğrulatıp başkasının numarasını sahiplenemez.
API key, HMAC secret, prefix ve callback URL tek bir kiracıya bağlıdır. Çapraz eşleşme yapısal olarak imkânsız.
İmza Unix zaman damgasına bağlanır; ±5 dakikalık pencere önerilir. Her OTP tek seferliktir, eşleştiği an geçersizleşir.
Süre sunucu tarafında uygulanır: her eşleşme sorgusu expires_at > now ister, pencere dolunca OTP eşleşmeyi bırakır ve silinir. Kullanıcı tarafında hiçbir hile süreyi uzatamaz.
Aynı telefon için yeni bir /auth/init, önceki oturumu sessizce failed olarak işaretler — eski kod o anda geçersizleşir.
Her dilde örnek kod timingSafeEqual / hash_equals kullanır — kendiniz == ile karşılaştırmayın.
API anahtarı ve HMAC secret yalnızca oluşturma veya yenileme anında görünür. Sızması hâlinde tek adımda yenilenebilir.
Tüm hesap parolaları endüstri standardı Argon2id ile özetlenir — OWASP Parola Saklama kılavuzunun asgari profilini birebir karşılar. Hiçbir parola düz metin ya da geri çevrilebilir biçimde tutulmaz.
Parolalar Argon2id ile özetlenir: m=19 MiB · t=2 · p=1 —
OWASP 2023 asgari profili. Hafıza-zorlu (memory-hard) tasarım, çalınan bir veritabanını
GPU/ASIC ile toplu kırmayı ekonomik olmaktan çıkarır.
Her parola için 16 baytlık benzersiz, CSPRNG üretimi tuz kullanılır; aynı parolalar bile farklı özetlere düşer. Doğrulama sabit zamanlı yapılır — zamanlama yan kanalı yok.
Maliyet parametreleri özetin içine gömülüdür. Standart yükseldiğinde eşiği artırmanız yeterli; mevcut kayıtlar bir sonraki girişte sessizce yeni profile yükseltilir — kimse kilitlenmez, parola sıfırlaması gerekmez.
Kimlik doğrulama katmanının tamamı tek bir denetlenebilir kripto modülü üzerine kuruludur.
OWASP parametreleriyle; PHC formatında, parametreler özetle birlikte saklanır.
İmzalı webhook geri çağrıları aynı modülde üretilir ve sabit zamanlı doğrulanır.
Oturum ve parola sıfırlama token'ları veritabanında yalnızca hash'lenmiş halde tutulur.
OTP'ler, tuzlar ve token'lar crypto.getRandomValues CSPRNG ile üretilir.
timingSafeEqual ile parola ve imza karşılaştırmalarında zamanlama sızıntısı yok.
Reddetme örneklemesiyle (rejection sampling) üretilen kodlarda modulo yanlılığı bulunmaz.
İlk 250 doğrulama ücretsiz. Sonrasında ihtiyacınız kadar kredi alırsınız; her başarılı doğrulama yalnızca 1 kredidir. Kredi başı 0,03 TL (KDV hariç); aşağıdaki tutarlara KDV dahildir.
SaaS'ınızda hâlihazırda form tabanlı bir OTP akışı varsa, geçişi ortalama 90 dakikada tamamlarsınız. İlk 250 başarılı doğrulama ücretsiz; kredi kartı gerekmez.