Custom flows give you headless control of authentication. You call the identity APIs and SDK primitives yourself, and you build the sign-in experience. Use this when the Account Portal and components can't express the UI or the logic you need.
When to go headless
Most apps are fine with the hosted portal or the embeddable components. Choose a custom flow when those can't meet the requirement: a sign-in UI that has to match a specific design, a multi-step onboarding that isn't the standard one, tight integration with your own state, or a native surface where you want to own every screen.
You take on the UI, the error handling, the MFA and step-up prompts, and the correctness of the flow. Authdog still issues and validates the session. The experience around it is yours.
The primitives
A headless flow is built from a few primitives that mirror what the portal and components do internally:
- Start sign-in: begin authentication for a chosen connection (credentials, social, or SSO) and drive any challenges (including MFA) yourself.
- Handle the callback: receive the result of the authentication step and exchange it for a session.
- Establish the session: set the
authdog-sessionfor the environment so the browser and your backend can use it. - Sign out: clear the session.
Illustrative shape
The precise API surface depends on your SDK; with the framework-agnostic browser client it looks like:
import { createAuthdogClient } from "@authdog/javascript";
const authdog = createAuthdogClient({ publicKey: PK_AUTHDOG });
// 1. Kick off sign-in (redirects to the identity flow)
authdog.signIn();
// 2. On return, consume the callback and persist the session
authdog.handleRedirectCallback();
// ...later
authdog.signOut("/");Validating the session
Once the authdog-session exists, validation is the same no matter how you created it. See Sessions and tokens. Your server enforces it on protected routes, as described in Backend requests. If you're rebuilding UI the SDK already ships, drop back to components for those screens.