> ## Documentation Index
> Fetch the complete documentation index at: https://auth0-actions-triggers-prototype.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Add Login to Your Hono Application

> This Quickstart demonstrates how to secure your Hono applications using Auth0 authentication. Follow the steps to add login, logout, and protected routes to a Hono app.

export const HowToSchema = () => <script type="application/ld+json">
    {'{"@context":"https://schema.org","@type":"HowTo"}'}
  </script>;

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

<HowToSchema />

<Callout icon="pencil" color="#FFC107" iconType="solid">
  This Quickstart is currently in **Beta**. We'd love to hear your feedback!
</Callout>

<Note>
  **Prerequisites:**

  * **Node.js** 20 LTS or newer
  * **npm** 10+ or **yarn** 1.22+ or **pnpm** 8+
  * Optional: **[jq](https://jqlang.org/)** - for Auth0 CLI setup and **openssl** to generate secure secrets
  * Hono projects should use Hono >= 3.x (peer dependency)
</Note>

## 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(auth0(...))` middleware, and `requiresAuth()` for selective protection.

<Steps>
  <Step title="Create a new Hono application" stepNumber={1}>
    Create a new Hono application using create-hono utility.

    ```shellscript theme={null}
    npm create hono@latest auth0-hono-app && cd auth0-hono-app
    ```

    Select `nodejs` template
  </Step>

  <Step title="Install dependencies" stepNumber={2}>
    Install the Auth0 middleware.

    ```shellscript theme={null}
    npm install @auth0/auth0-hono
    ```

    This quickstart uses `dotenv` package to load environment variables from a `.env` file.

    To install `dotenv` locally:

    ```shellscript theme={null}
    npm install -D dotenv
    ```

    Alternatively, if you prefer not to add a dependency, you can load an env file at process start using node's `--env-file` flag, which lets you omit installing and importing `dotenv`.

    Modify the `start` script in `package.json` to:

    ```json theme={null}
      "scripts": {
        "start": "node --env-file=.env dist/index.js"
      }
    ```
  </Step>

  <Step title="Create an Auth0 application" stepNumber={3}>
    Create an Auth0 Application in your Auth0 tenant (Regular Web Application) and record the **Domain**, **Client ID**, and **Client Secret** in environment variables to your project.
    You can choose to do this automatically by running a CLI command or do it manually via the Dashboard:

    <Tabs>
      <Tab title="CLI">
        Run the following shell command on your project’s root directory to create an Auth0 app and generate a `.env` file:

        <AuthCodeGroup>
          ```shellscript Mac theme={null}
          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 --metadata created_by="quickstart-docs-cli" > auth0-app-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && SECRET=$(openssl rand -hex 32) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env && echo "APP_BASE_URL=http://localhost:3000" >> .env && echo "AUTH0_SESSION_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env && rm auth0-app-details.json && cat .env
          ```

          ```shellscript Windows theme={null}
          $AppName = "Hono Quickstart"; winget install Auth0.CLI; auth0 login --no-input; auth0 apps create -n "$AppName" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json --metadata created_by="quickstart-docs-cli" | Set-Content -Path auth0-app-details.json; $ClientId = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_id; $ClientSecret = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_secret; $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; $Secret = [System.Convert]::ToHexString([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32)).ToLower(); Set-Content -Path .env -Value "AUTH0_DOMAIN=$Domain"; Add-Content -Path .env -Value "AUTH0_CLIENT_ID=$ClientId"; Add-Content -Path .env -Value "AUTH0_CLIENT_SECRET=$ClientSecret"; Add-Content -Path .env -Value "AUTH0_SESSION_ENCRYPTION_KEY=$Secret"; Add-Content -Path .env -Value "APP_BASE_URL=http://localhost:3000"; Remove-Item auth0-app-details.json; Write-Output ".env file created with your Auth0 details:"; Get-Content .env
          ```
        </AuthCodeGroup>

        Use the generated `.env` or update values manually as needed.
      </Tab>

      <Tab title="Dashboard">
        Manual steps:

        1. Go to the [Auth0 Dashboard](https://manage.auth0.com/dashboard/)
        2. Applications → Create Application → **Regular Web Application**
        3. In the app settings set:

        **Allowed Callback URLs**

        ```
        http://localhost:3000/auth/callback
        ```

        **Allowed Logout URLs**

        ```
        http://localhost:3000
        ```

        4. Create a `.env` file at your project root and populate these values:

        ```env theme={null}
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_CLIENT_ID=YOUR_AUTH0_CLIENT_ID
        AUTH0_CLIENT_SECRET=YOUR_AUTH0_CLIENT_SECRET
        APP_BASE_URL=http://localhost:3000
        AUTH0_SESSION_ENCRYPTION_KEY=your_32_char_min_secret
        # Optional for APIs
        AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
        ```

        Note: `AUTH0_SESSION_ENCRYPTION_KEY` must be at least 32 characters. Use `openssl rand -hex 32` to generate one.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Setup Hono web server with Auth0 middleware" stepNumber={4}>
    Replace the initial template in `index.ts` file with the following example. The code demonstrates zero-config setup where environment variables are automatically read, creating an `auth0()` middleware with public routes by default and protected routes using `requiresAuth()`.

    ```typescript ./src/index.ts wrap lines theme={null}
    // src/index.ts
    import { serve } from '@hono/node-server';
    import { Hono } from 'hono';
    import { auth0, requiresAuth, Auth0Error, type OIDCEnv } from '@auth0/auth0-hono';

    const app = new Hono<OIDCEnv>();

    // Zero-config: reads AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET,
    // APP_BASE_URL, AUTH0_SESSION_ENCRYPTION_KEY from environment
    app.use(
      auth0({
        authRequired: false, // Public by default, protect specific routes
      })
    );

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

    // Protected routes
    app.use('/profile/*', requiresAuth());

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

    // Error handling
    app.onError((err, c) => {
      if (err instanceof Auth0Error) {
        return c.json({ error: err.code, error_description: err.description }, err.status);
      }
      return c.json({ error: 'Internal server error' }, 500);
    });

    const port = Number(process.env.PORT) || 3000;
    serve({ fetch: app.fetch, port }, (info) => {
      console.log(`Server is running on http://localhost:${info.port}`);
    });
    ```
  </Step>

  <Step title="Run your app" stepNumber={5}>
    Start the server and open `http://localhost:3000`.

    ```shellscript theme={null}
    npm run dev
    ```
  </Step>
</Steps>

<Check>
  **Checkpoint**

  Your Hono app should be running on [http://localhost:3000](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.
</Check>

## Troubleshooting

<Accordion title="Common issues">
  <Accordion title="Callback or Redirect Mismatch">
    Cause: The callback URL configured in the Auth0 Dashboard does not exactly match `APP_BASE_URL` + the callback route (e.g., `http://localhost:3000/auth/callback`).

    Fix:

    1. Verify `.env` `APP_BASE_URL` value.
    2. Ensure Allowed Callback URLs in Auth0 Dashboard contain `http://localhost:3000/auth/callback`.
    3. Restart dev server after changes.
  </Accordion>

  <Accordion title="Session decryption / JWEDecryptionFailed">
    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.
  </Accordion>

  <Accordion title="Routes 404 (e.g., /auth/login returns 404)">
    Cause: Middleware not installed or placed after route registration.

    Fix:

    * Ensure `app.use(auth0(...))` runs before routes that depend on authentication.
    * Confirm package installed: `npm ls @auth0/auth0-hono`.
  </Accordion>

  <Accordion title="Missing environment variables in production">
    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.
  </Accordion>
</Accordion>

## Advanced Usage

* Selective protection: use `app.use(auth0({ 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 `Auth0Error` in `app.onError` to handle auth-specific errors cleanly.

***
