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

# Secure undefined APIs with API Key Authentication



## How Zuplo Handles It

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

## undefined Backend Code

```python
import os
import tornado.ioloop
import tornado.web
import hmac
import hashlib

# Middleware to validate shared secret header
class ValidateSharedSecret(tornado.web.RequestHandler):
    def prepare(self):
        secret = self.request.headers.get("X-Shared-Secret")
        expected_secret = os.getenv("SHARED_SECRET")

        if not expected_secret:
            self.set_status(500)
            self.finish({"error": "Server configuration error"})
            return

        if not secret:
            self.set_status(401)
            self.finish({"error": "No secret provided"})
            return

        # Use HMAC with SHA256 for timing-safe comparison
        if not hmac.compare_digest(secret, expected_secret):
            self.set_status(401)
            self.finish({"error": "Invalid secret"})
            return

# Example handler using the shared secret middleware
class ProtectedHandler(ValidateSharedSecret):
    def get(self):
        self.write({"message": "Access granted"})

def make_app():
    return tornado.web.Application([
        (r"/protected", ProtectedHandler),
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()
```

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