Knock docs

Reading the index…

door-sdk

Every export of @knock-dev/door-sdk, the knock it returns field by field, and the messages it and the Door send each other.

Markdown

@knock-dev/door-sdk is the browser side of Knock: one TypeScript file with no dependencies, in packages/door-sdk/src/index.ts. It needs a browser, since it opens a window.

TypeScript
import { DOOR, type Assertion, type Hex, KnockError, type KnockOptions, knock } from '@knock-dev/door-sdk'

Get it

It isn't on npm yet. Use it from a checkout of getknock/knock, in one of three ways:

  • Import it from the checkout, as the quickstart does: from '../knock/packages/door-sdk/src/index.ts'.
  • Copy the file into your project, such as src/door-sdk.ts, and import from it.
  • In a workspace with Knock's packages, add "@knock-dev/door-sdk": "workspace:*" to your dependencies. With Next.js, also add transpilePackages: ['@knock-dev/door-sdk'] to next.config.ts, since the package ships TypeScript.

knock()

TypeScript
function knock(options: KnockOptions): Promise<Assertion>

Opens the Door and resolves with the knock the Wedgie signed, or rejects with a KnockError. Call it from a click: it opens the Door straight away, and browsers allow that only while they're handling a click.

In order, knock():

  1. opens <door>/knock in a popup window named knock-door, 420 by 680 pixels, or rejects with blocked;
  2. waits for the Door's knock/ready, and for your challenge, whichever comes last;
  3. checks the challenge is 0x and 64 hex digits, or rejects with challenge;
  4. posts knock/request to the Door, addressed to the Door's origin only;
  5. resolves with the knock/result's assertion, or rejects with its error.

It rejects with closed if the popup is closed first, and with timeout, closing the popup, if timeoutMs passes. It takes messages only from the popup it opened, at the Door's origin.

KnockOptions

TypeScript
type KnockOptions = {
  challenge: Hex | Promise<Hex>
  mode?: 1
  door?: string
  timeoutMs?: number
}
FieldDefaultWhat it is
challengeRequiredYour verifier's challenge from POST /challenge, or a promise of it. With a promise, the Door opens at once and gets the challenge when it arrives.
mode1Bound: the human comes from the Wedgie's binding. Mode 2, Fresh, isn't offered.
doorDOORThe Door's URL. Only its origin is used: the popup opens at /knock there.
timeoutMs180000How long the whole knock may take, presses included. The Wedgie itself gives up after 2 minutes without a press.

Assertion

The knock, as the Wedgie signed it and the Door handed it over. Send it to your verifier as it is, and trust none of it until the verifier says ok.

TypeScript
type Assertion = {
  v: 1
  name: string
  challenge: Hex
  origin: string
  deviceNode: Hex
  counter: number
  mode: 1
  nullifier: Hex
  humanRef: Hex
  r: Hex
  s: Hex
}
FieldWhat it is
vThe format's version: 1.
nameThe ENS name the Wedgie knocks as, such as wedgie.itzraj.eth.
challengeYour verifier's challenge, 32 bytes.
originYour page's origin, as the Door read it from the browser.
deviceNodeThe name's ENS namehash.
counterThe Wedgie's knock counter. It rises with each knock, on any site.
mode1, Bound.
nullifierThe human's nullifier, 32 bytes, as the Wedgie holds it. Check 6 compares it with the name's ENS records.
humanRef32 zero bytes in mode 1.
r, sThe Wedgie's P-256 signature over the knock's KnockPass digest, s low.

The protocol page says how the digest is made.

KnockError

TypeScript
class KnockError extends Error {
  readonly code: string
}

Why there was no knock. code is for your code, and message is a sentence you can show people.

codeFromMeaning
blockeddoor-sdkThe browser didn't open the popup.
closeddoor-sdkThe popup was closed before a knock.
timeoutdoor-sdktimeoutMs passed.
challengedoor-sdkThe challenge's promise rejected, or it isn't 0x and 64 hex digits.
refuseddoor-sdkThe Door said no without a code.
rejectedThe DoorRed on the Wedgie.
timeoutThe DoorNobody pressed on the Wedgie within 2 minutes.
not_enrolledThe DoorThe Wedgie has no name, or isn't bound to a human.
not_readyThe DoorThe Door couldn't talk to the Wedgie.
bad_originThe DoorThe page isn't on https://, or localhost or 127.0.0.1 for development.
bad_requestThe DoorThe challenge or mode was wrong, or the Wedgie couldn't read the request.
bad_signatureThe DoorThe Wedgie's knock didn't hold for this site and challenge, so nothing was sent.
no_keyThe Wedgie, through the DoorThe Wedgie has no Knock key yet.

The Door passes the Wedgie's other codes on as they are. Add a Knock button says what to show for each.

DOOR

TypeScript
const DOOR = 'https://door.getknock.dev'

The Door that door-sdk opens unless you pass door: Knock's own. To use one you serve yourself, pass its address as door.

Hex

TypeScript
type Hex = `0x${string}`

The messages

door-sdk and the Door talk with postMessage. You only need these if you write your own client.

MessageFrom, toSent toBody
knock/readyDoor to your pageAny origin{ type: 'knock/ready' }. It says only that the Door is up.
knock/requestYour page to the DoorThe Door's origin{ type: 'knock/request', challenge, mode: 1 }
knock/resultDoor to your pageYour page's origin{ type: 'knock/result', ok: true, assertion }, or { type: 'knock/result', ok: false, error, why }

The Door:

  • takes a request only from the window that opened it, and reads that window's origin from the browser, as the message's origin;
  • answers once, and only to that origin;
  • takes one request, and closes itself a moment after a knock;
  • refuses to work inside a frame.