buildPasskeyRegistration and buildPasskeyAuthentication and a complete example function covering the full enroll → challenge → verify loop.
The examples are TypeScript + raw HTTP that map to the Authsignal API reference. See the Porting to other languages section at the end if you’re not on Node.
Prerequisites
- An Authsignal tenant with passkeys enabled
- Your API secret key (Portal → Settings → API Keys)
- A test runtime with Node.js 18+ (examples use
node:cryptoandfetch) - The origin your app uses for passkeys (e.g.
https://your-test-app.example.com)
How it works
- Enrollment: generate a key pair, package the public key as a WebAuthn attestation, and register it. Keep the private key in memory.
- Authentication: when the server issues a challenge, build a WebAuthn assertion and sign it with that same private key. The server verifies the signature against the public key it stored at enrollment.
Authentication & tokens
Every call below is one of two kinds:- Server API calls authenticate with your API secret key using HTTP Basic auth.
- Client API calls authenticate with the short-lived
tokenreturned bytrack, passed asAuthorization: Bearer TOKEN.
track an action to mint a token, then use that token for the passkey calls. The token enrolling a passkey needs permission to add authenticators, so pass scope: "add:authenticators" when tracking the enrollment action.
authsignal-client.ts
Setup
The only third-party dependency is a CBOR encoder, used to build the attestation during enrollment. The examples use@levischuck/tiny-cbor, but any spec-compliant CBOR library works. Authentication needs no CBOR at all.
passkey.ts
Enrolling a passkey
Enrollment is three steps: ask for registration options (which include the server’s challenge), build a credential, then submit it.buildPasskeyRegistration generates the key pair, encodes the public key as a COSE_Key, and assembles authenticatorData followed by a fmt: "none" attestation object. It returns the private key so you can sign assertions later.
passkey.ts
Submitting the credential
Authenticating with a passkey
Now complete a challenge with the passkey you just enrolled. Ask for authentication options, build a signed assertion, and submit it for verification. The key idea: the server verifies an ES256 signature overauthenticatorData ‖ SHA-256(clientDataJSON) using the public key captured at registration.
passkey.ts
Complete helper example
Everything together. This framework-agnostic sample gives you one function to call from atest(...) in Vitest, Jest, or any runner.
passkey-api.test.ts
Porting to other languages
The Authsignal calls are plain HTTP, so only the credential building is language-specific. Any language can do it with four primitives:- Generate an EC P-256 (secp256r1) key pair and keep the private key in memory.
- Encode the public key as a
COSE_Key: a CBOR map withkty=2,alg=-7,crv=1, and thex/ycoordinates. - Assemble
authenticatorDataand theattestationObject(fmt: "none") for registration; base64url-encode the parts. - For authentication, ES256-sign
authenticatorData ‖ SHA-256(clientDataJSON), DER-encode the signature, and base64url everything.

