Dokümantasyon

Sessiz giriş

Bir girişte yeni hiçbir şey yokken telefona tekrar tekrar sormayın. Tarayıcı cihaza bağlı bir anahtar tutar ve kararı Touchque risk motoru verir: telefona yalnızca yeni bir şey olduğunda sorulur (yeni tarayıcı, telefon, ülke ya da ağ, kritik işlem, herhangi bir risk sinyali). Sunucunuz push'u yalnızca Touchque öyle dediğinde atlar.

AdımNe olur
TarayıcıcreateTouchqueWeb({ browserKey: true }) (@touchque/web 2.2.0) siteniz için WebCrypto ile dışa aktarılamayan bir ECDSA P-256 anahtarı üretip IndexedDB'de tutar ve her istekte taze, imzalı kanıtını X-Touchque-Browser başlığında gönderir. Kod anahtarı kullanabilir, okuyamaz.
İlk girişSunucunuz push'u kanıtla birlikte gönderir (login.request({ …, browserProof }); guard bunu sizin için yapar). Kullanıcı telefonda onaylayınca Touchque tarayıcıyı tanır.
Sonraki girişlerTaze kanıtla POST /risk/check (tq.risk.check). prompt: false: yeni bir şey yok, kullanıcıyı push olmadan içeri alın. Diğer her durumda: her zamanki push.
POST/risk/check

/login/request ile aynı API anahtarı ve kota. Telefona hiçbir şey göndermez. Yanıt: 200 { prompt, reasons: [{ code, text }], assurance: "high" | "normal" | "low", silentMode: "enforce" | "shadow", caseCode: "K7P-2QX" }. caseCode bu yanıtın "Neden?" vaka kodudur: telefona sorulduğunda gösterin; ekibiniz kararı bu panelde Logs → Look up a case altında açar.

AlanTipAçıklama
externalUsernamestringKullanıcı ID Zorunlu
typestringİşlem (varsayılan "LOGIN"). Kritik bir işlem her zaman sorar.
clientIpstringSon kullanıcının genel IP adresi; önceki onaylı girişlerinin ağlarıyla karşılaştırılır. Gönderilmezse telefona sorulur.
userAgentstringSon kullanıcının tarayıcısı
browserProofstringX-Touchque-Browser değeri, olduğu gibi iletilir. Eksik ya da geçersiz olması hata değildir: tanınmayan tarayıcı sayılır.
maxAgeSecondsinteger ≥ 0Bu tarayıcıdaki son telefon onayının yaşı için kendi sınırınız. 0 = her zaman sor. Touchque hiçbir zaman 7 günü aşmaz.
Hata durumunda sor. Push'u yalnızca yanıt tam olarak prompt: false (boolean) olduğunda atlayın. Hata, zaman aşımı ya da okunamayan yanıt: her zamanki gibi push gönderin. SDK'lar yanıtı bu şekilde okur ve guard'ları hata durumunda asla onay vermez.
Asla sessiz değil: bunlar her zaman telefona sorar
  • Bir tarayıcıdaki ilk giriş ve geçerli anahtar kanıtı olmayan her istek (gizli pencere, başka tarayıcı, browserKey kullanmayan sayfa)
  • Kritik işlemler ve önemli bir şeyi değiştiren işlemler
  • Yeni bir ülke ya da ağ, barındırma / VPN / Tor ağı ya da karşılaştırılacak clientIp olmaması
  • Tarayıcıyı onaylayandan farklı bir telefon ya da maxAgeSeconds veya 7 günden eski son telefon onayı
  • Herhangi bir risk sinyali: yakın zamanda yanıtsız ya da reddedilmiş push, sahtekârlık ya da "Bu ben değildim" bildirimi, son 24 saatte değişen giriş yöntemi ya da parola
  • Vishing Shield: arama sırasında verilip yeniden onaylanmamış bir onay (12 saat) ya da geri alınan veya yönlendirildiği için reddedilen bir onay (7 gün)
  • Dondurulmuş hesap, anahtarlarını kaybeden telefon, yalnız passkey ya da her zaman sayı eşleştirme politikası, bekleyen ek doğrulama, erişim ya da ülke kuralı
  • Çalışamayan herhangi bir kontrol ve ölçüm (shadow) modu
Bir tarayıcı yalnızca kanıtını taşıyan bir istekte gerçek bir ikinci faktörle tanınır: telefonda onaylanan push (arama sırasında verilip yeniden onay bekleyen değil), passkey ya da o isteğin çevrimdışı QR kodu. Yazılan zaman tabanlı kod, kurtarma kodu ya da sessiz girişin kendisi bir tarayıcıyı asla tanıtmaz. shadow modunda (silentMode) prompt her zaman true olur ve reasons ne olacağını söyler.
Neden kodları: sorulmadı (hepsi birlikte)
codeAnlam
known_browserBu tarayıcı cihaza bağlı anahtarını kanıtladı
recent_approvalBu tarayıcıda süre sınırı içinde telefonla onay verildi
same_phoneŞu an bağlı olan telefon, bu tarayıcıyı onaylayan telefon
familiar_networkÜlke ve ağ daha önceki onaylı girişlerden tanıdık
no_risk_signalRisk sinyali yok
Neden kodları: soruldu (herhangi biri)
codeAnlam
no_browser_keyGeçerli tarayıcı anahtarı kanıtı yok: gizli pencere, başka tarayıcı, browserKey kapalı ya da eski veya tekrar kullanılmış kanıt
new_browserBu tarayıcı bu hesap için daha önce telefonla onaylanmadı
approval_too_oldBu tarayıcıdaki son telefon onayı sınırdan eski (maxAgeSeconds, en fazla 7 gün)
policy_every_sign_inmaxAgeSeconds 0: her girişte sorulur
other_phoneOnaylayacak telefon, bu tarayıcıyı onaylayan telefon değil
new_countryBu ülkeden ilk onaylı giriş
new_networkBu ağdan ilk onaylı giriş
network_unknownÜlke ya da ağ önceki girişlerle karşılaştırılamadı (clientIp gönderin)
hosting_networkBarındırma, VPN ya da Tor ağından giriş
critical_actionİşlem kritik
sensitive_actionİşlem önemli bir şeyi değiştiriyor
risk_signalBir risk sinyali (text içinde yazar)
push_fatigueSon zamanlarda yanıtsız ya da reddedilmiş onaylar var
fraud_reportYakın zamanda "Bu ben değildim" ya da sahtekârlık bildirimi
new_factorSon 24 saatte bir giriş yöntemi ya da parola değişti
vishing_shieldYakın bir onay sırasında arama ya da yönlendirme algılandı
checks_incompleteKontrollerin hepsi çalışamadı
not_a_sign_inYalnızca bir girişin ilk değerlendirmesi sessiz olabilir
silent_mode_shadowSessiz giriş henüz ölçüm modunda (shadow)
phone_not_linkedBu hesaba bağlı telefon yok
frozenBu hesabın onayları dondurulmuş
phone_keys_lostBağlı telefon onay anahtarlarını kaybetti
passkey_required_by_policyPolitikanız bu işlem için passkey istiyor
policy_always_challengePolitikanız her seferinde sayı eşleştirmeli onay istiyor
step_up_pendingÖnceki bir onay ek doğrulama istedi
access_policyErişim ya da ülke kurallarınızdan biri uygulanıyor
engine_unavailableRisk motoruna sorulamadı

text İngilizcedir; gösterin ya da kodu çevirin. Küçük sürümlerde yeni kodlar eklenebilir: bilinmeyen bir kodu "soruldu" sayın.

Tanınan tarayıcılar
EndpointSonuç
GET /risk/browsers?externalUsername={ browsers: [{ thumbprint, label, createdAt, lastMfaAt, lastMfaMethod, lastSeenAt, lastSilentAt }] }
POST /risk/browsers/forget{ externalUsername, thumbprint? } → { forgotten: n }. thumbprint verilmezse hepsi unutulur: parola sıfırlamadan ya da "her yerden çıkış"tan sonra yapın.
Guard seçeneği (varsayılan kapalı)
SDKSeçenekNerede
NodesilentSignIn: true | { maxAgeSeconds }requireTouchque, withTouchque, touchqueRouter, runGuard
Pythonsilent_sign_in=True | {'max_age_seconds': n}require_touchque (Flask, Django), RequireTouchque (FastAPI), relay'ler, run_guard
PHP'silentSignIn' => true | ['maxAgeSeconds' => n]TouchqueMiddleware, TouchqueRelay, RelayHandler, Guard::run
GoSilentSignIn: true, SilentSignInMaxAgeSecondsRequireOptions, RelayOptions, GuardInput
.NETSilentSignIn = new() | new() { MaxAgeSeconds = n }RequireTouchque, RelayOptions, GuardInput
JavasilentSignIn(Guard.SilentSignIn.on() | new Guard.SilentSignIn(n))TouchqueGuardOptions, RelayOptions, Guard.Input
Rubysilent_sign_in: true | { max_age_seconds: n }require_touchque (Rails), Touchque::Rack::Relay

Açıkken X-Touchque-Browser taşıyan yeni bir deneme önce risk.check çağırır. prompt: false ise push olmadan hemen onaylanır: assurance.method "silent", confirmedVia "SILENT", requestId "silent", reasons; relay'ler onAuthenticated'ı via "silent" ile çağırır. Aksi halde, ve kontroldeki her hatada, kanıt eklenmiş her zamanki push başlar; onayı tarayıcıyı tanıtır. Token ile yoklama tekrar kontrol etmez. Başka bir origin'deki relay, Access-Control-Allow-Headers içinde X-Touchque-Browser'a izin vermelidir.

Tarayıcı
import { createTouchqueWeb, browserKey } from '@touchque/web';

// Korumalı istekler ve klasik 2FA girişi X-Touchque-Browser taşır
const tq = createTouchqueWeb({ baseUrl: '/touchque', browserKey: true });

const result = await tq.classic2fa.login({ onStep });
if (result.assurance?.method === 'silent') {
  // bilinen tarayıcı: push gönderilmedi
}

// Ortak bilgisayar / her yerden çıkış: bu tarayıcının anahtarını sil
await tq.browserKey.forget();

// createTouchqueWeb olmadan: başlık değeri, kullanılamıyorsa null
const proof = await browserKey.proof();
Sunucu: guard seçeneği
app.post('/login/2fa',
  requireTouchque('LOGIN', {
    user: (req) => req.session.passwordVerifiedUser,
    silentSignIn: true, // ya da kendi sınırınız: { maxAgeSeconds: 8 * 3600 }
  }),
  (req, res) => {
    // req.touchque.assurance.method === 'silent' → push gönderilmedi
    // req.touchque.reasons → [{ code: 'known_browser', text: '…' }, …]
    res.json({ ok: true });
  });

// touchqueRouter(tq, { …, silentSignIn: true }) → onAuthenticated: via === 'silent'
Sunucu: guard olmadan
const browserProof = req.get('x-touchque-browser');
const risk = await tq.risk.check({
  externalUsername: user, type: 'LOGIN', clientIp: req.ip, userAgent: req.get('user-agent'), browserProof,
});
if (risk.prompt === false) return openSession(user); // risk.reasons nedenini söyler

// Her şeyin dışında: her zamanki push, kanıt ekli (onay tarayıcıyı tanıtır)
await tq.login.request({ externalUsername: user, type: 'LOGIN', clientIp: req.ip, browserProof });

const { browsers } = await tq.risk.browsers({ externalUsername: user });
await tq.risk.forgetBrowsers({ externalUsername: user }); // hepsi; tek biri için { thumbprint }
Cevap 200
{
  "prompt": false,
  "reasons": [
    { "code": "known_browser", "text": "This browser proved its device-bound key" },
    { "code": "recent_approval", "text": "Approved on the phone in this browser 3 hours ago" },
    { "code": "same_phone", "text": "The same phone approved this browser" },
    { "code": "familiar_network", "text": "Country and network seen in earlier approved sign-ins" },
    { "code": "no_risk_signal", "text": "No risk signal" }
  ],
  "assurance": "high",
  "silentMode": "enforce"
}