Services and Primitives
Build custom authentication behavior from low-level services.
effect-auth models authentication capabilities as Effect services. A service tag such as PasswordLogin, Sessions, or Challenge is the typed name used to request a capability from an Effect environment. The tag describes what callers can do; it is not a global singleton and does not choose production infrastructure.
A Live layer constructs an implementation and declares its dependencies. For example, PasswordLoginLive implements PasswordLogin, while PasswordDefaultLive() assembles the password services that normally belong together. Layers let TypeScript report missing capabilities and let an application replace an implementation for a deployment or test without changing domain code.
Service families
The public surface is intentionally compositional rather than one giant auth object. Its major families are:
- Flows and factors:
AuthFlow, password, passkey, email OTP, magic link, TOTP, recovery code, and strong-factor services perform focused authentication transitions. - Sessions and challenges:
Sessions,SessionCookie, andChallengemanage durable authentication state, browser tokens, and short-lived proof state. - Policy and security:
AuthRateLimit, rate limiting, step-up, trusted-device, login-risk, permission, and guard services decide whether work may proceed. - Persistence and runtime: storage tags, crypto, secrets, configuration, mail, and
WaitUntilisolate platform-specific effects. - Account and protocol features: OAuth, API keys, machine authentication, verification, audit, security timeline, retention, and webhooks build on those foundations.
Use a focused feature layer instead of manually collecting every implementation inside a family. Its required-service type is the current dependency contract.
Kernel composition
AuthKernelLive is the shared domain kernel, not a complete application runtime. Its current composition is:
storage + crypto + secrets + config (application layers)
|
v
SessionsLive SessionCookieLive ChallengeLive PrivacyLive
\ | | /
+------ AuthKernelLive ----------------+
| |
AuthFlow AuthHttpTransport
|
v
feature layers, such as PasswordDefaultLive()
|
v
application boundaryThe kernel provides its primitive layers to AuthFlowLive and AuthHttpTransportLive with Layer.provideMerge, so their outputs remain available to feature layers. The application must still provide every dependency visible in the resulting layer type. Composition follows dependencies, not initialization order.
Calling a primitive
A primitive is appropriate when authentication is one step in an application-specific workflow and an existing HTTP operation cannot express the required orchestration. The call itself remains small:
import { PasswordLogin } from "@effect-auth/core/Password";
import { Effect, Redacted } from "effect";
const authenticate = Effect.gen(function* () {
const passwords = yield* PasswordLogin;
return yield* passwords.signIn({
identity: {
scope: { type: "global" },
kind: "email",
value: "reader@example.com",
},
password: Redacted.make("correct horse battery staple"),
});
});This produces a typed domain effect. It is not an HTTP endpoint and does not inherit the controls supplied by HTTP operations or presets.
| Concern | Primitive owns | Application owns |
|---|---|---|
| Domain behavior | Credential checks, invariants, typed domain failures | Choosing and sequencing services |
| Security | Security internal to that capability | Origin/CSRF checks, authorization, rate limits, abuse policy, and auditing |
| Errors | Typed domain error channel | Sanitization and mapping to declared public errors/statuses |
| Sessions and cookies | Explicit session operations when called | Deciding when to issue/rotate/revoke, committing every Set-Cookie, and clearing cookies |
| Transport | Nothing | Request decoding, response schemas, middleware, and client contract |
Prefer Custom API when only routes, schemas, or middleware differ: HTTP operations retain standard security, error mapping, orchestration, and cookie commitment. Drop to primitives only when the workflow itself differs.
Composition is selective per endpoint. One server may mount a preset for passkeys, bind an HTTP operation for password sign-in, and use session primitives in a bespoke recovery flow. Supply only the feature layers those paths require; there is no need to enable the entire export surface.
See Architecture for integration levels, Sessions for token lifecycle, Security for operation policy, and Testing for replacing service implementations with deterministic layers.