SMS-OTP · ters yön doğrulama

Telefon doğrulamayı dakikalar içinde ekle.

Türkiye'ye göre yapılmış SMS-OTP altyapısı. Auth stack'ine iki endpoint'le oturur.

Evraksız, beklemesiz — hemen başla. Başlık onayı, BTK süreci, operatör anlaşması gerekmez — SMS'i biz göndermeyiz, kullanıcın kendi hattından gönderir. API key al, çağır.

Türkiye'de kalan. Numara, kod, oturum — İstanbul'daki altyapımızda işlenir; loglarda maskelenir, işi bitince silinir.

Fraud-korumalı. Kendi inisiyatifimizle tek SMS göndermeyiz: SMS bombing'e yapısal bağışıklık, gönderen-bazlı rate-limit, ön ödemeli kredi. Faturan patlamaz.

İlk 250 başarılı doğrulama ücretsiz — kredi kartı gerekmez.

01 · Sen çağırırsın

OTP başlat

→ otp.mioe.com.tr/auth/init
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…" }
02 · Biz çağırırız

İmzalı verified callback

→ yourapp.example/sms-login/cb
# Kullanıcı kodu SMS'leyince:
POST /sms-login/cb
X-Login-Signature: t=1746635012,v1=8c5d…

{ "type": "verified",
  "phone": "+905321112233" }

Kurulum cehennemini atla

Başlık onayı, BTK süreci, operatör API entegrasyonu — bu modelde hiçbiri sana düşmez: dışarıya SMS göndermiyoruz, inbound numarayı ve operatör tarafını biz işletiyoruz. Sen iki ucu bağla — /auth/init'i çağır, imzalı verified callback'ini karşıla. 250 doğrulamalık ücretsiz deneme ile dakikalar içinde canlı ol; Better Auth vb. auth stack'ine doğrudan oturur.

Veri sınırı geçmez

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 aktarımı hiç doğmaz. Üstüne veri minimizasyonu: loglarda numaralar maskelenir, biten oturumlar en geç 60 dakika içinde KVKK süpürmesiyle silinir. KVKK Aydınlatma Metni ve Veri İşleme Sözleşmesi hazır.

Fatura patlatan fraud'a karşı hazır

Sistem kendi inisiyatifiyle hiçbir zaman SMS göndermez — kötüye kullanılacak bir "kod gönder" ucu yok, SMS bombing ve toll fraud yapısal olarak imkânsız. İnbound tarafta taşıyıcı IP allowlist, gönderen-bazlı deneme sınırı ve HMAC imzalı callback yerleşik. Krediler ön ödemeli: bir gecede sürpriz fatura riski yok.

Kendiniz deneyin ve görün.

Klasik tek kullanımlık şifrede (OTP) kodu biz kullanıcıya yollarız, kullanıcı da onu ekrana yazar — oysa yazılan bir kod paylaşılabilir, yönlendirilebilir, kandırılabilir. 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. Doğrulama, mesaj gerçekten o telefondan çıkmadan kabul edilmiyor — asıl güvenlik tam burada. Taşıyıcı göndericinin o numara olduğuna şahitlik ediyor, biz oturumu eşleştirip uygulamanıza HMAC-SHA256 imzalı bir verified webhook'u atıyoruz.

Yandaki kodu gösterilen numaraya SMS atmak için SMS gönder butonuna basın.

Canlı oturum sess_…
··········
Telefonundan ···· ······ yazıp 0216 606 22 05 numarasına gönder.
Bu kod yalnızca bu oturuma özeldir ve sadece bu ekranda size gösterilir — başka kimse görmez, paylaşmanıza gerek yok.
— sn
Doğrulandı · taşıyıcı onaylı

Bu numara sizsin.

+90 ··· ··· ·· ··

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.

Süre doldu

60 saniye içinde eşleşen bir SMS ulaşmadı. Yeni bir kod alıp tekrar deneyebilirsin.

Oturum açılamadı

Bağlantıda bir sorun oluştu.

Dört adım. SMS'in kendisi kanıttır.

Form tabanlı OTP'lerde kullanıcı kodu okur ve yazar. Biz işin yönünü çeviriyoruz — taşıyıcı doğrudan kim olduklarına şahitlik ediyor.

01
Webapp

Oturumu başlat

POST /auth/init. Yanıt: 4 harfli prefix + 6 haneli OTP + 60 sn ömürlü oturum kimliği.

02
Son kullanıcı

SMS ile cevap

Ekrandaki WXKZ 482910 kombinasyonunu kısa numaraya yollar — bu işlem onun ispatıdır.

03
Gateway

Inbound webhook

GSM operatörü (veya seçtiğiniz sağlayıcı) bize POST eder. Prefix + OTP eşleşirse oturum kapanır.

04
Backend'iniz

İmzalı geri çağrı

callback_url'nize yalnızca verifiedsessionId ve doğrulanan phone birlikte, HMAC imzalı. Eşleşme olmazsa hiçbir şey göndermeyiz.

Tarayıcıdan taklit edilemeyen şeyler için.

Sahiplik ispatı

SMS'in göndericisi mobil ağ tarafından belirlenir — formdan değil. Tarayıcı kaynaklı hiçbir bilgi güvenilmez. Bu, telefon numarası doğrulamasını yapısal olarak sahteciliğe kapatır.

Sert 60 saniye

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 süpürülür — clock drift ya da açık kalmış oturum yok.

İmzalı geri çağrı

Backend'iniz hiçbir form alanına güvenmez. Sadece X-Login-Signature başlığını webapp'a özel HMAC secret'la doğrular — gövdeyi biz attest ediyoruz.

Telefon doğrulaması ancak sahte üretilemediğinde işe yarar. Bu yüzden tarayıcının söylediği hiçbir şeye değil, taşıyıcının ettiği şahitliğe güveniyoruz.
— Tasarım ilkesi · 01

Neden reverse OTP + bizim sertleştirmelerimiz daha güvenli?

Çıplak reverse OTP'nin, klasik (sistemin SMS gönderdiği) OTP'ye göre yapısal olarak daha geniş bir sahtecilik yüzeyi vardır — kimlik ispatı, taşıyıcının ilettiği bir iddiaya dayanır. Biz bu yüzeyi, her production ortamında gerçekten çalışan dört katmanla kapatıyoruz: taşıyıcının doğrulanmış ağına kilitli IP allowlist, ayrı bir paylaşılan header secret, gönderen numarası başına deneme sınırı ve HMAC-imzalı geri çağrılar. Sonuç: klasik OTP'nin kendi zayıf noktalarını taşımayan, daha güvenli bir sistem.

Risk / kriter Klasik OTP (SMS ile gönderim) Çıplak reverse OTP (sertleştirmesiz) Bizim sistemimiz
Kimlik ispatı nereye dayanır Kullanıcının kodu doğru okuyup tarayıcıya yazması Taşıyıcının "bu SMS bu numaradan geldi" şahitliği — doğrulanmamış Aynı şahitlik + o iddianın gerçekten taşıyıcını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 taşıyıcını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ı phishing / 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 zorlanan 60 saniyelik pencere; yakalansa bile hızla ölür
SMS bombing / 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 taşıyıcı-seviyesi risk Hiçbir OTP modelinin tek başına ortadan kaldıramadığı tek katman — ama IP allowlist + throttle bunu HTTP seviyesinde istismar etmeyi de zorlaştırır
Savunma katmanları (özet) Genelde yalnızca hız sınırlama + captcha Yok Taşıyıcı IP allowlist · paylaşılan header secret · gönderen-bazlı throttle · HMAC imzalı geri çağrı · kiracı başına izolasyon
Sonuç

Bu sertleştirmelerle birlikte reverse OTP, klasik (SMS-gönderimli) OTP'den daha güvenlidir. Çıplak reverse OTP'nin tek gerçek açığı — webhook/API sahteciliği — taşıyıcının doğrulanmış ağına kilitli IP allowlist ve ayrı bir paylaşılan token ile pratikte kapatılmıştır; kalan tek risk katmanı (taşıyıcı-seviyesi SIM-swap/SS7) zaten klasik OTP'nin de taşıdığı bir risktir.

Buna karşılık reverse OTP, klasik modelin gerçek dünyada en çok istismar edilen iki zayıf noktasına — gerçek zamanlı OTP-relay phishing ve SMS bombing/toll fraud — karşı yapısal olarak bağışık veya çok daha dirençlidir. Aynı taşıyıcı-seviyesi riski taşıyıp, klasik OTP'nin taşıdığı ekstra iki riski taşımıyoruz — üstelik dört bağımsız savunma katmanı eklendi.

Aynı backend. Üç inbound yöntemi.

Operatör webapp'ı oluştururken hangisinin kullanılacağını seçer. Sonradan değiştirmek bir tıklama.

Paylaşımlı

Operatörün GSM numarası

4 harfli prefix tüm webapp'ları aynı kısa numarada toplar.

Kullanıcı <prefix> <otp> yazar. Toplam 11 karakter.
En ucuz5 dakika kurulum
Özel

Kendi GSM numaranız

Numara doğrudan webapp'ınıza bağlı, prefix gerekmez.

Sadece 6 haneli OTP — daha kısa ve net.
Aylık abonelik1 gün kurulum
BYO Gateway

Kendi SMS sağlayıcınız

Twilio, Vonage veya self-hosted SMSC'i webapp'a özel inbound URL'e bağlayın.

Esnek — kendi markanızla kendi kısa numaranız.
Sağlayıcı maliyeti30 dk kurulum

İki HTTP çağrısı. O kadar.

Bir uca /auth/init'i çağırıyorsunuz, diğer uçta bizden imzalı bir POST bekliyorsunuz.

01 İstek

OTP başlat

→ otp.mioe.com.tr/auth/init
POST /auth/init HTTP/1.1
Host: otp.mioe.com.tr
X-API-Key: lvsr_a3f…b21
Content-Type: application/json

{ "phone": "+905321112233" }
Yanıtta sessionId, code (prefix), otp ve dedicated modda inboundNumber döner.
02 Geri çağrı

İmzalı POST'u doğrulayın

→ yourapp.example/sms-login/cb
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ıyı callback'teki phone ile giriş yapın, istemcinin bildirdiği numaraya değil — oturum → numara bağını biz imzalıyoruz.

QR kodu + SMS butonu: en iyi kullanıcı deneyimi.

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.

QR kodu (masaüstü)

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.

SMS butonu (mobil)

Mobil cihazlarda <a href="sms:…"> bağlantısı telefonun SMS uygulamasını doğrudan açar. Kullanıcı sadece "Gönder"e basar.

Android QR çözümü

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 URI

sms: şeması

Mobilde SMS butonunun bağlantısı
// 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.
Android QR

Yönlendirme sayfası

→ yourapp.example/sms-redirect
// 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;
Android kamera → HTTPS sayfası → sms: URI → SMS uygulaması açılır.
01

Mobil tespit

navigator.userAgent ile mobil/masaüstü ayırın. Mobilde SMS butonu, masaüstünde QR gösterin.

02

QR'da HTTPS kullanın

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.

03

API key'i frontend'e koymayın

/auth/init çağrısını backend proxy'niz üzerinden yapın. API anahtarı yalnızca sunucu tarafında kalmalıdır.

04

Sonucu backend'iniz alı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ış — bu entegrasyonun kapsamı dışında.

Tek güvendiğimiz şey: sizin secret'ınızla imzalanmış baytlar.

01

Taşıyıcı onaylı gönderici

Inbound SMS'in göndericisi mobil ağ tarafından set edilir. Tarayıcı kaynaklı hiçbir alan bu zincirde yer almaz.

02

HMAC-SHA256 imzalı geri çağrı

Her webhook X-Login-Signature taşır. Backend, ham gövdeyi sizin secret'ınızla doğrulayana kadar olayı varsaymaz.

03

Kimlik bağı — numara callback'ten gelir

verified geri çağrısı sessionId ve doğrulanan phone'u birlikte, imzanın altında taşır. Kullanıcıyı bu imzalı numarayla giriş yaparsınız; istemci "hangi numara doğrulandı" diyemez, dolayısıyla kendi numarasını doğrulatıp başkasınınkini iddia edemez.

04

Webapp-başına izolasyon

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.

05

Replay'e dayanıklı

İmza Unix zaman damgasına bağlanır; ±5 dakika pencere önerilir. Her OTP tek seferliktir, eşleştiği an ölür.

06

Sert 60 saniye

Süre sunucu tarafında zorlanır: her eşleşme sorgusu expires_at > now ister, pencere dolunca OTP eşleşmeyi bırakır ve süpürülür. Kullanıcı tarafında hiçbir hile süreyi uzatamaz.

07

Re-issue eskiyi öldürür

Aynı telefon için yeni /auth/init önceki oturumu sessizce failed olarak işaretler — eski kod anında işe yaramaz.

08

Sabit zamanlı doğrulama

Her dilde örnek kod timingSafeEqual / hash_equals kullanır — kendiniz == ile karşılaştırmayın.

09

Sırlar bir kez gösterilir

API key ve HMAC secret yalnızca oluşturma veya rotation anında görünür. Sızdığında operatör yerinde rotate edebilir.

Parolalar OWASP standardında saklanır.

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.

OWASP uyumlu Argon2id

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.

Geri döndürülemez, tuzlu

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.

Kendini güncelleyen

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.

Kriptografik temeller

Kimlik doğrulama katmanının tamamı tek bir denetlenebilir kripto modülü üzerine kuruludur.

01

Argon2id parola özetleme

OWASP parametreleriyle; PHC formatında, parametreler özetle birlikte saklanır.

02

HMAC-SHA256 imzalama

İmzalı webhook geri çağrıları aynı modülde üretilir ve sabit zamanlı doğrulanır.

03

SHA-256 token özeti

Oturum ve parola sıfırlama token'ları veritabanında yalnızca hash'lenmiş halde tutulur.

04

Kriptografik rastgelelik

OTP'ler, tuzlar ve token'lar crypto.getRandomValues CSPRNG ile üretilir.

05

Sabit zamanlı kıyas

timingSafeEqual ile parola ve imza karşılaştırmalarında zamanlama sızıntısı yok.

06

Bias'sız OTP

Reddetme örneklemesiyle (rejection sampling) üretilen kodlarda modulo yanlılığı bulunmaz.

Abonelik yok. Kullandığın kadar kredi.

İ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.

1.000 kredi
36 TL
KDV dahil
5.000 kredi
180 TL
KDV dahil
25.000 kredi
900 TL
KDV dahil
100.000 kredi
3.600 TL
KDV dahil

Bir akşamda bağlayın.

SaaS'ınız zaten bir form-OTP akışına sahipse, geçişi ortalama 90 dakikada tamamlıyorsunuz. İlk 250 başarılı doğrulama ücretsiz; kredi kartı gerekmez.