---
title: "Add JWT Authentication to Your Moleculer API"
description: "Secure your Moleculer API using JWT authentication with JWKS."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/javascript/moleculer/jwt-backend"
framework: "Moleculer"
language: "JavaScript"
authStrategy: "JWT with JWKS"
pageType: use-case
---

# Add JWT Authentication to Your Moleculer API

Secure your Moleculer API using JWT authentication with JWKS.

## How Zuplo Handles It

Let Zuplo issue short-lived JWTs signed with a JWKS your Moleculer backend can verify — no long-lived API keys touch your origin.

## Moleculer Backend Code

```javascript
const { ServiceBroker } = require("moleculer");
const ApiGateway = require("moleculer-web");
const jwt = require("jsonwebtoken");
const jwksClient = require("jwks-rsa");

const ISSUER = "https://my-api-a32f34.zuplo.api/__zuplo/issuer";

const client = jwksClient({
  jwksUri: `${ISSUER}/.well-known/jwks.json`,
  cache: true,
  cacheMaxAge: 600000,
});

function getKey(header, callback) {
  client.getSigningKey(header.kid, (err, key) => {
    if (err) return callback(err);
    callback(null, key.getPublicKey());
  });
}

const broker = new ServiceBroker();

broker.createService({
  name: "api",
  mixins: [ApiGateway],
  settings: {
    routes: [
      {
        path: "/api",
        authorization: true,
        aliases: {
          "GET /protected": "protected.get",
        },
      },
    ],
  },
  methods: {
    authorize(ctx, route, req) {
      const auth = req.headers["authorization"];
      if (!auth || !auth.startsWith("Bearer ")) {
        return Promise.reject(
          new ApiGateway.Errors.UnAuthorizedError("NO_TOKEN"),
        );
      }

      const token = auth.slice(7);

      return new Promise((resolve, reject) => {
        jwt.verify(
          token,
          getKey,
          { issuer: ISSUER, algorithms: ["RS256"] },
          (err, decoded) => {
            if (err) {
              reject(new ApiGateway.Errors.UnAuthorizedError("INVALID_TOKEN"));
            } else {
              ctx.meta.user = decoded;
              resolve(ctx);
            }
          },
        );
      });
    },
  },
});

broker.createService({
  name: "protected",
  actions: {
    get(ctx) {
      return { message: "Access granted", user: ctx.meta.user };
    },
  },
});

broker.start();
```

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