greenpau / caddy-security

🔐 Authentication, Authorization, and Accounting (AAA) App and Plugin for Caddy v2. 💎 Implements Form-Based, Basic, Local, LDAP, OpenID Connect, OAuth 2.0 (Github, Google, Facebook, Okta, etc.), SAML Authentication. MFA/2FA with App Authenticators and Yubico. 💎 Authorization with JWT/PASETO tokens. 🔐
https://authcrunch.com/
Apache License 2.0
1.49k stars 73 forks source link

question: API Key in Authorization: Bearer header #321

Open mitja opened 9 months ago

mitja commented 9 months ago

I would like to support client authentication with API Keys stored in an Authorization: Bearer header

If I understand correctly, the API key can be passed via the X-Api-Key header. I would like to be able to use the Authorization: Bearer header, instead or in addition to that.

The rationale is, that I could use Caddy with Caddy Security as an API Gateway for a self-hosted OpenAI API compatible Rest API (eg. as provided by Ollama). This would be immediately usable by the large number of clients, such as OpenWebUI. The OpenAI API uses Authorization: Bearer.

As per the discussion in issue 116 the following config makes auth with header X-Api-Key possible:

security {
  authorization policy mypolicy {
    with basic auth portal myportal realm local
    with api key auth portal myportal realm local
  }
}

On the other hand, Token validation can be activated with Authorization: Bearer with this config:

{
  security {
    authorization policy mypolicy {
      validate bearer header
    }
  }
}
curl --insecure -H "Authorization: Bearer JWT_TOKEN" -v https://localhost:8443/myapp

Is there a way to "merge" the two or set one header based on the other to achieve the following?

curl --insecure -H "Authorization: Bearer API_KEY" -v https://localhost:8443/myapp
mitja commented 8 months ago

I think it can be solved with two Caddies behind each other. The first copies the API token from the Authorization header to the X-Api-Key header. The second protects the route(s) with caddy-security.

I have checked with httpbin that the X-Api-Token header is set correctly with this Caddyfile:

:80 {
    @apikey {
        header_regexp apikey Authorization "Bearer (?P<apikey>[a-f0-9]+)"
    }

    route @apikey {
        reverse_proxy httpbin:8080 {
            header_up +X-Api-Key {http.regexp.apikey.apikey}
        }
    }
}

This docker-compose.yml file:

version: '3'
services:
  httpbin:
    image: mccutchen/go-httpbin
    command: ['/bin/go-httpbin', '-port', '8080']
  reverse_proxy:
    image: caddy
    depends_on:
      - httpbin
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
    ports:
      - "8000:80"

And this command:

curl -H "Authorization: Bearer 123456789" -c -U http://localhost:8000/headers

Response:

{
  "headers": {
    "Accept": [
      "*/*"
    ],
    "Accept-Encoding": [
      "gzip"
    ],
    "Authorization": [
      "Bearer 123456789"
    ],
    "Host": [
      "localhost:8000"
    ],
    "User-Agent": [
      "curl/8.4.0"
    ],
    "X-Api-Key": [
      "123456789"
    ],
    "X-Forwarded-For": [
      "172.25.0.1"
    ],
    "X-Forwarded-Host": [
      "localhost:8000"
    ],
    "X-Forwarded-Proto": [
      "http"
    ]
  }
}

Maybe it even works by just protecting the specific route with caddy-security in the same single Caddy, but I am unsure if the header values are copied early enough.

Haven't tried it, yet, with caddy-security, though.

faithiyanuekun22 commented 3 months ago

Roqqu Account Reactivation