---
title: "Add JWT Authentication to Your NancyFX API"
description: "Secure your NancyFX API using JWT authentication with JWKS."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/csharp/nancyfx/jwt-backend"
framework: "NancyFX"
language: "C#"
authStrategy: "JWT with JWKS"
pageType: use-case
---

# Add JWT Authentication to Your NancyFX API

Secure your NancyFX API using JWT authentication with JWKS.

## How Zuplo Handles It

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

## NancyFX Backend Code

```csharp
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Threading.Tasks;
using IdentityModel;
using IdentityModel.Client;
using Microsoft.IdentityModel.Tokens;
using Nancy;
using Nancy.Bootstrapper;
using Nancy.TinyIoc;

public class JwtAuthenticationBootstrapper : DefaultNancyBootstrapper
{
    private const string Issuer = "https://my-api-a32f34.zuplo.api/__zuplo/issuer";
    private const string JwksUri = Issuer + "/.well-known/jwks.json";
    private JsonWebKeySet _jwks;

    protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
    {
        LoadJwks();

        pipelines.BeforeRequest += async (ctx, _) => await AddJwtAuthentication(ctx);
    }

    private async Task LoadJwks()
    {
        var client = new HttpClient();
        var response = await client.GetDiscoveryDocumentAsync(Issuer);

        if (!response.IsError)
        {
            _jwks = new JsonWebKeySet(response.Json);
        }
        else
        {
            throw new Exception("Error loading JWKS: " + response.Error);
        }
    }

    private async Task<Response> AddJwtAuthentication(NancyContext context)
    {
        var token = context.Request.Headers.Authorization?.Replace("Bearer ", "");

        if (string.IsNullOrWhiteSpace(token))
        {
            return CreateUnauthorizedResponse("No token provided");
        }

        var handler = new JwtSecurityTokenHandler();
        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidIssuer = Issuer,
            ValidateIssuer = true,
            ValidateAudience = false,
            ValidateLifetime = true,
            IssuerSigningKeys = _jwks.GetSigningKeys()
        };

        try
        {
            handler.ValidateToken(token, tokenValidationParameters, out _);
            return null; // Continue processing
        }
        catch (Exception ex)
        {
            return CreateUnauthorizedResponse("Invalid token: " + ex.Message);
        }
    }

    private Response CreateUnauthorizedResponse(string message)
    {
        return new Response
        {
            StatusCode = HttpStatusCode.Unauthorized,
            ReasonPhrase = message
        };
    }
}

public class ProtectedModule : NancyModule
{
    public ProtectedModule()
    {
        Get("/protected", _ =>
        {
            return Response.AsJson(new { 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)
