`@authdog/fastify` resolves Authdog sessions on Fastify 4 and 5. Its plugin decorates requests with session context and exposes an authentication guard.

## Install

```package-install
@authdog/fastify fastify
```

`@authdog/fastify` is published on npm. `fastify` is a peer dependency (`^4` or `^5`); `@authdog/node-commons` and `fastify-plugin` install automatically. `@fastify/cookie` is not required.

## Register the plugin

Register once with your environment's public key (`pk_...`):

```ts
import Fastify from "fastify"
import { authdogPlugin } from "@authdog/fastify"

const app = Fastify()
await app.register(authdogPlugin, { publicKey: process.env.PK_AUTHDOG! })
```

The key is safe to expose. Registration rejects malformed keys and identity hosts outside the trusted HTTPS allowlist.

On each request, the plugin prefers the `authdog-session` cookie, then reads `Authorization: Bearer <token>`. It calls the environment's OIDC `userinfo` endpoint and sets `request.authdog` to `{ token, user, isAuthenticated }`. Only a success envelope (`meta.code === 200` with a user) authenticates the request. Missing, invalid, or unverifiable tokens yield anonymous context instead of an application error.

`fetchUserInfo: false` skips `userinfo` but does not authenticate token presence. `token` may be set while `user` remains null and `isAuthenticated` remains false. Built-in `requireAuth` therefore returns 401; use this option only with separate server-side validation and enforcement.

## Protect a route

Use `app.authdog.requireAuth` as a `preHandler`. It is the security boundary and returns `401 {"error":"Unauthorized"}` for anonymous context:

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

Authentication identifies a caller; it does not authorize actions. Apply [authorization](/docs/concepts/authorization) checks after this guard. Client-side checks never protect server routes.

## Sign out

`app.authdog.logout` clears the local cookie and redirects to a sanitized same-origin `redirect_uri`:

```ts
app.get("/logout", (req, reply) => app.authdog.logout(req, reply))
```

This does not revoke a bearer token or end an upstream identity-provider session.

## Next steps

- [Backend requests](/docs/backend)
- [Express](/docs/backend/express)
- [Calling the REST API](/docs/api)
