Relay rotaları
Tek bir router bağlayın; tarayıcı SDK'sının (@touchque/web) çağırdığı tüm rotalar hazır olsun: iki aşamalı POST /login, kayıt, çevrimdışı kodlar ve passkey işlemleri. Her sunucu SDK'sında var: Node (touchqueRouter), Python (Flask / FastAPI / Django), PHP (Laravel ya da tek başına RelayHandler), Go (net/http), .NET (MapTouchqueRelay), Java (Spring Boot starter) ve Ruby (Rails ve Rack için Touchque::Rack::Relay).
Login user seçeneğini (şifre adımını geçen kullanıcı) mutlaka verin. Verilmezse kullanıcı adı istek gövdesinden alınır ve çevrimdışı rotalar kapalı kalır (403).
| Rota | Not |
|---|---|
POST /login | Onaylanana kadar 202 + adım + token |
/enroll/start, /enroll/status | Oturum açmış kullanıcı; bağlı telefonu asla değiştirmez (409) |
/offline/* | Yalnız login user seçeneğiyle |
/passkey/* | Şifresiz giriş, passkey ile onay, passkey yönetimi |
Kimlik öncesi rotalar varsayılan olarak IP başına (20/dk) ve kullanıcı adı başına (5/dk) sınırlıdır.
Relay'i bağlayın
const { Touchque, touchqueRouter } = require('@touchque/node');
const tq = new Touchque(); // TQ_API_KEY / TQ_API_SECRET
app.use('/touchque', touchqueRouter(tq, {
getUserId: (req) => req.session.user, // oturum açmış kullanıcı
getLoginUser: (req) => req.session.passwordVerifiedUser, // şifre adımını geçen kullanıcı
onAuthenticated: (req, res, info) => { req.session.user = info.externalUsername; },
}));# Flask (FastAPI: touchque_relay_router, Django: touchque_relay_urls)
from touchque import Touchque
from touchque.contrib.flask import touchque_relay_blueprint
tq = Touchque() # TQ_API_KEY / TQ_API_SECRET
def opened(request, response, info):
session['user'] = info['externalUsername']
app.register_blueprint(touchque_relay_blueprint(
tq,
get_user_id=lambda req: session.get('user'),
get_login_user=lambda req: session.get('password_ok'),
on_authenticated=opened,
), url_prefix='/touchque')// Laravel — a service provider
use Illuminate\Http\Request;
use Touchque\Laravel\TouchqueRelay;
use Touchque\Relay\RelayResponse;
$this->app->singleton(TouchqueRelay::class, fn ($app) => new TouchqueRelay($app->make(\Touchque\Touchque::class), [
'getLoginUser' => fn (Request $r) => $r->session()->get('password_verified_user'),
'onAuthenticated' => function (Request $r, RelayResponse $res, array $info) {
$r->session()->regenerate();
$r->session()->put('user', $info['externalUsername']);
},
]));
// routes/web.php
TouchqueRelay::routes(app('router'), 'touchque');tq, err := touchque.New() // TQ_API_KEY / TQ_API_SECRET
if err != nil {
log.Fatal(err)
}
mux.Handle("/touchque/", http.StripPrefix("/touchque", touchque.NewRelayHandler(tq, touchque.RelayOptions{
UserID: func(r *http.Request) string { return sessionUser(r) }, // zorunlu
LoginUser: func(r *http.Request) string { return passwordVerifiedUser(r) },
OnAuthenticated: func(w http.ResponseWriter, r *http.Request, info touchque.AuthenticatedInfo) error {
return startSession(w, info.ExternalUsername)
},
})))builder.Services.AddTouchque(); // TQ_API_KEY / TQ_API_SECRET
app.MapTouchqueRelay("/touchque", new RelayOptions<HttpContext>
{
GetUserId = http => http.User.TouchqueUser(), // oturum açmış kullanıcı
GetLoginUser = http => http.Session.GetString("password_verified_user"), // şifre adımını geçen kullanıcı
OnAuthenticated = (http, response, info) => SignInAsync(http, info.ExternalUsername),
});// Spring Boot starter rotaları /touchque altında sunar (touchque.relay.path)
@Bean
RelayOptions<HttpServletRequest> touchqueRelay() {
return new RelayOptions<HttpServletRequest>(TouchqueSpring::user) // oturum açmış kullanıcı
.getLoginUser(req -> (String) req.getSession().getAttribute("password_verified_user")) // şifre adımını geçen kullanıcı
.onAuthenticated((req, response, info) -> signIn(req, info.externalUsername()));
}# config/routes.rb
mount Touchque::Rack::Relay.new(
get_user_id: ->(req) { req.session["user"] }, # oturum açmış kullanıcı
get_login_user: ->(req) { req.session["password_verified_user"] }, # şifre adımını geçen kullanıcı
on_authenticated: ->(req, _response, info) { req.session["user"] = info["externalUsername"] }
) => "/touchque"