How to hide api key in params when user making api call

Dear community, I have an action with two input parameters: text and api_key. I don’t want a user to provide API key so I hardcoded it in instructions.
At the same time, I want to keep this API key hidden from the user, however each time it goes into action and prints parameters.

{
  "api_key": "actual API key",
  "text": "user's text"
}

Is there any way to hide the API key and keep my API secure with API key ?

Hey there and welcome to the community!

Whoooa there buddy, yeah don’t send your API key as a message.

So, the API key should stored as an environment variable (with extra precautions) on the server side. Meaning your system(s).

Basically, you as the developer are running code inside your own box, and sending only the data the client application needs (in this case, txt/strings).

2 Likes

The standard way to achieve your goal is in the action builder where you select the authentication method.

The API key will be encrypted and stored on OpenAIs servers. Then when the action is executed the API key will be send with the request headers and cannot be viewed by the users.

2 Likes

I did not catch this was about custom GPT auth and not the actual OpenAI API :sweat_smile:. Oops. Thanks for swooping in here!

2 Likes

The problem is many APIs expect the API key as part of the query string.

You can hard code it in your spec, but it will be user visible.

The only way around this (if you’re not calling an API you yourself are hosting) is to set up an API gateway (either locally or hosted) to add the key to the query string on the fly.

2 Likes

I could not agree more but for starters this is the right direction.

The documentation for API auth could need a little upgrade.

1 Like

thanks, yeah, I experimented with authentication, but it never reads API key and throws me bad gateway.
I’ve tried both bearer and custom auth.
This is the last version I tried (this is just a sample to ping):

API:

@app.get("/ping")
async def ping(api_key: str, dependencies=[Depends(get_bearer_api_key)]):
    return {"message": "the secret word is `bear`"}

def get_bearer_api_key(request: Request) -> str:
    authorization: str = request.headers.get("Authorization")
    if not authorization:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Authorization header is missing",
        )
    prefix = "Bearer "
    if authorization.startswith(prefix):
        api_key = authorization[len(prefix):].strip()
        if api_key == MY_VERY_SECRET_KEY:
            return api_key
    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Invalid API Key"
    )

And Openapi specification:

openapi: 3.0.0
info:
  title: API Key Validation Service
  version: 1.0.0
servers:
  - url: https://proxy_sample_api
    description: Production server
paths:
  /ping:
    get:
      summary: Validates the API key and returns a secret message
      operationId: ping
      security:
        - BearerAuth: []
      responses:
        "200":
          description: Successful API key validation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SecretMessage"
        "401":
          description: Unauthorized - Invalid API Key or Authorization header is missing
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
  schemas:
    SecretMessage:
      type: object
      properties:
        message:
          type: string
    MissingApiKeyError:
      type: object
      properties:
        detail:
          type: string
security:
  - BearerAuth: []

I am really confused why it isn’t working

Thanks everyone, it finally worked with the custom header. I’ve added an alias to make sure that it uses the same parameter:
str = Header(..., alias="api-key")

1 Like