import { Hex } from 'ox' import { Credential as Credential_, Registration, type Types } from 'ox/webauthn' import * as Aaguid from './Aaguid.js' /** Credential. */ export type Credential = Credential_.Credential /** Credential creation options. */ export type Options = Types.CredentialCreationOptions /** Registration response. */ export type Response = Registration.Response & { aaguid: string | undefined } /** * Generates serialized `PublicKeyCredentialCreationOptions` for registration. * * A random 32-byte challenge is generated by default. The challenge is * returned alongside the options so it can be stored for later verification. * * @example * ```ts * import { Registration } from 'webauthx/server' * * async function handler(request: Request) { * const { challenge, options } = Registration.getOptions({ * name: 'alice', * rp: { id: 'example.com', name: 'Example' }, * }) * await db.storeChallenge(challenge) * return Response.json(options) * } * ``` */ export function getOptions(options: getOptions.Options = {}): getOptions.ReturnType { const challenge = options.challenge ?? Hex.random(32) const serialized = Registration.serializeOptions( Registration.getOptions({ ...options, challenge } as Registration.getOptions.Options), ) return { challenge, options: serialized } } export declare namespace getOptions { type Options = Omit & { challenge?: Hex.Hex | undefined } type ReturnType = { challenge: Hex.Hex options: Types.CredentialCreationOptions } type ErrorType = Registration.getOptions.ErrorType | Registration.serializeOptions.ErrorType } /** * Verifies a serialized registration response from the client. * * Deserializes the credential, then validates the attestation object, * rpIdHash, challenge, origin, and extracts the P256 public key. * * @example * ```ts * import { Registration } from 'webauthx/server' * * async function handler(request: Request) { * const credential = await request.json() * const result = Registration.verify(credential, { * challenge, * origin: 'https://example.com', * rpId: 'example.com', * }) * } * ``` */ export function verify(credential: Credential, options: verify.Options): Response { const deserialized = Credential_.deserialize(credential) const result = Registration.verify({ ...options, credential: deserialized }) return { ...Registration.serializeResponse(result), aaguid: Aaguid.extract(credential), } } export declare namespace verify { type Options = Omit type ErrorType = | Registration.verify.ErrorType | Credential_.deserialize.ErrorType | Credential_.serialize.ErrorType }