Skip to main content
This Quickstart is currently in Beta. We’d love to hear your feedback!
Prerequisites:
  • Node.js 20 LTS or newer
  • npm 10+ or yarn 1.22+ or pnpm 8+
  • Optional: jq (for CLI automation) and openssl (to generate secure secrets)
  • Hono projects should use Hono >= 3.x (peer dependency)

Get Started

This quickstart shows the minimal, recommended way to secure a Hono application using @auth0/auth0-hono. It follows the repository’s recommended patterns: environment-driven configuration, app.use(auth(...)) middleware, and requiresAuth() for selective protection.
1

Create a new project

Create a new folder and initialize a Node project.
mkdir auth0-hono-app && cd auth0-hono-app
npm init -y
2

Install dependencies

Install Hono and the Auth0 middleware. Optionally install tsx for running TypeScript directly during development.
npm install hono @auth0/auth0-hono
npm install -D tsx
3

Create an Auth0 application

Create an Auth0 Application in your Auth0 tenant (Regular Web Application) and record the Domain, Client ID, and Client Secret.
(macOS) Example automation using Auth0 CLI + jq:
AUTH0_APP_NAME="Hono Quickstart" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json > auth0-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && echo "AUTH0_DOMAIN=${DOMAIN}" > .env && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env && echo "BASE_URL=http://localhost:3000" >> .env && echo "AUTH0_SESSION_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env && rm auth0-details.json && cat .env
Use the generated .env or update values manually as needed.
4

Add configuration (.env)

Create a .env file at your project root with these values:
AUTH0_DOMAIN=your-tenant.auth0.com
AUTH0_CLIENT_ID=your_client_id
AUTH0_CLIENT_SECRET=your_client_secret
BASE_URL=http://localhost:3000
AUTH0_SESSION_ENCRYPTION_KEY=your_32_char_min_secret
# Optional for APIs
AUTH0_AUDIENCE=https://api.yourapp.com
Note: AUTH0_SESSION_ENCRYPTION_KEY must be at least 32 characters. Use openssl rand -hex 32 to generate one.
5

Add Hono server with Auth0 middleware

Create a server.ts file with the following example.
// server.ts
import { Hono } from 'hono';
import { auth, requiresAuth, Auth0Exception } from '@auth0/auth0-hono';

const app = new Hono();

// Configure auth middleware using environment variables.
app.use(
  auth({
    domain: process.env.AUTH0_DOMAIN,
    clientID: process.env.AUTH0_CLIENT_ID,
    clientSecret: process.env.AUTH0_CLIENT_SECRET,
    baseURL: process.env.BASE_URL,
    session: {
      secret: process.env.AUTH0_SESSION_ENCRYPTION_KEY,
    },
  })
);

// Public route
app.get('/', (c) => c.text('Public — no login required'));

// Make most routes public, but protect /profile/* specifically
app.use('/profile/*', requiresAuth());

app.get('/profile', (c) => {
  const session = c.var.auth0Client?.getSession(c);
  const user = session?.user;
  return c.json({ message: 'Protected profile', user });
});

// Optional: handle Auth0-specific errors
app.onError((err, c) => {
  if (err instanceof Auth0Exception) {
    console.error('Auth0 error', err);
    return err.getResponse();
  }
  return c.text(`Internal Server Error: ${err.message}`, 500);
});

export default app;
Add a package.json script to run with tsx for development:
{
  "scripts": {
    "dev": "tsx server.ts"
  }
}
6

Run your app

Start the server and open http://localhost:3000.
npm run dev
CheckpointYour Hono app should be running on http://localhost:3000. The / route is public. Visiting /profile should redirect you to login (if not authenticated) and then return profile data after successful authentication.

Troubleshooting

Cause: The callback URL configured in the Auth0 Dashboard does not exactly match BASE_URL + the callback route (e.g., http://localhost:3000/auth/callback).Fix:
  1. Verify .env BASE_URL value.
  2. Ensure Allowed Callback URLs in Auth0 Dashboard contain http://localhost:3000/auth/callback.
  3. Restart dev server after changes.
Cause: AUTH0_SESSION_ENCRYPTION_KEY is missing or too short, or you changed it while cookies from an old secret remain.Fix:
  • Ensure AUTH0_SESSION_ENCRYPTION_KEY is at least 32 characters.
  • Clear browser cookies for localhost after changing the key.
  • Restart dev server.
Cause: Middleware not installed or placed after route registration.Fix:
  • Ensure app.use(auth(...)) runs before routes that depend on authentication.
  • Confirm package installed: npm ls @auth0/auth0-hono.
Cause: Deployment platform not providing environment variables or using different names.Fix:
  • Map environment variables in your hosting provider dashboard to the names used in this quickstart.
  • For Cloudflare Workers, verify session/cookie handling is compatible with the platform.

Advanced Usage

  • Selective protection: use app.use(auth({ authRequired: false })) to make routes public by default and app.use('/private/*', requiresAuth()) to protect specific paths.
  • Silent login: use attemptSilentLogin() middleware to try silent authentication for better UX.
  • Custom login flow: call login({...}) to customize forwarded query params, redirectAfterLogin, or silent login options.
  • Token management: the middleware exposes access and ID tokens via the session; follow least-privilege for scopes and rotate refresh tokens safely.

Best Practices & Security

  • Keep secrets out of source control — use environment variables.
  • Use a 32+ character AUTH0_SESSION_ENCRYPTION_KEY.
  • Set cookie secure to true in production and set appropriate sameSite policy.
  • Limit token scopes; use audience only when requesting access tokens for APIs.
  • Catch Auth0Exception in app.onError to handle auth-specific errors cleanly.