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

# Secure Bottle APIs with API Key Authentication

Secure your Bottle API using a shared secret.

## How Zuplo Handles It

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

## Bottle Backend Code

```python
from bottle import Bottle, request, response, HTTPResponse
import os
import hmac
import hashlib

app = Bottle()

def validate_shared_secret():
    def decorator(func):
        def wrapper(*args, **kwargs):
            secret = request.headers.get('X-Shared-Secret')
            expected_secret = os.getenv('SHARED_SECRET')

            if not expected_secret:
                return HTTPResponse(status=500, body="Server configuration error")

            if not secret:
                return HTTPResponse(status=401, body="No secret provided")

            if not timing_safe_compare(secret, expected_secret):
                return HTTPResponse(status=401, body="Invalid secret")

            return func(*args, **kwargs)

        return wrapper
    return decorator

def timing_safe_compare(val1, val2):
    return hmac.compare_digest(val1, val2)

@app.get('/protected')
@validate_shared_secret()
def protected_route():
    return {'message': 'Access granted'}

if __name__ == '__main__':
    app.run(host='localhost', port=8080)
```

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