Auth for apps and agents. Server-side sessions, OIDC discovery, encrypted cookies. Any OIDC provider. No vendor lock-in.
import { Hono } from 'hono'
import { createBffRoutes, requiresAuth } from 'fz-auth'
const app = new Hono()
app.route('/auth', await createBffRoutes({
issuerUrl: process.env.ISSUER_URL!,
clientId: process.env.CLIENT_ID!,
encryptionKey: process.env.SESSION_SECRET!,
}))
app.get('/api/me', requiresAuth({ encryptionKey: process.env.SESSION_SECRET! }), (c) => {
return c.json({ message: 'Authenticated!' })
})
export default appThat's a working auth server. SESSION_SECRET is a 32-byte hex key (openssl rand -hex 32). The issuerUrl is any OIDC provider — Google, Auth0, Keycloak, Ory, Cognito.
Browser → GET /auth/login → redirect to IdP (Google, Auth0, etc.)
User authenticates at the IdP
IdP → GET /auth/callback?code=X → server exchanges code for tokens
Server sets encrypted httpOnly cookie → redirect to app
Browser → GET /api/me (cookie sent automatically) → server decrypts, returns data
Tokens never reach the browser. This is the BFF pattern — the IETF-recommended approach for browser-based OAuth2.
| Package | What |
|---|---|
fz-auth |
Hono routes + middleware (the main install) |
fz-auth-core |
Framework-agnostic core (for building Express/Fastify adapters) |
fz-auth-react |
<AuthProvider> + useAuth() for React SPAs |
fz-auth-aws |
AWS KMS envelope encryption for session cookies |
- Any OIDC provider — endpoints discovered automatically via
.well-known/openid-configuration - No tokens in browser — httpOnly, Secure, SameSite=Lax,
__Host-prefix cookies - No database required — sessions stored in AES-256-GCM encrypted cookies
- Pluggable crypto — swap in AWS KMS, Vault, or any custom backend via
SessionCryptointerface - Rolling sessions —
rollingDurationresets session expiry on activity - Agent identity — API keys with
agentIdfor non-human audit trails - OIDC discovery — one
issuerUrl, works with Google, Auth0, Keycloak, Ory, Cognito - Silent refresh — server-side refresh token rotation, no user interaction
# Generate a session encryption key
openssl rand -hex 32
# Install
npm install fz-auth
# For React apps
npm install fz-auth-react
# For AWS KMS encryption (production)
npm install fz-auth-aws| Guide | What |
|---|---|
| Choose an IdP | Auth0 vs Ory vs Keycloak vs Google-only |
| Provision an IdP | Set up your identity provider |
| Add social login | Google, GitHub, Microsoft, Apple |
| Add BFF to your app | Mount auth routes on Hono |
| Add React frontend | AuthProvider + protected routes |
| Add agent auth | API keys, device flow, CI/CD tokens |
| Add organizations | Multi-tenant teams with roles |
| Production hardening | KMS, rate limits, security headers |
| Guide | What |
|---|---|
| AWS App Runner | Deploy BFF + Ory on App Runner |
| AWS OIDC setup | GitHub Actions → AWS without long-lived keys |
| Secrets management | Env var injection at runtime |
| Guide | What |
|---|---|
| Unit tests | Test BFF routes with mocked OIDC |
| Smoke tests | Post-deploy health + OIDC validation |
| Security checks | CORS, auth enforcement, headers, rate limits |
| E2E login flow | Playwright browser tests |
| Mock auth server | Test JWT middleware without a real IdP |
| Session security | Encryption validation, tamper detection |
| Guide | What |
|---|---|
| Local stack | Docker Compose with Ory + PG + your app |
| Process manager | Run everything in one terminal |
| Social login on localhost | Google OAuth on localhost |
| Guide | What |
|---|---|
| Renovate | Auto-update dependencies |
| Release pipeline | Changesets → auto-publish |
| Secret scanning | Pre-commit detect-secrets |
The ory/ directory contains a production-ready Ory Kratos + Hydra configuration:
cd ory && docker compose up -dThis gives you a full identity provider on localhost with password login, email verification, and OAuth2 — ready for fz-auth to connect to.
fz-auth-core ← OIDC discovery, PKCE, session crypto (no framework dependency)
fz-auth ← Hono adapter: routes + middleware (~160 lines of glue)
fz-auth-react ← React AuthProvider + useAuth (~100 lines)
fz-auth-aws ← AWS KMS envelope encryption (~110 lines)
The core is framework-agnostic. The Hono adapter is thin. Building an Express or Fastify adapter means writing ~160 lines of cookie/redirect glue over createBffCore().
- Per IETF draft-ietf-oauth-browser-based-apps-26 §6.1 (BFF pattern)
- Per RFC 9700 (OAuth 2.0 Security BCP)
- AES-256-GCM with random IV per encryption
__Host-cookie prefix (Secure, no Domain, Path=/)- Pluggable
SessionCryptofor KMS/Vault/HSM backends - PKCE (S256) on all authorization flows
- No tokens in
localStorageorsessionStorage