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

# Secure Koa APIs with API Key Authentication

Secure your Koa API using a shared secret.

## How Zuplo Handles It

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

## Koa Backend Code

```javascript
const Koa = require("koa");
const Router = require("@koa/router");
const crypto = require("crypto");

const app = new Koa();
const router = new Router();

function validateSharedSecret(ctx, next) {
  const secret = ctx.headers["x-shared-secret"];
  const expectedSecret = process.env.SHARED_SECRET;

  if (!expectedSecret) {
    ctx.status = 500;
    ctx.body = { error: "Server configuration error" };
    return;
  }

  if (!secret) {
    ctx.status = 401;
    ctx.body = { error: "No secret provided" };
    return;
  }

  if (
    secret.length !== expectedSecret.length ||
    !crypto.timingSafeEqual(Buffer.from(secret), Buffer.from(expectedSecret))
  ) {
    ctx.status = 401;
    ctx.body = { error: "Invalid secret" };
    return;
  }

  return next();
}

router.get("/protected", validateSharedSecret, (ctx) => {
  ctx.body = {
    message: "Access granted",
  };
});

app.use(router.routes()).use(router.allowedMethods());

app.listen(3000, () => {
  console.log("Server running on http://localhost:3000");
});
```

## 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)
