Phishing resistance
End-to-end encryption protects the link between the phone and Touchque. Phishing attacks the link between the user's browser and your site: a look-alike domain forwards everything to the real one. NIST SP 800-63B-4 only counts methods whose output is cryptographically bound to the site's address as phishing-resistant; in Touchque that is the passkey.
| Method | Phishing-resistant | Why |
|---|---|---|
| Passkey | Yes | The browser signs your site's real address; a look-alike site cannot use the signature. |
| Push + number matching | No (AAL2) | A real-time proxy can show the real number. Stops push fatigue, not relays. |
| Offline QR code | No (AAL2) | The user types the code, so a proxy can forward it. Binds amount and payee. |
| Time-based / recovery code | No | Typed codes can be relayed within their lifetime. |
1) App user policy → "Passkeys on your site": enter your domain (RP ID) and sign-in page origins. 2) Users register a passkey. 3) Optionally require a passkey for critical actions: no push is sent for them and the response has requiresPasskey: true. 4) Before treating a session as high-assurance, check assurance.phishingResistant in the status/webhook.
The Touchque app is a passkey provider (iOS 17+). Users can save passkeys to Touchque; to sign in on a computer they scan the browser's QR code with their iPhone and approve with Bluetooth proximity and Face ID. The key stays in the phone's Secure Enclave. No extra code on your side; these passkeys are stored as device-bound and labelled "Touchque".
When a passkey is required
const { Touchque, TouchquePasskeyRequiredError } = require('@touchque/node');
try {
await tq.login.verify({ externalUsername, type: 'WITHDRAW', details });
} catch (err) {
if (err instanceof TouchquePasskeyRequiredError) {
// browser: await tq.passkeys.approveLogin({ requestId: err.requestId })
return res.status(409).json({ passkeyRequired: true, requestId: err.requestId });
}
throw err;
}Status / webhook
{
"status": "CONFIRMED",
"confirmedVia": "WEBAUTHN",
"assurance": { "phishingResistant": true, "method": "passkey" }
}