first commit
This commit is contained in:
74
docs/identity/auth/webauthn/src/schemas/schemas.md
Normal file
74
docs/identity/auth/webauthn/src/schemas/schemas.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# WebAuthn — boundary schemas
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Defines the Zod schemas wired at every public surface of `@suaveplan/webauthn`. They serve as the structural contract for caller-supplied options (`register`, `authenticate`) and for the parsed shapes the package returns (`ParsedAuthData`, `ParsedAttestationStmt`, `ClientDataJSON`, `CoseKey`). The schemas are the single typed boundary between untrusted byte input and the production validation pipeline.
|
||||
|
||||
## Features
|
||||
|
||||
- Strict caller-option shapes for `register` and `authenticate`.
|
||||
- Forward-compatible `passthrough()` on every authenticator-produced structure so an authenticator that emits extra metadata does not break parsing.
|
||||
- Constrained literal unions for `attestation`, `userVerification`, `mediation`, `residentKey`, and the per-format dispatchers so a mistyped enum surfaces at the boundary.
|
||||
- Discriminated `largeBlob` authenticate input (`read: true` xor `write: Uint8Array`) so the verifier can branch on the shape without re-validating.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { WebAuthnRegisterOptionsSchema } from "@suaveplan/webauthn";
|
||||
|
||||
const parsed = WebAuthnRegisterOptionsSchema.parse({
|
||||
rp: { name: "example.com" },
|
||||
user: { id: new Uint8Array(16), name: "u", displayName: "U" },
|
||||
challenge: new Uint8Array(32),
|
||||
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
|
||||
expectedOrigin: "https://example.com",
|
||||
expectedRpIdHash: new Uint8Array(32),
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
ParsedAuthDataSchema,
|
||||
WebAuthnAuthenticateOptionsSchema,
|
||||
} from "@suaveplan/webauthn";
|
||||
|
||||
function validate(unsafe: unknown) {
|
||||
const opts = WebAuthnAuthenticateOptionsSchema.parse(unsafe);
|
||||
return opts;
|
||||
}
|
||||
const auth = ParsedAuthDataSchema.parse({
|
||||
rpIdHash: new Uint8Array(32),
|
||||
flags: {
|
||||
userPresent: true,
|
||||
userVerified: false,
|
||||
backupEligible: false,
|
||||
backupState: false,
|
||||
attestedCredentialData: false,
|
||||
extensionsPresent: false,
|
||||
},
|
||||
flagsByte: 0x01,
|
||||
signCount: 0,
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `ClientDataJSONSchema` — pinned `type`, `challenge`, `origin`; passthrough.
|
||||
- `CoseKeySchema` — pinned `kty` (int); optional `alg`, `crv`, `x`, `y`, `n`, `e`, `k`; passthrough.
|
||||
- `ParsedAuthDataFlagsSchema` — six booleans per W3C L3 §6.1.
|
||||
- `ParsedAuthDataSchema` — fixed prefix + optional attested-credential-data + optional extensions.
|
||||
- `ParsedAttestationStmtSchema` — `fmt: string`, `attStmt: Record<string, unknown>`.
|
||||
- `WebAuthnRegisterOptionsSchema`, `WebAuthnAuthenticateOptionsSchema` — caller options.
|
||||
- `PrfRegisterInputSchema`, `PrfAuthenticateInputSchema`, `LargeBlobRegisterInputSchema`, `LargeBlobAuthenticateInputSchema` — extension inputs.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- COSE_Key fields outside the RFC 9052 §7 minimum set are kept on the parsed object via `passthrough()` so a verifier can reach into vendor extensions when needed. The structural type narrowing happens in `parser/cose-key.ts` where the discriminated `kty` arms (`EC2`, `OKP`, `RSA`, `Symmetric`) are produced.
|
||||
- `WebAuthnRegisterOptionsSchema` deliberately marks `attestation` as optional; the W3C default is `"none"` and the production code applies that default before forwarding to the adapter.
|
||||
- `LargeBlobAuthenticateInputSchema` is a `z.union` of `{ read: true }` xor `{ write: Uint8Array }` so callers cannot request both simultaneously — the same constraint W3C §10.1.3 imposes.
|
||||
- Every options schema accepts a caller-side `Uint8Array` instance check rather than `Buffer`. This is universal — `Buffer` would not load in browsers.
|
||||
Reference in New Issue
Block a user