---
title: "Basic and Bearer Auth"
description: "Hono provides built-in middleware for HTTP Basic and Bearer Auth to secure API endpoints by validating credentials against static configurations or custom verification handlers. These middlewares i..."
last_updated: "2026-10-12T08:14:12.743647+00:00"
canonical_url: "https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/security-middleware/basic-and-bearer-auth"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [src/middleware/bearer-auth/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts)
- [src/utils/jwt/jwt.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/jwt/jwt.ts)
- [src/middleware/secure-headers/secure-headers.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/secure-headers/secure-headers.ts)
- [src/adapter/aws-lambda/handler.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/aws-lambda/handler.ts)
- [src/middleware/basic-auth/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts)
- [src/middleware/jwt/jwt.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwt/jwt.ts)
- [src/middleware/jwk/jwk.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwk/jwk.ts)
- [src/utils/basic-auth.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/basic-auth.ts)
- [src/middleware/jwk/keys.test.json](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwk/keys.test.json)
- [src/middleware/csrf/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/csrf/index.ts)
- [src/utils/jwt/jws.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/jwt/jws.ts)
- [src/adapter/lambda-edge/handler.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/lambda-edge/handler.ts)
- [src/middleware/ip-restriction/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/ip-restriction/index.ts)
- [src/utils/headers.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/headers.ts)
- [src/utils/ipaddr.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/ipaddr.ts)
- [src/request.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/request.ts)
- [src/helper/proxy/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/proxy/index.ts)
- [src/utils/buffer.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts)
- [src/preset/quick.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/preset/quick.ts)
- [src/helper/streaming/text.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/helper/streaming/text.ts)
- [src/types.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/types.ts)
- [src/middleware/etag/digest.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/etag/digest.ts)
- [src/utils/jwt/utf8.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/jwt/utf8.ts)
- [src/utils/encode.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/encode.ts)
- [src/utils/cookie.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/cookie.ts)
- [src/utils/jwt/types.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/jwt/types.ts)
- [src/utils/accept.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/accept.ts)
- [src/router/linear-router/router.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/router/linear-router/router.ts)
- [src/adapter/netlify/handler.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/adapter/netlify/handler.ts)
- [src/middleware/jwt/index.ts](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwt/index.ts)
</details>

## Overview

Hono provides built-in middleware for HTTP Basic and Bearer Auth to secure API endpoints by validating credentials against static configurations or custom verification handlers. These middlewares inspect incoming request headers, parse authorization schemes, and dispatch standardized HTTP exceptions with `401 Unauthorized` status codes and `WWW-Authenticate` challenge headers when verification fails.

Sources: [src/middleware/basic-auth/index.ts:31-46](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L31-L46), [src/middleware/bearer-auth/index.ts:88-89](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L88-L89)

To prevent timing side-channel attacks during credential comparison, the system utilizes constant-time string and buffer comparison algorithms implemented within utility modules.

Sources: [src/utils/buffer.ts:29-63](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L29-L63)

## Basic Authentication Flow

### Credential Matching Execution Walkthrough

The `basicAuth` middleware accepts an options object supporting either static username/password pairs or a custom `verifyUser` asynchronous callback function. The public configuration options also accept an optional `realm`, a `hashFunction` for credential normalization, an `invalidUserMessage` string, object, or message function, and an `onAuthSuccess` callback hook. If neither static credentials nor a `verifyUser` function are supplied, initialization throws an error.

Sources: [src/middleware/basic-auth/index.ts:14-30](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L14-L30), [src/middleware/basic-auth/index.ts:80-91](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L80-L91)

| Option Key | Type | Default Value | Description |
| :--- | :--- | :--- | :--- |
| `username` | `string` | — | Static username for authentication matching |
| `password` | `string` | — | Static password for authentication matching |
| `verifyUser` | `Function` | — | Custom verification handler taking `(username, password, c)` |
| `realm` | `string` | `"Secure Area"` | Realm attribute populated in the `WWW-Authenticate` header |
| `hashFunction` | `Function` | `sha256` | Hash function utilized during secure credential comparison |
| `invalidUserMessage` | `string \| object \| Function` | `"Unauthorized"` | Response body content returned on validation failure |
| `onAuthSuccess` | `Function` | — | Callback function invoked upon successful authentication |

Sources: [src/middleware/basic-auth/index.ts:36-43](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L36-L43), [src/middleware/basic-auth/index.ts:93-99](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L93-L99)

> [!NOTE]
> When static `username` and `password` properties are specified in the configuration object alongside rest parameters (`...users`), they are prepended to the internal user verification array via `users.unshift()`.

Sources: [src/middleware/basic-auth/index.ts:81-83](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L81-L83), [src/middleware/basic-auth/index.ts:101-103](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L101-L103)

When an incoming request is intercepted, the handler extracts and parses authorization credentials from the request headers using the basic auth utility function, checking the provided username and password against configured accounts or the custom verification handler via the execution chain: `basicAuth` → `timingSafeEqual` → `timingSafeEqualString` → `constantTimeEqualString`.

Sources: [src/middleware/basic-auth/index.ts:105-131](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L105-L131), [src/utils/buffer.ts:29-96](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L29-L96)

1. `basicAuth` invokes `auth(ctx.req.raw)` to extract the decoded request username and password, then iterates through configured users to invoke `timingSafeEqual(user.username, requestUser.username, options.hashFunction)` and `timingSafeEqual(user.password, requestUser.password, options.hashFunction)` via `Promise.all`.
Sources: [src/middleware/basic-auth/index.ts:106-121](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L106-L121)
2. `timingSafeEqual` checks argument types and routes string inputs to `timingSafeEqualString`.
Sources: [src/utils/buffer.ts:76-83](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L76-L83)
3. `timingSafeEqualString` resolves the active hash function (defaulting to `sha256`), computes hashed byte representations of both strings in parallel via `Promise.all`, and passes the resulting digests to `constantTimeEqualString`.
Sources: [src/utils/buffer.ts:44-63](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L44-L63)
4. `constantTimeEqualString` evaluates character codes across the maximum length utilizing bitwise operations to accumulate differences without early exits.
Sources: [src/utils/buffer.ts:29-40](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L29-L40)

```mermaid
sequenceDiagram
    participant Index as src/middleware/basic-auth/index.ts
    participant Buffer as src/utils/buffer.ts
    Index->>Buffer: basicAuth() calls timingSafeEqual()
    Buffer->>Buffer: timingSafeEqual() calls timingSafeEqualString()
    Buffer->>Buffer: timingSafeEqualString() calls constantTimeEqualString()
```

Sources: [src/middleware/basic-auth/index.ts:118-121](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L118-L121), [src/utils/buffer.ts:76-83](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L76-L83), [src/utils/buffer.ts:44-63](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L44-L63), [src/utils/buffer.ts:29-40](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L29-L40)

## Parsing Authorization Credentials

### Credential Extraction and Decoding

The [Utilities and Encoding](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/helpers-and-tooling/utilities-and-encoding) page documents how low-level helpers manage character encoding [src/utils/encode.ts:1-4](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/encode.ts#L1-L4). Incoming HTTP requests are processed by the `auth` helper, which reads the `Authorization` header and matches it against `CREDENTIALS_REGEXP` to isolate the Base64-encoded payload portion [src/utils/basic-auth.ts:3-10](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/basic-auth.ts#L3-L10). If the header is missing or fails the regular expression pattern, the function immediately returns `undefined` [src/utils/basic-auth.ts:10-13](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/basic-auth.ts#L10-L13).

Sources: [src/utils/basic-auth.ts:3-13](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/basic-auth.ts#L3-L13), [src/utils/encode.ts:1-4](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/encode.ts#L1-L4)

### Execution Walkthrough and Sequence

1. `basicAuth` invokes `auth(ctx.req.raw)` to retrieve credentials from the raw request object [src/middleware/basic-auth/index.ts:106](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L106).
Sources: [src/middleware/basic-auth/index.ts:106](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L106)
2. `auth` executes `CREDENTIALS_REGEXP.exec` on the header string, captures group `1`, and passes it to `decodeBase64` [[src/utils/basic-auth.ts:10], [src/utils/basic-auth.ts:18]].
Sources: [src/utils/basic-auth.ts:10](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/basic-auth.ts#L10], [src/utils/basic-auth.ts:18)
3. `decodeBase64` invokes `atob(str)` and constructs a `Uint8Array` using byte character codes [src/utils/encode.ts:25-33](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/encode.ts#L25-L33).
Sources: [src/utils/encode.ts:25-33](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/encode.ts#L25-L33)

```mermaid
sequenceDiagram
    participant BasicAuth as src/middleware/basic-auth/index.ts
    participant BasicAuthUtil as src/utils/basic-auth.ts
    participant EncodeUtil as src/utils/encode.ts
    BasicAuth->>BasicAuthUtil: auth(ctx.req.raw)
    BasicAuthUtil->>EncodeUtil: decodeBase64(match[1])
    EncodeUtil-->>BasicAuthUtil: Returns Uint8Array bytes
```

Sources: [src/middleware/basic-auth/index.ts:106](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L106), [src/utils/basic-auth.ts:10-18](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/basic-auth.ts#L10-L18), [src/utils/encode.ts:25-33](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/encode.ts#L25-L33)

### Regular Expressions and Sanitization

| Constant Name | Regular Expression Pattern | Purpose |
| :--- | :--- | :--- |
| `CREDENTIALS_REGEXP` | `/^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/` | Matches and extracts the Base64 token following the Basic scheme prefix. |
| `USER_PASS_REGEXP` | `/^([^:]*):(.*)$/` | Splits the decoded string into username and password components across the first colon. |

Sources: [src/utils/basic-auth.ts:3-4](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/basic-auth.ts#L3-L4)

> [!WARNING]
> If an invalid string is passed to `atob()`, a `DOMException` is thrown; the `auth` function catches this exception inside a `try...catch` block and safely returns `undefined` rather than crashing the [request lifecycle](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/core-engine/request-lifecycle).

Sources: [src/utils/basic-auth.ts:15-20](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/basic-auth.ts#L15-L20)

## Bearer Authentication Enforcement

### Bearer Options and Header Processing

The `bearerAuth` middleware requires options containing either a `token` (string or array of strings) or a `verifyToken` function. Optional configurations include `realm`, `prefix`, `headerName`, `hashFunction`, and customized error responses via `noAuthenticationHeader`, `invalidAuthenticationHeader`, and `invalidToken`. If neither `token` nor `verifyToken` is provided, the middleware throws an initialization error.

Sources: [src/middleware/bearer-auth/index.ts:22-50](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L22-L50), [src/middleware/bearer-auth/index.ts:107-109](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L107-L109)

| Option Name | Type | Default Value | Purpose |
| :--- | :--- | :--- | :--- |
| `token` | `string \| string[]` | `undefined` | The static token string or array of acceptable tokens. |
| `verifyToken` | `(token: string, c: Context) => boolean \| Promise<boolean>` | `undefined` | Custom token verification callback function. |
| `realm` | `string` | `''` | Authentication realm string included in challenge headers. |
| `prefix` | `string` | `'Bearer'` | Expected scheme prefix preceding the token. |
| `headerName` | `string` | `'Authorization'` | Custom header name to inspect instead of `Authorization`. |
| `hashFunction` | `Function` | `sha256` | Custom hashing function used during token comparison. |

Sources: [src/middleware/bearer-auth/index.ts:22-50](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L22-L50), [src/middleware/bearer-auth/index.ts:110-115](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L110-L115), [src/utils/buffer.ts:50](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L50)

> [!NOTE]
> When `prefix` is set to an empty string `''`, scheme prefix validation is bypassed entirely, and the entire header value is treated directly as the token string.

Sources: [src/middleware/bearer-auth/index.ts:172-174](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L172-L174)

### Execution Walkthrough and Sequence

1. `bearerAuth` receives the request and inspects the specified HTTP header using `c.req.header(options.headerName || HEADER)`.
Sources: [src/middleware/bearer-auth/index.ts:156-157](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L156-L157)
2. If the header is missing, it dispatches an unauthorized exception via `throwHTTPException` with a 401 status.
Sources: [src/middleware/bearer-auth/index.ts:158-168](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L158-L168)
3. If present, it validates the scheme prefix case-insensitively, trims leading whitespace, and tests the extracted token against `tokenRegexp` (`^[A-Za-z0-9._~+/-]+=*$`).
Sources: [src/middleware/bearer-auth/index.ts:12-19](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L12-L19), [src/middleware/bearer-auth/index.ts:175-182](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L175-L182)
4. If token validation fails, a 400 Bad Request exception is thrown.
Sources: [src/middleware/bearer-auth/index.ts:182-192](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L182-L192)
5. Otherwise, credential matching delegates to `verifyToken` or calls `timingSafeEqual`.
Sources: [src/middleware/bearer-auth/index.ts:195-206](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L195-L206)
6. `timingSafeEqual` invokes `timingSafeEqualString`.
Sources: [src/utils/buffer.ts:76-83](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L76-L83)
7. `timingSafeEqualString` invokes `constantTimeEqualString` for byte and hash verification.
Sources: [src/utils/buffer.ts:44-63](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L44-L63)

```mermaid
sequenceDiagram
    participant BearerAuth as src/middleware/bearer-auth/index.ts
    participant BufferUtil as src/utils/buffer.ts
    BearerAuth->>BufferUtil: timingSafeEqual(options.token, tokenValue, options.hashFunction)
    BufferUtil->>BufferUtil: timingSafeEqualString(a, b, hashFunction)
    BufferUtil->>BufferUtil: constantTimeEqualString(sa, sb)
```

Sources: [src/middleware/bearer-auth/index.ts:198](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L198), [src/utils/buffer.ts:76-83](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L76-L83), [src/utils/buffer.ts:44-63](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L44-L63), [src/utils/buffer.ts:29-40](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L29-L40)

## Timing-Attack Mitigation

### Constant-Time Comparison Operations

Hono implements timing-attack mitigation utilities in `src/utils/buffer.ts` to prevent attackers from inferring secret tokens or passwords via response latency side channels. The lowest-level primitive, `constantTimeEqualString`, processes two strings character by character without short-circuiting on mismatch:

```typescript
const constantTimeEqualString = (a: string, b: string): boolean => {
  const aLen = a.length
  const bLen = b.length
  const maxLen = Math.max(aLen, bLen)
  let out = aLen ^ bLen
  for (let i = 0; i < maxLen; i++) {
    const aChar = i < aLen ? a.charCodeAt(i) : 0
    const bChar = i < bLen ? b.charCodeAt(i) : 0
    out |= aChar ^ bChar
  }
  return out === 0
}
```

Sources: [src/utils/buffer.ts:29-40](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L29-L40)

> [!CAUTION]
> Length differences between strings are accumulated into the XOR accumulator via `aLen ^ bLen`, preventing length-extension leaks from exiting early when string lengths diverge.

Sources: [src/utils/buffer.ts:33](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L33)

### ArrayBuffer and String Equivalence

Higher-level comparison functions handle binary `ArrayBuffer` instances as well as hashed and unhashed strings. The `equal` function compares two `ArrayBuffer` instances using a DataView iteration loop:

```typescript
export const equal = (a: ArrayBuffer, b: ArrayBuffer): boolean => {
  if (a === b) {
    return true
  }
  if (a.byteLength !== b.byteLength) {
    return false
  }

  const va = new DataView(a)
  const vb = new DataView(b)

  let i = va.byteLength
  while (i--) {
    if (va.getUint8(i) !== vb.getUint8(i)) {
      return false
    }
  }

  return true
}
```

Sources: [src/utils/buffer.ts:8-27](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L8-L27)

The `timingSafeEqualString` function wraps string hashing and comparison. By default, if no custom `hashFunction` is provided, it falls back to `sha256`:

```typescript
const timingSafeEqualString = async (
  a: string,
  b: string,
  hashFunction?: StringHashFunction
): Promise<boolean> => {
  if (!hashFunction) {
    hashFunction = sha256
  }

  const [sa, sb] = await Promise.all([hashFunction(a), hashFunction(b)])

  if (sa == null || sb == null || typeof sa !== 'string' || typeof sb !== 'string') {
    return false
  }

  const hashEqual = constantTimeEqualString(sa, sb)
  const originalEqual = constantTimeEqualString(a, b)

  return hashEqual && originalEqual
}
```

Sources: [src/utils/buffer.ts:44-63](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L44-L63)

> [!NOTE]
> `timingSafeEqualString` evaluates both `constantTimeEqualString(sa, sb)` on the hashed outputs and `constantTimeEqualString(a, b)` on the raw inputs concurrently, returning true only if both comparisons succeed.

Sources: [src/utils/buffer.ts:53-62](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L53-L62)

The exported `timingSafeEqual` entry point normalizes inputs and routes execution depending on whether parameters are strings or generic objects/booleans:

```typescript
export const timingSafeEqual: TimingSafeEqual = async (
  a,
  b,
  hashFunction?: Function
): Promise<boolean> => {
  if (typeof a === 'string' && typeof b === 'string') {
    return timingSafeEqualString(a, b, hashFunction as StringHashFunction)
  }

  if (!hashFunction) {
    hashFunction = sha256
  }

  const [sa, sb] = await Promise.all([hashFunction(a), hashFunction(b)])

  if (!sa || !sb || typeof sa !== 'string' || typeof sb !== 'string') {
    return false
  }

  return timingSafeEqualString(sa, sb)
}
```

Sources: [src/utils/buffer.ts:76-96](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/utils/buffer.ts#L76-L96)

## Authentication Challenges and Error Dispatch

### HTTPException Instantiation and Response Generation

When authentication fails across Hono's authentication middlewares, error handling is dispatched via `HTTPException` combined with custom `Response` instances. The `basicAuth` middleware evaluates the parsed user credentials against configured options or user lists. Upon failure, it constructs a 401 Unauthorized status response containing the `WWW-Authenticate` header populated with the escaped realm name. If `invalidUserMessage` is configured as a function or an object, it is dynamically serialized into a text or JSON payload before throwing the `HTTPException`:

```typescript
  // Invalid user.
  const status = 401
  const headers = {
    'WWW-Authenticate': 'Basic realm="' + options.realm?.replace(/"/g, '\\"') + '"',
  }
  const responseMessage =
    typeof options.invalidUserMessage === 'function'
      ? await options.invalidUserMessage(ctx)
      : options.invalidUserMessage
  const res =
    typeof responseMessage === 'string'
      ? new Response(responseMessage, { status, headers })
      : new Response(JSON.stringify(responseMessage), {
          status,
          headers: {
            ...headers,
            'content-type': 'application/json',
          },
        })
  throw new HTTPException(status, { res })
}
```

Sources: [src/middleware/basic-auth/index.ts:132-152](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L132-L152)

Similarly, the `bearerAuth` middleware defines a private `throwHTTPException` helper function to encapsulate status codes, challenge headers, and message body construction. Depending on the specific failure branch—such as missing headers, malformed requests, or invalid tokens—it issues status codes 401, 400, or 401 respectively.

Sources: [src/middleware/bearer-auth/index.ts:122-154](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L122-L154)

> [!WARNING]
> Realms containing double quotes are automatically escaped via `options.realm?.replace(/"/g, '\\"')` prior to header injection to prevent header injection vulnerabilities.

Sources: [src/middleware/basic-auth/index.ts:135](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L135), [src/middleware/bearer-auth/index.ts:117](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L117)

### WWW-Authenticate Challenge Construction

The construction of challenge headers differs between schemes based on whether options specify plain strings, objects, or callback functions. The `bearerAuth` middleware processes `wwwAuthenticateHeader` parameters by checking their type. If an object is supplied, its entries are mapped into comma-separated key-value pairs appended to the challenge prefix:

```typescript
const wwwAuthenticateHeaderValue: string | object =
  typeof wwwAuthenticateHeader === 'function'
    ? await wwwAuthenticateHeader(c)
    : wwwAuthenticateHeader

const headers = {
  'WWW-Authenticate':
    typeof wwwAuthenticateHeaderValue === 'string'
      ? wwwAuthenticateHeaderValue
      : `${wwwAuthenticatePrefix}${Object.entries(wwwAuthenticateHeaderValue)
          .map(([key, value]) => `${key}="${value}"`)
          .join(',')}`,
}
```

Sources: [src/middleware/bearer-auth/index.ts:128-140](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L128-L140)

For JSON Web Token workflows in `jwt` and `jwk` middlewares, failed verifications or missing tokens trigger `unauthorizedResponse`, which formats challenge headers including the current request URL, error codes, and detailed descriptions:

```typescript
function unauthorizedResponse(opts: {
  ctx: Context
  error: string
  errDescription: string
  statusText?: string
}) {
  return new Response('Unauthorized', {
    status: 401,
    statusText: opts.statusText,
    headers: {
      'WWW-Authenticate': `Bearer realm="${opts.ctx.req.url}",error="${opts.error}",error_description="${opts.errDescription}"`,
    },
  })
}
```

Sources: [src/middleware/jwt/jwt.ts:160-173](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwt/jwt.ts#L160-L173), [src/middleware/jwk/jwk.ts:170-182](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwk/jwk.ts#L170-L182)

| Middleware | Default Status Code | Default WWW-Authenticate Challenge | Message Payload Handling |
| :--- | :--- | :--- | :--- |
| `basicAuth` | `401` | `Basic realm="..."` | Text or JSON via `invalidUserMessage` |
| `bearerAuth` (Missing) | `401` | `Bearer realm="..."` | Text or JSON via `noAuthenticationHeader.message` |
| `bearerAuth` (Invalid Request) | `400` | `Bearer error="invalid_request"` | Text or JSON via `invalidAuthenticationHeader.message` |
| `bearerAuth` (Invalid Token) | `401` | `Bearer error="invalid_token"` | Text or JSON via `invalidToken.message` |
| `jwt` / `jwk` | `401` | `Bearer realm="...",error="...",error_description="..."` | Static string `'Unauthorized'` |

Sources: [src/middleware/basic-auth/index.ts:133-151](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/basic-auth/index.ts#L133-L151), [src/middleware/bearer-auth/index.ts:160-215](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/bearer-auth/index.ts#L160-L215), [src/middleware/jwt/jwt.ts:160-173](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwt/jwt.ts#L160-L173), [src/middleware/jwk/jwk.ts:170-182](https://github.com/blade47/hono/blob/e50df01453e71b071c3e6136b161b160b9fdf916/src/middleware/jwk/jwk.ts#L170-L182)

## Related

- [JWT and JWK](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/technical/security-middleware/jwt-and-jwk)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/552ca36e-f67e-41c3-a07a-def9bd9551b0/llms.txt) for all pages in this wiki.
