---
title: "Secure Apache HTTP Server APIs with API Key Authentication"
description: "Secure your Apache HTTP Server API using a shared secret."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/c/apachehttpserver/secure-header"
framework: "Apache HTTP Server"
language: "C"
authStrategy: "shared secret header"
pageType: use-case
---

# Secure Apache HTTP Server APIs with API Key Authentication

Secure your Apache HTTP Server API using a shared secret.

## How Zuplo Handles It

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

## Apache HTTP Server Backend Code

```c
#include <httpd.h>
#include <http_protocol.h>
#include <http_config.h>
#include <http_log.h>
#include <apr_strings.h>
#include <apr_env.h>
#include <string.h>

// Timing safe string comparison
static int timing_safe_compare(const char *a, const char *b) {
    size_t i, match = 0;
    size_t len_a = strlen(a);
    size_t len_b = strlen(b);

    if (len_a != len_b) return 0;

    for (i = 0; i < len_a; i++) {
        match |= a[i] ^ b[i];
    }

    return match == 0;
}

// Handler to validate shared secret
static int validate_shared_secret(request_rec *r) {
    if (!r->handler || strcmp(r->handler, "protected-handler")) return DECLINED;

    const char *secret = apr_table_get(r->headers_in, "X-Shared-Secret");
    const char *expected_secret;

    if (apr_env_get(&expected_secret, "SHARED_SECRET", r->pool) != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Server configuration error: SHARED_SECRET not set");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    if (!secret) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Unauthorized: No secret provided");
        return HTTP_UNAUTHORIZED;
    }

    if (!timing_safe_compare(secret, expected_secret)) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Unauthorized: Invalid secret");
        return HTTP_UNAUTHORIZED;
    }

    return OK;
}

// Register the handler
static void register_hooks(apr_pool_t *pool) {
    ap_hook_handler(validate_shared_secret, NULL, NULL, APR_HOOK_MIDDLE);
}

// Module definition
module AP_MODULE_DECLARE_DATA secure_module = {
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    register_hooks
};
```

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