---
title: "Secure Axum APIs with API Key Authentication"
description: "Secure your Axum API using a shared secret."
canonicalUrl: "https://zuplo.com/use-cases/api-key-auth/rust/axum/secure-header"
framework: "Axum"
language: "Rust"
authStrategy: "shared secret header"
pageType: use-case
---

# Secure Axum APIs with API Key Authentication

Secure your Axum API using a shared secret.

## How Zuplo Handles It

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

## Axum Backend Code

```rust
use axum::{
    body::Body,
    http::{Request, StatusCode},
    response::{IntoResponse, Response},
    routing::get,
    Router,
};
use tokio::sync::OnceCell;
use hyper::header::HeaderName;
use tower::ServiceBuilder;
use std::sync::Arc;
use axum::middleware::Next;
use axum::middleware::from_fn;
use constant_time_eq::constant_time_eq;

static SHARED_SECRET: OnceCell<Arc<String>> = OnceCell::const_new();

async fn validate_shared_secret<B>(
    req: Request<B>,
    next: Next<B>,
) -> Result<Response, StatusCode> {
    let secret_header_name = HeaderName::from_static("x-shared-secret");

    let expected_secret = SHARED_SECRET.get_or_init(|| {
        Arc::new(std::env::var("SHARED_SECRET").unwrap_or_else(|_| {
            panic!("SHARED_SECRET environment variable is not set")
        }))
    });

    let secret = req.headers().get(&secret_header_name).ok_or(StatusCode::UNAUTHORIZED)?;

    if !constant_time_eq(secret.as_bytes(), expected_secret.as_bytes()) {
        return Err(StatusCode::UNAUTHORIZED);
    }

    Ok(next.run(req).await)
}

async fn protected_handler() -> impl IntoResponse {
    (StatusCode::OK, "Access granted")
}

#[tokio::main]
async fn main() {
    dotenv::dotenv().ok();

    let app = Router::new()
        .route("/protected", get(protected_handler))
        .layer(
            ServiceBuilder::new()
                .layer(from_fn(validate_shared_secret))
        );

    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}
```

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