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

# Secure Hanami APIs with API Key Authentication

Secure your Hanami API using a shared secret.

## How Zuplo Handles It

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

## Hanami Backend Code

```ruby
# config/application.rb
require "openssl"

module MyApp
  class Application < Hanami::Application
    config.middleware.use :shared_secret_validator

    # Other configurations...
  end
end

# lib/middleware/shared_secret_validator.rb
module Middleware
  class SharedSecretValidator
    def initialize(app)
      @app = app
    end

    def call(env)
      request = Rack::Request.new(env)
      secret = request.get_header("HTTP_X_SHARED_SECRET")
      expected_secret = ENV["SHARED_SECRET"]

      unless expected_secret
        return [500, { "Content-Type" => "application/json" }, [{ error: "Server configuration error" }.to_json]]
      end

      unless secret
        return [401, { "Content-Type" => "application/json" }, [{ error: "No secret provided" }.to_json]]
      end

      unless secure_compare(secret, expected_secret)
        return [401, { "Content-Type" => "application/json" }, [{ error: "Invalid secret" }.to_json]]
      end

      @app.call(env)
    end

    private

    def secure_compare(a, b)
      return false if a.bytesize != b.bytesize

      OpenSSL.fixed_length_secure_compare(a, b)
    end
  end
end

# in your routes configuration
module MyApp
  class Routes < Hanami::Routes
    define do
      get '/protected', to: ->(env) { [200, { 'Content-Type' => 'application/json' }, [{ message: "Access granted" }.to_json]] }, use: Middleware::SharedSecretValidator
    end
  end
end
```

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