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

# Secure ASP.NET Core APIs with API Key Authentication

Secure your ASP.NET Core API using a shared secret.

## How Zuplo Handles It

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

## ASP.NET Core Backend Code

```csharp
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using System;
using System.Text;

public class ValidateSharedSecretAttribute : ActionFilterAttribute
{
    private readonly string _expectedSecret;

    public ValidateSharedSecretAttribute(IConfiguration configuration)
    {
        _expectedSecret = configuration["SHARED_SECRET"];
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var secret = context.HttpContext.Request.Headers["x-shared-secret"];

        if (string.IsNullOrEmpty(_expectedSecret))
        {
            context.Result = new StatusCodeResult(StatusCodes.Status500InternalServerError);
            return;
        }

        if (string.IsNullOrEmpty(secret))
        {
            context.Result = new UnauthorizedObjectResult(new { error = "No secret provided" });
            return;
        }

        if (!IsSecretValid(secret, _expectedSecret))
        {
            context.Result = new UnauthorizedObjectResult(new { error = "Invalid secret" });
            return;
        }

        base.OnActionExecuting(context);
    }

    private bool IsSecretValid(string secret, string expectedSecret)
    {
        if (secret.Length != expectedSecret.Length)
        {
            return false;
        }

        bool areEqual = true;
        for (int i = 0; i < secret.Length; i++)
        {
            areEqual &= secret[i] == expectedSecret[i];
        }
        return areEqual;
    }
}

[ApiController]
[Route("[controller]")]
public class ProtectedController : ControllerBase
{
    // Apply the shared secret validation filter
    [HttpGet]
    [ValidateSharedSecret]
    public IActionResult Get()
    {
        return Ok(new { message = "Access granted" });
    }
}

// In Program.cs, ensure configuration is set up
// var app = builder.Build();
// app.MapControllers();
// 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)
