UI Components
What ships in @rebellion-systems/authensee-ui — primitives, question inputs, SDK React glue, and turnkey flows. How to compose them.
UI Components
The @rebellion-systems/authensee-ui package is a thin React component library that pairs with the SDK. These components drive the on-device ceremony and are what the AuthenSee hosted pages render; they're published for AuthenSee's first-party surfaces and React Native parity. Two composition styles:
- Turnkey — drop in
<EnrollmentFlow>/<AuthenticationFlow>and get a styled multi-step UI for free. - Composed — wrap your app in
<AuthenSeeProvider>and assemble your own flows from the primitives + question inputs.
First-party / hosted-runtime components. Like the SDK methods, these only work served from AuthenSee's own origin. If you're integrating from your own app, use the hosted popup instead — see the embed guide.
Hosted pages (auth.authensee.com) uses the composed path because it has its own brand chrome and demo routes — but anyone integrating AuthenSee can pick whichever path fits their UX.
Install
Use the embed package from your browser app to launch the hosted flow:
What's in the package
Everything is themeable via the same AuthenSeeTheme shape — see the theming guide for full details.
Theme
The theme provider plumbs CSS custom properties (--authensee-primary, etc.) into the DOM so every component picks up your brand colors without prop drilling.
AuthenSeeProvider wraps both the theme provider and the SDK provider. If you only want the theme (e.g., to style a marketing page that doesn't need the SDK), use AuthenSeeThemeProvider directly.
Default theme is the orange/black brand palette mirroring authensee.com; themeToCssVars() is exported if you need to compute the variable map yourself.
Primitives
Brand-styled brutalist building blocks. Every primitive responds to the active theme via CSS variables.
| Component | Purpose | Key props |
|---|---|---|
<Button> | Primary / secondary / ghost actions | variant, size, loading, disabled, onClick |
<Card> | Content panel with brand border + padding | className, children |
<ProgressBar> | Step indicator (1 of N) | current, total, label |
<Logo> | The AuthenSee mark; respects theme.logoSrc override | className, alt |
<ErrorDisplay> | Structured error rendering keyed on AuthenSeeErrorCode | code, message, onRetry |
<SuccessDisplay> | Success state | title, message |
Example:
Question inputs
One component per QuestionTypeId. Each component takes a questionText (optional prompt label) and an onChange(answer | null) callback. The callback fires with the typed AnswerData discriminated union — pass that straight into sdk.enroll() / sdk.authenticate().
| Component | QuestionTypeId | Captures |
|---|---|---|
<TextInput> | EPISODIC_TEXT (1) | Free-text answer (autocomplete/spellcheck off — answers are sensitive) |
<RecognitionGrid> | RECOGNITION (2) | One of N option tiles (with optional images) |
<DoodleCanvas> | DOODLE (3) | A 16×16 bitmap drawing |
<SequenceInput> | SEQUENCE (4) | Ordered list of symbol IDs |
<MapPicker> | MAP_ROUTE (8) | Four (lat, lng) points rasterized to Web Mercator buckets |
If you don't know the typeId at compile time (e.g., it comes from a server-driven question schema), use the dispatcher:
It picks the right concrete component from the typeId.
SDK glue
Three hooks/contexts that connect the UI to the underlying SDK class:
<AuthenSeeProvider>
Wraps your tree. Initialises an AuthenSee SDK instance with the sessionToken you pass in and exposes it via context. Composing also sets up theme + state for proof-progress events.
useAuthenSee()
Returns { sdk, isInitialized, persona, error } from anywhere in the tree:
useProofProgress()
Subscribes to proof.generating / proof.complete / auth.success / auth.failure events emitted by the SDK and exposes them as React state — useful for spinners, progress bars, and lifecycle UX.
Turnkey flows
Multi-step orchestrators that compose the primitives + question inputs + SDK calls + WebAuthn ceremony into a single ready-to-drop-in UI. Two are exported:
<EnrollmentFlow>— walks the user through their question, runs the WebAuthn registration ceremony, callssdk.enroll()with the aggregate scheme commitment.<AuthenticationFlow>— re-asks the user's question, drives the WebAuthn assertion via the SDK's callback, callssdk.authenticate().
Plus <QuestionStep>, the building block both flows use internally if you want to assemble your own multi-step.
Both flows take a passkey: PasskeyHandlers prop. The fastest way to get one is the browserPasskey() factory from the /passkey sub-path:
<AuthenticationFlow> takes the same passkey object — the flow uses passkey.sign instead of passkey.create:
For V1 the question list must contain exactly one question (the passkey_question_v1 scheme aggregates one answer + one passkey signature in the same proof). Multi-question schemes will be a future scheme/circuit pair, not a backward-compatible knob.
browserPasskey() — the default browser ceremony
Returns a single PasskeyHandlers object exposing both .create (registration) and .sign (authentication). The implementation:
- Builds
PublicKeyCredentialCreationOptions/RequestOptionswithuserVerification: "required"(the V1 circuit asserts the UV bit). - Pulls the P-256 public key out of the SPKI bytes returned by
getPublicKey(). - Parses the DER-encoded ECDSA signature into raw
r || sand applies low-s normalisation (the V1 verifier rejects high-s).
Lives on a separate sub-path so the DOM-bound code doesn't get pulled into the main bundle for non-browser callers (React Native, SSR-only consumers).
Custom ceremonies
For non-browser runtimes (React Native), custom RP layouts, or any other reason you'd want to bypass browserPasskey, implement the PasskeyHandlers interface directly. The types are re-exported from the main barrel:
Composed pattern
If you want full control over layout — a multi-step wizard that doesn't fit the turnkey shape, custom progress chrome, etc. — wrap with <AuthenSeeProvider> and drop in the primitives + question inputs yourself. Hosted-pages (auth.authensee.com) uses this pattern because it has its own brand UX.
For authentication, replace passkey.create with passkey.sign and pass it through to sdk.authenticate({ answers, passkey: { sign: passkey.sign } }).
Where things ship
| Concern | Lives in | Why |
|---|---|---|
| Hosted-flow launch and callback relay | @rebellion-systems/authensee-embed | Provider-facing browser integration |
| Provider session creation and result exchange | @rebellion-systems/authensee-sdk | Server-only provider SDK |
| Theme tokens, primitives, question inputs, turnkey flows | AuthenSee hosted runtime | Operated by AuthenSee for hosted flows |
WebAuthn DOM helpers (navigator.credentials.create / .get) | @rebellion-systems/authensee-ui/passkey (browser) — or your own implementation of PasskeyHandlers for other runtimes | Centralised so the byte-level WebAuthn parsing (DER, SPKI, low-s normalisation) lives in one place; the sub-path keeps DOM code out of non-browser bundles |
| Session validation, demo launching, hosted-pages routing | authnc-hosted-pages (private to AuthenSee) | Service-specific to the operated reference deployment. Not published as a library. |
React Native
React Native runtime components are not a public provider integration surface yet. Mobile providers should launch hosted flows and exchange result codes from their backend, matching the hosted-pages model.