Browser Client
Call typed authentication endpoints from browser applications.
createAuthClient is the browser-facing client for the standard effect-auth HTTP contract. It is exported from @effect-auth/core/Client and returns Promise-based operations suitable for UI code, query libraries, and framework actions.
The client and server contract are two views of the same schemas: AuthClientProtocolApi defines endpoint paths, payloads, successful responses, and public errors; the client validates inputs, calls those endpoints, and decodes responses. This catches contract drift instead of treating JSON as unknown. It does not discover application routes at runtime. See Architecture for where the HTTP contract sits relative to operations and primitives.
Browser UI -> createAuthClient -> AuthClientProtocolApi contract -> auth HTTP server
typed input encoded request session cookie
decoded result <- decoded response <-------+Create a client
For an application that proxies /auth/* on its own origin, no configuration is required:
import { createAuthClient, isAuthApiError } from "@effect-auth/core/Client";
export const auth = createAuthClient();createAuthClient accepts:
baseUrl: an absolute server origin or URL base. Omit it for relative, same-origin requests.requestInit: defaults merged into every request. The built-in default is{ credentials: "include" }.fetch: a replacementfetch, useful for platform integration or tests.browser.passkey: browser credential overrides used by the high-level passkey methods.protocol: typed overrides, removals, and extensions described below.
The client owns an Effect managed runtime. Call await auth.dispose() when the client has a shorter lifetime than the page or application.
Effect applications can use makeAuthHttpClient instead. It returns the generated AuthClientProtocolApi client in an Effect requiring HttpClient, so the application owns transport, interruption, tracing, and lifecycle. This lower-level client uses contract-shaped calls such as client.password.signIn({ payload }); createAuthClient remains the recommended Promise facade for browser UI code and adds ergonomic workflows such as passkey orchestration.
import { makeAuthHttpClient } from "@effect-auth/core/Client";
import { Effect } from "effect";
import { FetchHttpClient } from "effect/unstable/http";
const program = Effect.gen(function* () {
const client = yield* makeAuthHttpClient({
baseUrl: "https://auth.example.com",
});
return yield* client.session.current();
}).pipe(Effect.provide(FetchHttpClient.layer));Cookies and origins
Same-origin deployment is the simplest: leave baseUrl unset and serve or proxy the auth routes from the application's origin. Requests include cookies by default.
For a separate auth origin, set baseUrl and retain credentials: "include". The server boundary must also return appropriate credentialed CORS headers, allow the browser application's origin, and issue cookies whose SameSite, Secure, domain, and path attributes permit the deployment. effect-auth's allowed-origin checks provide request-origin/CSRF protection; they do not configure CORS. Avoid changing credentials unless the endpoint intentionally does not use the browser session.
export const auth = createAuthClient({
baseUrl: "https://auth.example.com",
requestInit: { credentials: "include" },
});Method groups
Methods follow the feature model rather than exposing raw URLs.
| Group | Representative operations |
|---|---|
password, email, emailOtp, magicLink | sign in/up, reset, start and verify |
session | current, refresh, logout, list, revoke |
passkey, totp, recoveryCodes | enroll/register, verify, list, revoke |
mfa, stepUp, loginApproval | continue or strengthen an auth flow |
emailVerification, security | verify email, report a login |
Feature-specific standalone clients are also exported from @effect-auth/core/Client, including createIdentityClient, createPasskeyClient, createTotpClient, and clients for OAuth, API keys, JWTs, trusted devices, security timelines, and administrative operations. createAdminPermissionDefinitionClient calls the separately mounted permission-definition lifecycle API and exposes definitions.create/get/list/update/disable/enable/delete; list accepts bounded keyset pagination with after and limit. The unified client exposes the same identity settings calls under auth.identities, but intentionally does not include permission administration. Use the unified client for normal browser auth; use a standalone client when you need that narrower contract.
Results, failures, and cancellation
Authentication can succeed without being complete. Password, email OTP, and magic-link verification return a discriminated result whose type can be authenticated, requires_mfa, requires_email_verification, requires_login_approval, or requires_passkey_enrollment. These continuation values are successful responses, not exceptions. Preserve their flowId and other fields and route the user through the corresponding client group. The Password guide shows exhaustive handling.
Failed HTTP responses reject the Promise with decoded public error objects. Narrow them with isAuthApiError, display a safe message with authClientErrorMessage, and obtain the mapped status with authClientErrorStatus. Schema/decode, network, and browser errors are not auth API errors, so keep an unknown fallback.
try {
return await auth.password.signIn({
identity: { scope: { type: "global" }, kind: "email", value: email },
password,
});
} catch (error) {
if (isAuthApiError(error)) console.error(error.code);
throw error;
}Every asynchronous operation accepts { signal?: AbortSignal } as its final argument. Cancellation interrupts the Effect execution and underlying fetch; this integrates directly with query libraries:
queryFn: ({ signal }) => auth.session.currentOrUndefined({ signal });currentOrUndefined converts only the typed unauthenticated response to undefined; other failures still reject.
Extensions and custom endpoints
protocol can replace a built-in operation, remove a group with null, or add local operations. For a custom HTTP endpoint, local functions alone provide no contract typing or response decoding. Define an Effect HttpApi, wrap it with defineAuthHttpApiExtension, and place that extension under protocol.extensions; the resulting operations share the client's base URL, fetch layer, request defaults, cancellation, and lifecycle.
Use overrides deliberately: replacing or removing standard operations means the browser contract no longer mirrors the standard AuthClientProtocolApi. Application-specific server endpoints always require a corresponding custom client extension (or a separately implemented client); createAuthClient cannot infer them.
Continue with the Quick Start, Architecture, or Password authentication.