hor-cookie-authentication · v2026.08.18 · 2026-10-16 · sha256 d237c58a986f26bb
hor-cookie-authentication v2026.08.18A
Immutable. This exact content never changes and is served at /api/v1/blob/d237c58a986f26bb.
--- name: hor-cookie-authentication description: "Password sign-in with cookie-based sessions for a renchan backend, per actor: the credential and token models (password hash, access + rotating refresh tokens with reuse detection), the refresh-token HttpOnly cookie, the signIn / signUp / signOut / renewAccessToken resolvers, and the engine's public-operation policy. Use when adding password auth to an actor/role. Boundary: external identity provider sign-in and other credential routes have their own conventions." metadata: author: OpenReachTech version: "2026.08.18" --- # Cookie Authentication (Backend) Use this skill when adding **password sign-in** with cookie-based sessions to a renchan backend: storing an actor's credential and tokens, the sign-in / sign-out / renew operations, the refresh-token cookie, and deciding which operations are public. An authenticated actor (a role such as `user`, `customer`, `admin`, or `tenant`) keeps its password as a hash and authenticates with two tokens: a short-lived **access token** the client sends as a header, and a long-lived **refresh token** kept in the DB and handed to the browser as an **HttpOnly cookie**. `signIn` issues both; `renewAccessToken` reads the cookie, rotates the refresh token (detecting reuse of a retired one), and returns a fresh access token; `signOut` revokes the series and clears the cookie. Only `renewAccessToken` and `signOut` authenticate by the cookie — every other operation authenticates by the access-token header. This skill covers the password route only. An actor who signs in at an external OpenID Connect provider follows `/hor-oidc-sign-in`, which ends where this skill's session begins and reuses it unchanged. A request that carries its credential in a cookie, a Bearer header, an IAP JWT or an HMAC signature instead of `x-renchan-access-token`, and an application behind IAP that has no sign-in of its own, are in `/hor-restfulapi-architecture`. You build this **per actor**, on top of the boilerplate's base classes — it is not shipped in the boilerplate; each app builds it for the actors its spec declares. Design the actor entity and its profile first with [[hor-database-design]] / [[hor-sequelize-model]]; this skill adds the credential, tokens, operations, and cookie to it. It says what the auth cluster contains and how the pieces fit — writing each piece follows its own convention ([[hor-sequelize-model]], [[hor-sequelize-seeder]], [[hor-mutation-resolver]], [[hor-type-interface]]), and the engine is [[hor-graphql-server-engine]]. > **This replaces the older access-token-only flow.** In the old flow the access token was the durable credential — stored on the client and sent on every request, with no refresh cookie. Here the access token is short-lived and held only in memory on the client; durability comes from the refresh cookie. Do not mix the two: when this skill applies, there is no long-lived access token. The frontend half is [[hof-cookie-authentication]]. > Snippets throughout use `<Actor>` for the role being authenticated — substitute your own (`Member`, `Operator`, `Account`, …). Not every app has a "customer"; the reference implementation these snippets are drawn from happens to use `Customer` and `Admin`. ## Core | Topic | Description | Reference | | --- | --- | --- | | Environment & config | Step-by-step setup: the `cookie` dependency, the `AUTH_*` env vars + facade, the per-actor cookie-name constant, and the engine's refresh-token cookie config | [environment](references/environment.md) | | Token & credential models | Per actor: the password-hash model and the access / refresh token models, with `sessionKey` rotation columns and the backup mixin | [token-models](references/token-models.md) | | Migrations | The create-table migrations for the credential and token tables | [migrations](references/migrations.md) | | Session clerk | `SessionClerk` — the injected orchestrator over the token tables (`saveSession` / `rotateSession` / `revokeSession` / `findRefreshToken`), returning throwable-save result objects | [session-clerk](references/session-clerk.md) | | Refresh-token cookie | The HttpOnly cookie clerk and reading / setting the cookie in the GraphQL context | [cookie-context](references/cookie-context.md) | | Auth resolvers | `signIn` / `signUp` / `signOut` / `renewAccessToken` — token issue, rotation, and reuse detection | [resolvers](references/resolvers.md) | | Auth-filter policy | `schemasToSkipFiltering` + `generateFilterHandler` — which operations are public (cookie) vs header-guarded | [auth-filter](references/auth-filter.md) | | Error codes | The `Unauthenticated` and `RefreshTokenReused` codes and where they are thrown | [error-codes](references/error-codes.md) | | Dev-login seeder | A development seeder so `npm run dev` can sign in against real data | [dev-login-seeder](references/dev-login-seeder.md) |