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

# Add JWT Authentication to Your Carter API

Secure your Carter API using JWT authentication with JWKS.

## How Zuplo Handles It

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

## Carter Backend Code

```csharp
using Carter;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        var issuer = "https://my-api-a32f34.zuplo.api/__zuplo/issuer";
        var jwksUri = $"{issuer}/.well-known/jwks.json";

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
        {
            options.RequireHttpsMetadata = true;
            options.Authority = issuer;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidIssuer = issuer,
                ValidateIssuerSigningKey = true,
                IssuerSigningKeyResolver = (token, securityToken, kid, parameters) =>
                {
                    // Fetch the JWKS data
                    var httpClient = new HttpClient();
                    var jwks = httpClient.GetStringAsync(jwksUri).Result;
                    var keys = new JsonWebKeySet(jwks);
                    return keys.Keys;
                },
                ValidateLifetime = true,
                ValidateAudience = false,
            };
        });

        services.AddCarter();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(builder => builder.MapCarter());
    }
}

public class AuthModule : CarterModule
{
    public AuthModule()
    {
        this.RequireAuthorization();

        Get("/protected", async (req, res) =>
        {
            var user = req.HttpContext.User;
            if (!user.Identity.IsAuthenticated)
            {
                res.StatusCode = 401;
                await res.WriteAsync("Access denied");
                return;
            }

            await res.WriteAsync($"Access granted, user: {user.Identity.Name}");
        });
    }
}
```

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