Skip to content

Set up passkeys on your website

Your domain, the sign-in page origins, a registration token from your server, the browser prompt and the check before a session starts.

PasskeysUpdated 28 October 20267 min read

A passkey lets a user sign in with the fingerprint, face or screen lock they already use to unlock their phone or laptop. It is saved by Google Password Manager, iCloud Keychain or the browser for your domain, and it cannot be typed into a fake site. This guide adds passkeys to a website that already has a sign-in. It takes about 30 minutes.

How it fits together: your server asks SignOps for short-lived tokens, the browser script talks to the user’s device, and your server checks the result before starting its own session. Your login system keeps its users and sessions.

1. Enter your domain in the dashboard

In the SignOps dashboard, open Passkeys, Setup:

  1. Domain: the domain users know, such as kiranaexpress.in. No https://, no www. This is fixed once anyone has a passkey.
  2. Name in the prompt: your product name, such as Kirana Express.
  3. Page origins: every address that shows your sign-in or “add a passkey” page, such as https://kiranaexpress.in and https://app.kiranaexpress.in. They must be on the domain or a subdomain. Other origins are refused.
  4. Allow synced passkeys: leave on. Off allows only passkeys tied to one device, which users lose with the device.
  5. Choose Save and turn on.

For local development, make a second SignOps app with the domain localhost and the origin http://localhost:3000.

2. Let signed-in users add a passkey

Offer it where users expect it: right after a sign-in (“Sign in faster next time with your fingerprint”) and on the account security page.

Your server makes a registration token for the signed-in user:

// Your server
app.post("/api/passkeys/token", requireUser, async (req, res) => {
  const { token } = await signops.passkeys.registrationToken({
    user_id: req.user.id,          // your own user id
    user_name: req.user.email,     // what the user sees in their password manager
  });
  res.json({ token });
});

Your page passes it to the browser script:

import { configure, passkeys } from "https://api.signops.dev/web.js";   // or npm install @signops/web
configure({ key: "pk_live_..." });   // your publishable key

const { token } = await (await fetch("/api/passkeys/token", { method: "POST" })).json();
await passkeys.register({ token });
// The device's prompt appears; the passkey is saved for your domain.

3. Sign in with a passkey

Add webauthn to the email field’s autocomplete, so the browser offers saved passkeys as the user taps the field:

<input type="email" name="email" autocomplete="username webauthn" />
// On the sign-in page, at load
const { signops_token } = await passkeys.signIn({ autofill: true });
await fetch("/api/passkeys/signin", { method: "POST", body: JSON.stringify({ signops_token }) });

Add a Sign in with a passkey button that calls passkeys.signIn() without autofill, for browsers that do not offer autofill.

4. Check the token on your server

The token proves nothing until your server confirms it. Never start a session from the browser’s word alone.

app.post("/api/passkeys/signin", async (req, res) => {
  const r = await signops.passkeys.verify(req.body.signops_token);
  if (!r.valid) return res.status(401).end();
  startSession(res, r.user_id);   // your own session, as after a password
  res.json({ ok: true });
});

A token works once and only for a short time, so a copied token cannot be replayed.

5. Try it

If you cannot reach your own site yet, the dashboard’s Try it here works on a test app with the domain signops.dev and the origin https://app.signops.dev. On your site: add a passkey, sign out, and sign in again by tapping the email field. Check what your browser supports with the passkey checker.

Then manage what you made: Users in the dashboard lists each user’s passkeys, and DELETE /v1/passkeys/:id removes one (for a “Remove this passkey” button on your security page).

Next

Frequently asked questions

More questions? Email us and the answer goes on this page.

hello@signops.dev
Which domain should I enter?

The domain users know, without www, such as kiranaexpress.in. Passkeys made for it work on the domain and every subdomain (www, app, accounts). It cannot change once users have passkeys, because each passkey is tied to it.

Can I test passkeys on localhost?

Yes. Make a separate SignOps app for development with the domain localhost and an origin such as http://localhost:3000. Keep your real domain on the live app.

Does SignOps show its own name to users?

No. The browser's prompt shows your domain and the name you enter in the dashboard. There is no hosted login page.

What if a user's device has no passkey support?

Keep your current sign-in as the fallback. Passkeys sit next to it; they do not replace it until you decide they should.

Send your first push today.

Free for 1,000 push devices, 100 approvals and 1,000 passkey sign-ins a month, and 500 email codes to try. No card until you pass a free amount.