---
title: "Secure Nitro APIs with API Key Authentication"
description: "Secure your Nitro API using a shared secret."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/typescript/nitro/secure-header"
framework: "Nitro"
language: "TypeScript"
authStrategy: "shared secret header"
pageType: use-case
---

# Secure Nitro APIs with API Key Authentication

Secure your Nitro API using a shared secret.

## How Zuplo Handles It

Put Zuplo in front of your Nitro backend to authenticate API keys and forward a shared secret header so your origin only accepts traffic from Zuplo.

## Nitro Backend Code

```typescript
import { defineEventHandler, getHeader, sendError, createError } from "h3";
import { timingSafeEqual } from "crypto";

// Middleware to validate shared secret header
const validateSharedSecret = defineEventHandler((event) => {
  const secret = getHeader(event, "x-shared-secret");
  const expectedSecret = process.env.SHARED_SECRET;

  if (!expectedSecret) {
    throw createError({
      statusCode: 500,
      statusMessage: "Server configuration error",
    });
  }

  if (!secret) {
    throw createError({ statusCode: 401, statusMessage: "No secret provided" });
  }

  // Use timing-safe comparison to prevent timing attacks
  if (!timingSafeEqual(Buffer.from(secret), Buffer.from(expectedSecret))) {
    throw createError({ statusCode: 401, statusMessage: "Invalid secret" });
  }
});

// Example protected handler
export default defineEventHandler(async (event) => {
  validateSharedSecret(event);

  return {
    message: "Access granted",
  };
});
```

## Example Request

```bash
curl -X GET \
  'https://your-api.zuplo.dev/your-route' \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

## Learn More

- [API Key Authentication on Zuplo](https://zuplo.com/docs/policies/api-key-auth-inbound)
- [JWT Authentication on Zuplo](https://zuplo.com/docs/policies/open-id-jwt-auth-inbound)
- [All use cases](https://zuplo.com/use-cases)
