> For the complete documentation index, see [llms.txt](https://docs.openbotauth.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openbotauth.org/sdks/nodejs.md).

# Node.js / TypeScript

The official Node.js SDK for OpenBotAuth signature verification.

**Package:** [@openbotauth/verifier-client](https://www.npmjs.com/package/@openbotauth/verifier-client)

## Installation

```bash
# npm
npm install @openbotauth/verifier-client

# pnpm
pnpm add @openbotauth/verifier-client

# yarn
yarn add @openbotauth/verifier-client
```

**Requirements:** Node.js >= 18.0.0

## Quick Start

### Express Middleware

The fastest way to integrate is with the Express middleware:

```typescript
import express from 'express';
import { openBotAuthMiddleware } from '@openbotauth/verifier-client/express';

const app = express();

// Add middleware (observe mode by default)
app.use(openBotAuthMiddleware());

app.get('/api/content', (req, res) => {
  const oba = (req as any).oba;

  if (oba.signed && oba.result?.verified) {
    // Verified bot - full access
    res.json({
      content: 'Full article content...',
      agent: oba.result.agent
    });
  } else {
    // Anonymous or unverified - limited access
    res.json({
      content: 'Article preview...',
      upgrade: 'Sign requests for full access'
    });
  }
});

app.listen(3000);
```

### Next.js App Router

For Next.js Server Components and Route Handlers:

```typescript
// app/api/content/route.ts
import { NextRequest, NextResponse } from 'next/server';
import {
  VerifierClient,
  buildVerifyRequestForNext,
  hasSignatureHeaders
} from '@openbotauth/verifier-client';

const client = new VerifierClient();

export async function GET(request: NextRequest) {
  // Check if request has signature headers
  if (!hasSignatureHeaders(request.headers)) {
    return NextResponse.json({ content: 'Preview only' });
  }

  // Build verification request from Next.js request
  const verifyRequest = buildVerifyRequestForNext(request);
  const result = await client.verify(verifyRequest);

  if (result.verified) {
    return NextResponse.json({
      content: 'Full content',
      agent: result.agent
    });
  }

  return NextResponse.json(
    { error: 'Verification failed', reason: result.error },
    { status: 401 }
  );
}
```

### Direct Client Usage

For custom integrations:

```typescript
import { VerifierClient, VerificationRequest } from '@openbotauth/verifier-client';

const client = new VerifierClient({
  verifierUrl: 'https://verifier.openbotauth.org/verify', // default
  timeoutMs: 5000 // default
});

const request: VerificationRequest = {
  method: 'GET',
  url: 'https://example.com/api/content',
  headers: {
    'host': 'example.com',
    'signature-input': 'sig=("@method" "@target-uri" "host");created=1699900000;keyid="key-1";alg="ed25519"',
    'signature': 'sig=:base64signature...:',
    'signature-agent': 'https://registry.openbotauth.org/jwks/mybot.json'
  }
};

const result = await client.verify(request);

if (result.verified) {
  console.log('Verified agent:', result.agent?.client_name);
  console.log('Key ID:', result.kid);
} else {
  console.log('Verification failed:', result.error);
}
```

## API Reference

### VerifierClient

Main client class for calling the verifier service.

```typescript
interface VerifierClientOptions {
  verifierUrl?: string;   // Default: 'https://verifier.openbotauth.org/verify'
  timeoutMs?: number;     // Default: 5000
}

class VerifierClient {
  constructor(options?: VerifierClientOptions);
  verify(request: VerificationRequest): Promise<VerificationResult>;
}
```

### VerificationRequest

Request object sent to the verifier:

```typescript
interface VerificationRequest {
  method: string;           // HTTP method (GET, POST, etc.)
  url: string;              // Full request URL
  headers: Record<string, string>;  // Request headers
  body?: string;            // Request body (for POST/PUT)
}
```

### VerificationResult

Response from the verifier:

```typescript
interface VerificationResult {
  verified: boolean;        // Whether signature is valid
  agent?: {                 // Agent info (if verified)
    client_name: string;
    client_uri?: string;
    // ... other agent metadata
  };
  kid?: string;             // Key ID used for signing
  jwks_url?: string;        // JWKS URL for the agent
  error?: string;           // Error message (if failed)
  created?: number;         // Signature creation timestamp
  expires?: number;         // Signature expiration timestamp
}
```

### Middleware Options

```typescript
interface MiddlewareOptions {
  verifierUrl?: string;     // Verifier service URL
  mode?: 'observe' | 'require-verified';  // Default: 'observe'
  attachProperty?: string;  // Request property name (default: 'oba')
  timeoutMs?: number;       // Verification timeout
}
```

### OBAState

State attached to requests by middleware:

```typescript
interface OBAState {
  signed: boolean;          // Request had signature headers
  result?: VerificationResult;  // Verification result (null if not signed)
}
```

## Header Utilities

Utility functions for working with RFC 9421 headers:

```typescript
import {
  hasSignatureHeaders,
  parseCoveredHeaders,
  extractForwardedHeaders
} from '@openbotauth/verifier-client';

// Check if request has signature headers
const hasSig = hasSignatureHeaders(request.headers);

// Parse covered headers from Signature-Input
const covered = parseCoveredHeaders(signatureInput);
// Returns: ['@method', '@target-uri', 'host', ...]

// Extract only safe headers for forwarding to verifier
const safeHeaders = extractForwardedHeaders(
  request.headers,
  coveredHeaders
);
```

## Security

### Sensitive Headers

The SDK automatically blocks sensitive headers from being forwarded to the verifier:

* `cookie`
* `authorization`
* `proxy-authorization`
* `www-authenticate`

If a `Signature-Input` references any of these headers, the request will be rejected.

### Timeout Handling

All verification requests have a configurable timeout (default 5 seconds). On timeout, verification is treated as failed.

## Middleware Modes

### Observe Mode (Default)

All requests pass through regardless of verification status. Use this for:

* Logging and analytics
* Gradual rollout
* A/B testing between verified and unverified access

```typescript
app.use(openBotAuthMiddleware({ mode: 'observe' }));
```

### Require-Verified Mode

Protected paths return 401 for unsigned or failed verification:

```typescript
app.use(openBotAuthMiddleware({
  mode: 'require-verified',
  protectedPaths: ['/api/premium', '/api/content']
}));
```

## Error Handling

```typescript
try {
  const result = await client.verify(request);
  if (!result.verified) {
    // Verification failed (invalid signature, expired, etc.)
    console.log('Reason:', result.error);
  }
} catch (error) {
  // Network error, timeout, or verifier service unavailable
  console.error('Verification error:', error);
}
```

## TypeScript Support

The package is written in TypeScript and exports all types:

```typescript
import type {
  VerifierClientOptions,
  VerificationRequest,
  VerificationResult,
  MiddlewareOptions,
  OBAState
} from '@openbotauth/verifier-client';
```

## Examples

### Express with Custom Verifier

```typescript
import express from 'express';
import { openBotAuthMiddleware } from '@openbotauth/verifier-client/express';

const app = express();

app.use(openBotAuthMiddleware({
  verifierUrl: 'https://your-verifier.example.com/verify',
  mode: 'observe',
  timeoutMs: 3000
}));

app.get('/api/data', (req, res) => {
  const { signed, result } = (req as any).oba;

  res.json({
    authenticated: signed && result?.verified,
    agent: result?.agent?.client_name || 'anonymous'
  });
});
```

### Next.js with Body Verification

```typescript
// For POST requests that need body in signature
import { buildVerifyRequestForNextWithBody } from '@openbotauth/verifier-client';

export async function POST(request: NextRequest) {
  const body = await request.text();
  const verifyRequest = buildVerifyRequestForNextWithBody(request, body);
  const result = await client.verify(verifyRequest);
  // ...
}
```

## Links

* **npm:** <https://www.npmjs.com/package/@openbotauth/verifier-client>
* **GitHub:** <https://github.com/OpenBotAuth/openbotauth>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.openbotauth.org/sdks/nodejs.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
