---
title: "Secure Carter APIs with API Key Authentication"
description: "Secure your Carter API using a shared secret."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/csharp/carter/secure-header"
framework: "Carter"
language: "C#"
authStrategy: "shared secret header"
pageType: use-case
---

# Secure Carter APIs with API Key Authentication

Secure your Carter API using a shared secret.

## How Zuplo Handles It

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

## Carter Backend Code

```csharp
using Carter;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using System;
using System.Text;

public class ValidateSharedSecretMiddleware
{
    private readonly RequestDelegate _next;
    private readonly string _expectedSecret;

    public ValidateSharedSecretMiddleware(RequestDelegate next, IConfiguration configuration)
    {
        _next = next;
        _expectedSecret = configuration["SHARED_SECRET"];

        if (string.IsNullOrEmpty(_expectedSecret))
        {
            throw new InvalidOperationException("Server configuration error: SHARED_SECRET missing.");
        }
    }

    public async Task InvokeAsync(HttpContext context)
    {
        if (!context.Request.Headers.TryGetValue("X-Shared-Secret", out var secret) ||
            !IsTimingSafeEqual(secret, _expectedSecret))
        {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsync("Invalid or missing secret");
            return;
        }

        await _next(context);
    }

    private bool IsTimingSafeEqual(string secret, string expectedSecret)
    {
        return secret.Length == expectedSecret.Length &&
               CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(secret),
                                                      Encoding.UTF8.GetBytes(expectedSecret));
    }
}

public class ProtectedModule : CarterModule
{
    public ProtectedModule()
    {
        RequireAuthorization();

        Get("/protected", async (req, res) =>
        {
            await res.WriteAsync("Access granted");
        });
    }

    public override void AddRoutes(IEndpointRouteBuilder app)
    {
        app.MapCarter();
    }
}

public static class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        var app = builder.Build();

        app.UseMiddleware<ValidateSharedSecretMiddleware>();
        app.MapCarter();

        app.Run();
    }
}
```

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