@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.