---
title: "Services and Primitives"
url: "https://effect-auth.itsbroly.com/concepts/primitives/"
description: "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 [#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`, and `Challenge` manage 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 `WaitUntil` isolate 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 [#kernel-composition]

`AuthKernelLive` is the shared domain kernel, not a complete application runtime. Its current composition is:

```text
storage + crypto + secrets + config (application layers)
                     |
                     v
 SessionsLive  SessionCookieLive  ChallengeLive  PrivacyLive
          \          |                |          /
           +------ AuthKernelLive ----------------+
                   |             |
               AuthFlow    AuthHttpTransport
                   |
                   v
       feature layers, such as PasswordDefaultLive()
                   |
                   v
             application boundary
```

The 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 [#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:

```ts
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](/guides/custom-auth-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](/concepts/architecture/) for integration levels, [Sessions](/concepts/sessions/) for token lifecycle, [Security](/concepts/security-policies/) for operation policy, and [Testing](/guides/testing/) for replacing service implementations with deterministic layers.

