Dokümantasyon

Kendi sisteminize Touchque 2FA ekleyin (Google Authenticator yerine)

Müşterileriniz Google Authenticator'daki 6 haneli kodlar yerine Touchque Authenticator uygulamasıyla giriş onaylasın. Şifre adımınız aynı kalır; ikinci adım telefona gelen bir onay olur. Bu rehber bütün yolu anlatır: API anahtarı, SDK kurulumu, telefonu bağlama, giriş isteği, sonuç (webhook ya da durum sorgusu) ve kısa kod.

Kısaca: 1) Panelde API anahtarı oluşturun. 2) SDK'yı kurun. 3) Kullanıcı ayarlar sayfanızdaki QR'ı Touchque Authenticator ile bir kez okutur. 4) Her girişte şifreden sonra login.request çağırın, telefona push gider. 5) Sonucu webhook ile ya da login.status ile alın ve oturumu açın.

Kullanıcılarınız için ne değişir?

KonuGoogle AuthenticatorTouchque Authenticator
İkinci adımKullanıcı uygulamayı açar, 6 haneli kodu okur ve yazar.Telefona bir push gelir. Kullanıcı bakar ve Onayla'ya dokunur (Face ID ya da parmak izi).
Kullanıcının gördüğüBir kod ve adınız. Bu girişle ilgili hiçbir şey.Markanız, neyin onaylandığı (giriş ya da ayrıntılarıyla bir ödeme), şehir ve tarayıcı.
Başkası denerseOltalama sayfası kodu ister ve hemen kullanır.Push başka bir şehir ya da tarayıcı gösterir; kullanıcı "Bu ben değilim"e dokunur. Riskli istekler sayı eşleştirme ister ya da engellenir.
Telefonda internet yoksaKodlar çevrimdışı çalışır.Açarsanız çevrimdışı QR kodu ya da çevrimdışı zaman tabanlı kod.
Telefon kaybolursa2FA'yı elle sıfırlarsınız.Kurtarma kodları, iş arkadaşlarının onayıyla yeni telefona taşıma ya da sizin yaptığınız sıfırlama.

Kullanıcılarınız Touchque Authenticator'ı telefonlarına (iPhone ya da Android) kurar ve bir kez bağlar. Kayıt olma ve şifre yazma şekilleri değişmez.

Başlamadan önce

  • Touchque panelinde Developers → API keys altında bir anahtar oluşturun. tq_ ile başlayan API anahtarını ve API secret'ı alırsınız; secret yalnız bir kez gösterilir.
  • İkisini de yalnız sunucunuzda tutun (TQ_API_KEY, TQ_API_SECRET). Tarayıcıya ya da mobil uygulamaya koymayın: her istek bu secret ile HMAC imzalanır.
  • Her kullanıcı için sabit bir kimlik seçin: externalUsername (e-posta, kullanıcı id'si). Touchque bunu yalnız referans olarak saklar.

1. SDK'yı kurun ve anahtarlarınızı tanımlayın

Sunucu dilinizi seçin. Node.js 5.2.0, Python 5.2.0, PHP 5.2.0, Go 5.2.0, .NET 5.2.0, Ruby 5.2.0 ve Java 5.2.0 yayımlandı. SDK olmadan REST API her dilde çalışır: istek imzası için Kimlik doğrulama sayfasına bakın.

# Node.js
npm install @touchque/node
# Python
pip install touchque-authenticator
# PHP
composer require touchque-authenticator/php-sdk:^5.0
# Go
go get github.com/Touchque/touchque-go/v5
# .NET
dotnet add package Touchque.AspNetCore
# Ruby
bundle add touchque
# Java
implementation("com.touchque:touchque-spring-boot-starter:5.2.0")
# : henüz yayımlanmadı

# .env sunucunuzda (asla tarayıcıda ya da uygulamada değil)
TQ_API_KEY=tq_...
TQ_API_SECRET=...

2. Kullanıcının telefonunu bağlayın (bir kez)

Ayarlar sayfanızda ("2FA'yı aç") kullanıcı için bir secret oluşturun ve birlikte gelen QR görselini gösterin. Kullanıcı Touchque Authenticator'ı açar ve QR'ı okutur; Google Authenticator'a hesap eklemek gibi. Secret 5 dakika geçerlidir; sonra yenisini oluşturun. 10 kurtarma kodunu bir kez gösterin ve saklamasını isteyin: telefon yoksa giriş yolu bunlardır.

const { Touchque } = require('@touchque/node');
const tq = new Touchque(); // TQ_API_KEY / TQ_API_SECRET from the environment

// Ayarlar sayfası → "2FA'yı aç"
app.post('/2fa/enroll', requireSession, async (req, res) => {
  const { qrCodeDataUrl, recoveryCodes, expiresAt } = await tq.auth.generateSecret({
    externalUsername: req.user.email,
  });
  // QR'ı gösterin (<img src=qrCodeDataUrl>), kurtarma kodlarını bir kez gösterin
  res.json({ qrCodeDataUrl, recoveryCodes, expiresAt });
});

// Telefon bağlanana kadar sayfa bunu sorar
app.get('/2fa/enroll/status', requireSession, async (req, res) => {
  const user = await tq.auth.getUser({ externalUsername: req.user.email });
  res.json({ linked: Boolean(user.used && user.deviceId) });
});
Kullanıcı bağlandığında getUser yanıtında used: true ve bir deviceId olur. Panelde 2FA users sayfası da bağlı telefonları gösterir.

3. Şifreden sonra giriş isteğini gönderin

Şifre doğruysa oturumu henüz açmayın. Sunucunuzdan login.request çağırın: Touchque kullanıcının telefonuna push gönderir. Telefon girişin nereden geldiğini gösterebilsin diye kullanıcının IP adresini ve tarayıcı bilgisini (user agent) iletin. İstek 30 saniye geçerlidir.

// Şifre kontrolü geçtikten sonra:
const r = await tq.login.request({
  externalUsername: user.email,
  type: 'LOGIN',
  clientIp: req.ip,                 // telefonda şehir, ülke olarak görünür
  userAgent: req.get('user-agent'), // tarayıcı ve cihaz olarak görünür
});
// r = { requestId, expiresAt, challengeCode?, caseCode }
req.session.pending2fa = { requestId: r.requestId, user: user.email };
res.json({ waiting: true, number: r.challengeCode }); // sayı varsa gösterin
Yanıtta challengeCode varsa (risk yüksek ya da siz requireNumberMatch istediniz) sayıyı sayfanızda gösterin: telefon kullanıcıdan aynı sayıyı seçmesini ister. Bu, kullanıcının yalnız kendi başlattığı girişi onaylamasını sağlar.

4. Sonucu alın: webhook ya da durum sorgusu

İki yol var, birini kullanın. Webhook (önerilen): Developers → Webhooks altında Callback URL'nizi girin; kullanıcı onaylayınca ya da reddedince Touchque sonucu API secret'ınızla imzalayıp oraya POST eder (o sayfadaki Signing secret aynı değerdir). Güvenmeden önce x-signature başlığını ham gövde üzerinde mutlaka doğrulayın. Durum sorgusu: 30 saniyeye kadar 2 saniyede bir login.status sorun. Oturumu yalnız CONFIRMED (durum) ya da SUCCESS (webhook) için ve yalnız 3. adımda sakladığınız requestId ve kullanıcı için açın.

// Webhook: Developers → Webhooks → Callback URL = https://uygulamaniz/webhooks/touchque
app.post('/webhooks/touchque', express.raw({ type: 'application/json' }), (req, res) => {
  let event;
  try {
    event = tq.webhook.verify({ rawBody: req.body.toString('utf8'), signature: req.get('x-signature') });
  } catch {
    return res.sendStatus(403); // Touchque'dan değil, değiştirilmiş ya da eski
  }
  // event.status: 'SUCCESS' | 'REJECTED', event.requestId, event.externalUsername
  saveDecision(event.requestId, event.status); // bekleyen tarayıcı bunu okur
  res.sendStatus(200);
});

// Ya da tarayıcı beklerken 2 saniyede bir sorun:
const s = await tq.login.status(pending.requestId); // PENDING | CONFIRMED | REJECTED | EXPIRED
if (s.status === 'CONFIRMED' && s.externalUsername === pending.user) startSession(pending.user);
Webhook adresiniz HTTPS olmalı (yerel testte localhost olabilir) ve 5 saniye içinde 2xx dönmeli; dönmezse Touchque birkaç kez yeniden dener. Aynı olay iki kez gelebilir: jti ya da requestId ile tekrarları ayıklayın.

5. Diğer yanıtları ele alın

Her yanıt K7P-2QX gibi bir caseCode taşır. İstek reddedilince kodu kullanıcıya gösterin; ekibiniz panelde Logs → Look up a case altında kodu açar ve nedenini görür.

YanıtNe yapmalı
challengeCode ile 200Sayı eşleştirme: sayıyı sayfanızda gösterin. Telefon kullanıcıdan bu sayıyı seçmesini ister.
404Kullanıcının bağlı telefonu yok. 2. adıma yönlendirin ya da kurtarma kodu kabul edin.
403 blockedRisk motoru isteği reddetti. caseCode'u gösterin: "Destek ekibinize söyleyin: K7P-2QX".
403 device_keys_lostTelefon anahtarlarını kaybetti (uygulama yeniden kuruldu, telefon geri yüklendi). Kullanıcı telefonu yeniden bağlar.
423 frozenÇok fazla reddedilen istek. Kullanıcının kim olduğunu doğrulayın, sonra secret'ı sıfırlayın (sıfırlama dondurmayı da kaldırır).
429 rate_limitedBu kullanıcıya 10 dakikada 5'ten fazla push. retryAfter saniye bekleyin.
requiresPasskey: truePolitikanız bu işlem için passkey istiyor, push gönderilmedi. Passkey sayfasına bakın.
REJECTEDKullanıcı Reddet'e dokundu. rejectReason bunu bildirip bildirmediğini söyler ("Bu ben değilim").
EXPIRED30 saniye içinde yanıt gelmedi. Yeni bir istek göndermeyi önerin.
const { TouchqueAPIError } = require('@touchque/node');

try {
  await tq.login.request({ externalUsername: user.email, type: 'LOGIN', clientIp: req.ip });
} catch (err) {
  if (!(err instanceof TouchqueAPIError)) throw err;
  if (err.status === 404) return res.json({ enroll: true });            // bağlı telefon yok
  if (err.caseCode) return res.status(err.status).json({                 // blocked, frozen, rate_limited
    message: `Destek ekibinize söyleyin: ${err.caseCode}`,
  });
  throw err;
}

Google Authenticator kullanıcılarını taşıma

  • Google Authenticator secret'ları Touchque'ya aktarılamaz: her kullanıcı telefonunu 2. adımdaki QR ile bir kez bağlar.
  • Geçiş süresince iki yöntemi birlikte tutun: telefonu bağlı olana push, olmayana eski kod. Bir sonraki girişte "Touchque ile onayla"yı önerin.
  • Kullanıcının telefonu bağlanınca (used: true) onun eski TOTP secret'ını silin; böylece oltalanabilecek kod kalmaz.
  • Telefonu internetsiz kalabilen kullanıcılar için panelde App user policy altında çevrimdışı onayı açın.

Kısayollar: tek satırlık middleware ve hazır ekranlar

Yukarıdaki adımlar çıplak çağrılardır. SDK'lar bunları sarar: requireTouchque('LOGIN') (Express), @require_touchque (Flask, Django, FastAPI), ->middleware('touchque:LOGIN') (Laravel) ve touchque.Require (Go) telefon onaylayana kadar 202 döner. Sayfada @touchque/web ve @touchque/react bağlama QR'ını, sayılı bekleme ekranını ve passkey adımını hazır verir. Bu rehberler için kenar çubuğunu SDKs'e çevirin.

Canlıya almadan önce

  • API anahtarı ve secret yalnız sunucuda; istekler HTTPS üzerinden.
  • Webhook imzası doğrulanıyor; oturum yalnız sizin başlattığınız requestId için açılıyor.
  • Kurtarma kodları kayıt sırasında gösteriliyor ve telefon kaybı için bir yolunuz var (Sorun giderme sayfasına bakın).
  • Reddedilen isteklerde caseCode kullanıcıya gösteriliyor.
  • Gerçek bir telefonla bağlama, onay, ret ve süre dolması denendi.