Authenticate OpenAI SDK clients with Key Authentication in Kong AI Gateway

Deployment Platform
Minimum Version
Kong Gateway - 3.6
TL;DR

The OpenAI SDK sends API keys as Bearer tokens in the Authorization header, which Key Auth doesn’t recognize. Add a Pre-function plugin to extract the Bearer token and rewrite it into a header that Key Auth expects, then configure Key Auth and AI Proxy Advanced as usual.

Prerequisites

This is a Konnect tutorial and requires a Konnect personal access token.

  1. Create a new personal access token by opening the Konnect PAT page and selecting Generate Token.

  2. Export your token to an environment variable:

     export KONNECT_TOKEN='YOUR_KONNECT_PAT'
    
  3. Run the quickstart script to automatically provision a Control Plane and Data Plane, and configure your environment:

     curl -Ls https://get.konghq.com/quickstart | bash -s -- -k $KONNECT_TOKEN --deck-output
    

    This sets up a Konnect Control Plane named quickstart, provisions a local Data Plane, and prints out the following environment variable exports:

     export DECK_KONNECT_TOKEN=$KONNECT_TOKEN
     export DECK_KONNECT_CONTROL_PLANE_NAME=quickstart
     export KONNECT_CONTROL_PLANE_URL=https://us.api.konghq.com
     export KONNECT_PROXY_URL='http://localhost:8000'
    

    Copy and paste these into your terminal to configure your session.

This tutorial requires Kong Gateway Enterprise. If you don’t have Kong Gateway set up yet, you can use the quickstart script with an enterprise license to get an instance of Kong Gateway running almost instantly.

  1. Export your license to an environment variable:

     export KONG_LICENSE_DATA='LICENSE-CONTENTS-GO-HERE'
    
  2. Run the quickstart script:

    curl -Ls https://get.konghq.com/quickstart | bash -s -- -e KONG_LICENSE_DATA 
    

    Once Kong Gateway is ready, you will see the following message:

     Kong Gateway Ready
    

decK is a CLI tool for managing Kong Gateway declaratively with state files. To complete this tutorial, install decK version 1.43 or later.

This guide uses deck gateway apply, which directly applies entity configuration to your Gateway instance. We recommend upgrading your decK installation to take advantage of this tool.

You can check your current decK version with deck version.

For this tutorial, you’ll need Kong Gateway entities, like Gateway Services and Routes, pre-configured. These entities are essential for Kong Gateway to function but installing them isn’t the focus of this guide. Follow these steps to pre-configure them:

  1. Run the following command:

    echo '
    _format_version: "3.0"
    services:
      - name: example-service
        url: http://httpbin.konghq.com/anything
    routes:
      - name: example-route
        paths:
        - "/anything"
        service:
          name: example-service
    ' | deck gateway apply -
    

To learn more about entities, you can read our entities documentation.

This tutorial uses OpenAI:

  1. Create an OpenAI account.
  2. Get an API key.
  3. Create a decK variable with the API key:

    export DECK_OPENAI_API_KEY='YOUR OPENAI API KEY'
    

To complete this tutorial, you’ll need Python (version 3.7 or later) and pip installed on your machine. You can verify it by running:

python3
python3 -m pip --version
  1. Create a virtual env:

    python3 -m venv myenv
    
  2. Activate it:

    source myenv/bin/activate
    

Install the OpenAI SDK:

pip install openai

The OpenAI SDK authenticates by sending Authorization: Bearer <api-key> with every request. This behavior is hardcoded in the SDK and can’t be changed.

The Key Auth plugin doesn’t inspect the Authorization header. It looks for an API key in a configurable header (default: apikey), a query parameter, or the request body. This means Key Auth rejects requests from the OpenAI SDK out of the box.

To work around this, you can use the Pre-function plugin to extract the Bearer token from the Authorization header and copy it into the header that Key Auth expects. Pre-function runs before Key Auth in Kong’s plugin execution order, so the rewritten header is in place by the time authentication happens.

If you use the OpenID Connect plugin instead of Key Auth, this workaround isn’t necessary. OIDC natively inspects Bearer tokens in the Authorization header.

Create a Consumer

Configure a Consumer with a Key Auth credential. The credential value is what OpenAI SDK clients will send as their api_key:

echo '
_format_version: "3.0"
consumers:
  - username: openai-client
    keyauth_credentials:
    - key: my-consumer-key
' | deck gateway apply -

Configure the Pre-function plugin

The Pre-function plugin intercepts incoming requests and rewrites the Authorization header. It extracts the Bearer token and copies it into the apikey header, where Key Auth can find it:

echo '
_format_version: "3.0"
plugins:
  - name: pre-function
    config:
      access:
      - |-
        local auth_header = kong.request.get_header("Authorization")
        if auth_header and auth_header:find("^Bearer ") then
          local key = auth_header:sub(8)
          kong.service.request.set_header("apikey", key)
        end
' | deck gateway apply -

Configure the Key Authentication plugin

Enable Key Auth on the route. The key_names value must match the header name set in the Pre-function code above:

echo '
_format_version: "3.0"
plugins:
  - name: key-auth
    config:
      key_names:
      - apikey
' | deck gateway apply -

Configure the AI Proxy Advanced plugin

Enable AI Proxy Advanced to proxy authenticated requests to OpenAI. The auth block here holds the upstream OpenAI API key, which is separate from the Consumer’s Key Auth credential:

echo '
_format_version: "3.0"
plugins:
  - name: ai-proxy-advanced
    config:
      targets:
      - route_type: llm/v1/chat
        auth:
          header_name: Authorization
          header_value: Bearer ${{ env "DECK_OPENAI_API_KEY" }}
        model:
          provider: openai
          name: gpt-4o
          options:
            max_tokens: 512
            temperature: 1.0
' | deck gateway apply -

Validate

Create a test script to verify the full authentication flow. The script uses the OpenAI Python SDK, pointing at your Kong Gateway Route with the Consumer’s Key Auth credential as the API key.

cat <<EOF > test_openai.py
from openai import OpenAI

kong_url = "http://localhost:8000"
kong_route = "anything"

client = OpenAI(
    api_key="my-consumer-key",
    base_url=f"{kong_url}/{kong_route}"
)

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Say hello."}]
)

print(response.choices[0].message.content)
EOF
cat <<EOF > test_openai.py
from openai import OpenAI
import os

kong_url = os.environ['KONNECT_PROXY_URL']
kong_route = "anything"

client = OpenAI(
    api_key="my-consumer-key",
    base_url=f"{kong_url}/{kong_route}"
)

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Say hello."}]
)

print(response.choices[0].message.content)
EOF

Run the script:

python test_openai.py

If authentication is configured correctly, you’ll see the model’s response printed to the terminal.

To confirm that Key Auth is actually enforcing access, create a second script with an invalid key:

cat <<EOF > test_openai_wrong_key.py
from openai import OpenAI

kong_url = "http://localhost:8000"
kong_route = "anything"

client = OpenAI(
    api_key="wrong-key",
    base_url=f"{kong_url}/{kong_route}"
)

try:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Say hello."}]
    )
    print(response.choices[0].message.content)
except Exception as e:
    print(f"Expected error: {e}")
EOF
cat <<EOF > test_openai_wrong_key.py
from openai import OpenAI
import os

kong_url = os.environ['KONNECT_PROXY_URL']
kong_route = "anything"

client = OpenAI(
    api_key="wrong-key",
    base_url=f"{kong_url}/{kong_route}"
)

try:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Say hello."}]
    )
    print(response.choices[0].message.content)
except Exception as e:
    print(f"Expected error: {e}")
EOF

Run the script:

python test_openai_wrong_key.py

This should return a 401 Unauthorized error, confirming that Kong rejects requests with invalid credentials.

Cleanup

If you created a new control plane and want to conserve your free trial credits or avoid unnecessary charges, delete the new control plane used in this tutorial.

curl -Ls https://get.konghq.com/quickstart | bash -s -- -d
Something wrong?

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!