Quickstart
Add Login with TruthID to your backend: create a challenge, show a QR code, and verify the signed response.
Add "Login with TruthID" to your backend: create a challenge, show it as a QR code, and verify the signed response that comes back from the user's phone. Check the prerequisites first — you'll need a backend that can receive an HTTPS POST.
1. Install the SDK
npm install truthid-sdk2. Create a challenge
A challenge is what gets embedded in the QR code on your login page. It's single-use and expires after 30 seconds — create it on demand, right before rendering the QR code.
import { TruthIDClient } from "truthid-sdk";
const truthid = new TruthIDClient({ network: "base-mainnet" });
const pendingChallenges = new Map(); // any store with a TTL works
app.get("/auth/challenge", (req, res) => {
const challenge = truthid.createChallenge(req.hostname);
pendingChallenges.set(challenge.nonce, challenge);
res.json({
action: "truthid-auth",
challenge,
callbackUrl: `https://${req.hostname}/auth/verify`,
});
});3. Render the QR code
Your frontend turns that JSON response into a QR code — any QR rendering library works, server-side or client-side. The TruthID mobile app expects this exact shape:
{
"action": "truthid-auth",
"challenge": { "type": "challenge", "nonce": "...", "issuedAt": 1718000000000, "origin": "yoursite.com" },
"callbackUrl": "https://yoursite.com/auth/verify"
}callbackUrl must be https:// — the mobile app refuses to send the signed response anywhere else.
4. Verify the response
When the user approves on their phone, it POSTs straight to callbackUrl — no server in between. verifyAuthResponse checks the signature and reads the device's status from the blockchain.
app.post("/auth/verify", async (req, res) => {
const response = req.body;
const challenge = pendingChallenges.get(response.nonce);
if (!challenge) return res.status(400).json({ error: "Challenge not found or already used" });
pendingChallenges.delete(response.nonce); // prevents replay
const result = await truthid.verifyAuthResponse({ challenge, response });
if (!result.valid) return res.status(401).json({ error: result.reason });
res.json({ identityId: result.identityId!.toString() });
});That's the whole backend integration. Full runnable examples (Express, Flask, Sinatra) with session tokens and a protected route are in the SDK reference.
Session visibility — nothing to do
Completed logins already show up in the user's TruthID mobile/desktop apps and can be individually revoked from there. The phone registers the session on-chain itself (via a UserOperation) before it ever calls your /auth/verify endpoint — there's no relayer to fund and no separate registration step. See the SDK reference (TypeScript, Python, Ruby) if you want to double-check a session landed on-chain via verifySession.
5. Test it with a real device
To actually scan a QR code and approve a login, you need:
- A TruthID identity — created once with any EVM wallet on Base.
- A trusted device paired to that identity — the desktop app or the mobile app.
Download the desktop app and the browser extension from the TruthID landing page — pre-built installers for Linux, Windows, macOS (Apple Silicon), and an Android APK.
Two things that trip people up on the first try:
callbackUrlmust be reachable from the internet over HTTPS —localhostwon't work. Use a tunnel (e.g.ngrok http 3000) during development.- The challenge expires in 30 seconds, so generate it right before showing the QR code, not ahead of time.
Next steps
- Full API reference: SDK Reference (TypeScript, Python, Ruby)
- How TruthID Works — the full protocol behind what you just called
- Desktop / Mobile — what the "real device" in step 5 actually is
- Smart contract addresses: Smart contracts in the introduction
- Security model — what TruthID protects against, and what it doesn't