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

# Add JWT Authentication to Your FoalTS API

Secure your FoalTS API using JWT authentication with JWKS.

## How Zuplo Handles It

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

## FoalTS Backend Code

```typescript
import {
  Config,
  dependency,
  Get,
  Hook,
  HttpResponseUnauthorized,
  ParseJWT,
  TokenRequired,
} from "@foal/core";
import { fetch, JwksRsa } from "jwks-client";

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

export class ApiController {
  // Setup the JWKS client
  private jwksClient = new JwksRsa({
    clientOptions: {
      jwksUri: `${ISSUER}/.well-known/jwks.json`,
      cache: true,
      cacheMaxAge: 600000, // 10 minutes
    },
  });

  // Hook to validate JWT
  @Hook(() => TokenRequired({ user: ParseJWT({ required: true }) }))
  @Hook(() => async (ctx, services) => {
    const token = ctx.request.token;
    if (!token) {
      return new HttpResponseUnauthorized({ error: "No token provided" });
    }

    return this.jwksClient
      .getSigningKey(token.header.kid)
      .then((key) => {
        token.verify({
          key: key.getPublicKey(),
          options: {
            issuer: ISSUER,
            algorithms: ["RS256"],
          },
        });
      })
      .catch((err) => {
        return new HttpResponseUnauthorized({
          error: "Invalid token",
          details: err.message,
        });
      });
  })

  // Example protected route
  @Get("/protected")
  protected(ctx) {
    return {
      message: "Access granted",
      user: ctx.user,
    };
  }
}
```

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