Authdog

Express

Last updated Jul 19, 2026npmlatestCI passing
View as Markdown

@authdog/express resolves Authdog sessions for Express 4 and 5. It reads a cookie or bearer token, checks it through the environment's OIDC userinfo endpoint, and exposes the result to route handlers.

Install

npm install @authdog/express express

@authdog/express is published on npm. express is a peer dependency (^4.18 or ^5); @authdog/node-commons installs automatically.

Configure

Create one client with your environment's public key (pk_...):

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

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

The key is safe to expose. It is parsed at startup; malformed keys and identity hosts outside the trusted HTTPS allowlist fail immediately.

Attach the session

Mount attachSession() before routes:

app.use(authdog.attachSession())

It prefers the authdog-session cookie, then reads Authorization: Bearer <token>. A valid token requires a successful userinfo response (meta.code === 200 with a user). Missing, expired, malformed, or unverifiable tokens do not fail the request; they produce:

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

attachSession({ fetchUser: false }) only surfaces the unverified token. It deliberately leaves user null and isAuthenticated false. Therefore built-in requireAuth rejects that request with 401; use this option only when separate server-side validation and enforcement replace Authdog's gate.

Protect a route

attachSession only records context. requireAuth is the security boundary and returns 401 {"error":"Unauthorized"} unless isAuthenticated is true:

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

Authentication identifies a caller; it does not authorize actions. Apply your authorization checks after requireAuth. Client-side checks never protect server routes.

Sign out

logout expires the local cookie and redirects to a sanitized same-origin redirect_uri:

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

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

Next steps

Learn more