Wocha Docs

BYO UI (bring your own forms)

Tier C — own credential UI for registration, login, MFA, recovery, and verification while keeping Code+PKCE.

Wocha supports three integration tiers for authentication UI:

TierNameWhat you build
AHosted Universal LoginRedirect to id.wocha.ai
BHeadless redirectOwn buttons/chrome via @wocha/react / @wocha/ui — still redirects to hosted Auth
CTrue BYOOwn forms that call BFF → Auth /api/auth/byo/* → Code+PKCE

This guide covers Tier C. Full contract: byo-ui.md in the monorepo.

Requirements

  • First-party OAuth client (FIRST_PARTY_CLIENT_IDS)
  • Confidential BFF (WOCHA_CLIENT_ID / WOCHA_CLIENT_SECRET / WOCHA_ISSUER)
  • Optional WOCHA_AUTH_URL (defaults oauth.*id.*)

BFF routes (@wocha/nextjs, Remix, SvelteKit, Nuxt)

RouteMethodStage
{authBasePath}/loginGETHosted OAuth start
{authBasePath}/loginPOSTBYO password login
{authBasePath}/registerPOSTBYO registration
{authBasePath}/mfa/verifyPOSTBYO MFA (TOTP / backup codes)
{authBasePath}/recoveryPOSTForgot password (action: start | complete)
{authBasePath}/verificationPOSTEmail verification
{authBasePath}/passkey/continuePOSTPasskey session → OAuth continue

After a successful credential stage the BFF returns { continueUrl } and sets the PKCE cookie. Navigate the browser to continueUrl (full page) to finish Code+PKCE.

Example — BYO login

async function onSubmit(email: string, password: string) {
  const res = await fetch("/api/auth/login", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email, password, return_to: "/portal" }),
  });
  const data = await res.json();
 
  if (data.status === "mfa_required") {
    // Show TOTP form; then POST /api/auth/mfa/verify with challengeToken + code
    return data;
  }
 
  if (data.continueUrl) {
    window.location.href = data.continueUrl;
  }
}

Password change (signed-in)

Use the Account API via @wocha/react / @wocha/ui:

const { changePassword } = useProfile();
await changePassword(currentPassword, newPassword);

What stays hosted

Social/OIDC buttons, third-party consent, OAuth org-select, and forced policy settings remain on Auth. First-party clients skip consent automatically.

On this page