The `@authdog/express` SDK validates Authdog sessions on Express 4 and 5. It reads the session your frontend already holds, verifies it against your environment's public key, and exposes the current user to your route handlers. This page covers install, the middleware, and protecting routes. For the model behind it, see [Backend requests](/docs/backend).

## Install

```bash
npm install @authdog/express express
```

`express` is a peer dependency (`^4.18` or `^5`). The SDK is built on `@authdog/node-commons`, which is pulled in automatically.

## Configure

Create the client once with your environment's **public key** (`pk_...`) — the same key your frontend uses, safe to expose:

```ts
import express from "express"
import { createAuthdog } from "@authdog/express"

const app = express()
const authdog = createAuthdog({ publicKey: process.env.PK_AUTHDOG! })
```

The public key is parsed at startup, so a malformed key — or one whose identity host isn't on the trusted allowlist — fails immediately rather than on the first request.

## Attach the session

`attachSession()` is a non-blocking middleware. It reads the token from the `authdog-session` cookie or an `Authorization: Bearer <token>` header, calls the identity provider's `userinfo` endpoint, and attaches the result to `req.authdog`. It never throws, so it's safe to mount globally:

```ts
app.use(authdog.attachSession())
```

`req.authdog` has the shape:

```ts
{
  token: string | null
  user: unknown | null
  isAuthenticated: boolean
  userInfo?: UserInfoResponse | null
}
```

Pass `{ fetchUser: false }` to skip the `userinfo` round-trip when you only need to know a token is present.

## Protect a route

`attachSession` is *informational*. The enforcement point is `requireAuth`, which rejects unauthenticated requests with `401 { "error": "Unauthorized" }`:

```ts
app.get("/me", authdog.requireAuth, (req, res) => {
  res.json(req.authdog!.user)
})
```

Resolving a session tells you *who* the caller is — pair it with your environment's [authorization](/docs/concepts/authorization) model to decide *what* they can do.

## Sign out

`logout` expires the `authdog-session` cookie and redirects to a sanitized `?redirect_uri`:

```ts
app.get("/logout", authdog.logout)
```

## Service-to-service

For requests with no end user, send a machine-to-machine token as `Authorization: Bearer <token>`. `attachSession` resolves it on the same path as a browser session, and `requireAuth` gates it the same way. See [Backend requests](/docs/backend#service-to-service-m2m).

## Next steps

- [Backend requests](/docs/backend) — the verification model across every backend SDK.
- [Fastify](/docs/backend/fastify) — the same primitives for the Fastify runtime.
- [Calling the REST API](/docs/api) — read users and organizations once a request is authenticated.
