GPTs won't recognize API authorizations?

I’ve been practicing with OpenAPI and setting up basic GPTs that take data via API.

I’ve set up basic authentication as per the API documentation.

I’ve tried everything outside GPTs, and the connection works.

Then I tried via GPTs and got errors that the API authentication key is not correct. I tried to use it inside the OpenAI schema and via the authentication panel, but got the same result - it cannot recognize it.

Then I said, “Take this key and execute,” and it worked.

My question is, how can I set up the schema or authentication so it takes the key into account?

2 Likes

Are you converting the authentication for Base Auth in the Base64 format? You must convert it first, then provide that string (which will contain your username:password values) in the authentication box.

I hope this helps.

1 Like

Appreciate your answer.

I’ve never heard about this approach, but do you have a source on how to set this up or an example that you could share? (I’m literally having a headache for the past week figuring this out with authentication.)

I’ve checked about the Base64. Is it about binary?

Look, there’s a protocol for operating in the API world. Authentication is one of them.

In the past - early beginning of the internet, the credentials were flowing free, in a text format. Then, people started to realize that needs some sort of encryption. The base64 is an algorithm that encrypt your message in a scrambled way so you can’t figure it out by just looking at it.

That’s why today we have the TLS/SSL (which basically do the same, but by using keys, instead of a fixed protocol).

With the base64, it’s easy to encode/decode, so, that’s why you must use HTTPS in your API calls instead of HTTP only.

What you need to do is convert the credentials like:

username:password

and paste the base64 value in the authentication, in this case, this is the value I got from the website:

dXNlcm5hbWU6cGFzc3dvcmQ=

The Authentication Type is API Key, and Auth Type is BASIC.

For all BASIC Authentication (remember, there’s a protocol, a set of rules), you must provide the API key, in base64 format by username:password.

What if the API auth I need just has the API and no username. We just need to pass the API to the key parameter like this ?key=API-KEY
image

Got it!

But how do you implement the code so that a person cannot reverse engineer it?

My question was how to set up API authentication. It seems that with the current GPT platform, whenever a key is added, the API thinks it is not added.

I can only hardcode inside the instructions, which is a big red flag for that case.

1 Like

I got it now, and indeed Base needs Base64 check this:
https://swagger.io/docs/specification/authentication/basic-authentication/

Now what work in my case is a NEW option for APIs in query which is not yet available for GPTs.

image

2 Likes

Did you manage to establish any kind of APi connection? (with authentification)

1 Like

I don’t see that new Query option, but anyway the OpenAPI spec already indicate in the security schema that the key should be passed as query parameter and with which key name. Shouldn’t that be enough to make the request properly?

I solved this issue by using the Custom option, then setting a header to pass the API Key (my API endpoint allow both options for passing the key, query and header), and that worked nicely.

I hope that helps :slight_smile:

3 Likes

in my case all I have been trying to do is add an API in the query which is not an available option, were you not able to make it work with any of the available options?

My screenshot is what I would like to see OpenAI offer, it is not available as an option yet I added that manually (inspect element).

1 Like

I like it, but going to need one for each thing that needs authing to.

Ok! Nice hack :slight_smile:

You can try the header option, seems to work better than query parameter

Well the receiving end only accept the API in query in my case.

2 Likes

If you don’t control the receiving end, you can always do a small proxy API, and there change the header received from the GPT, into a query param for the real API.

2 Likes

Love it, will try and let you guys know.

Any chance you could share schema template that shows authentification and the custom option example?

It doesn’t matter which security schema you set in the OpenAPI spec, as when selecting Custom it will use that configuration. Anyway, this is how to define a security schema in your OpenAPI Sepcification for an API key that goes as query parameter:

{
  "openapi": "3.0.1",
  ...
  "components": {
    "schemas": {...},
    "securitySchemes": {
      "function_key": {
        "type": "apiKey",
        "name": "code",
        "in": "query"
      }
    }
  }
}

And the custom option for using headers instead of query parameters:
Screenshot 2023-11-16 at 13.39.14

1 Like

Thanks man I finally got it to work using Cloudflare Workers. It takes the API from headers and sends it in query. The API was secure and never shared anywhere in frontend. I used the following code in the cloudflare worker.

image

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  // Extract the API key from the header
  const apiKey = request.headers.get('X-Api-Key');

  // If no API key, return an error
  if (!apiKey) {
    console.log('API key is missing'); // Log missing API key
    return new Response('API key is missing', { status: 400 });
  }

  // Clone the request to modify it
  const newRequest = new Request(request);

  // Construct the new URL using the external API base, maintaining the path and query parameters
  const url = new URL(newRequest.url);
  url.hostname = 'api.CUSOTMAPI.com'; // Replace with the external API's hostname
  url.searchParams.append('key', apiKey); // Append the API key as a query parameter

  // Log each parameter found in the original request URL
  const originalUrl = new URL(request.url);
  originalUrl.searchParams.forEach((value, key) => {
    console.log('Original param:', key, value); // Log the key and value of each parameter
    if (key.toLowerCase() !== 'x-api-key') {
      url.searchParams.set(key, value); // Set or overwrite the parameter
    }
  });

  console.log('Modified URL:', url.toString()); // Log the final URL to be fetched

  // Create a new Headers object from the original request's headers
  const newHeaders = new Headers(request.headers);

  // Remove the API key header from the new headers
  newHeaders.delete('X-Api-Key');

  // Make a new request with the updated headers and original request's body
  const modifiedRequest = new Request(url, {
    method: request.method,
    headers: newHeaders,
    body: request.method === 'POST' ? null : request.body
  });

  // Log the final modified request
  console.log('Modified request:', modifiedRequest);

  // Make the new request to the external API
  const response = await fetch(modifiedRequest);
  
  // Log the status of the response
  console.log('Response status:', response.status);
  
  // Return the response from the external API
  return response;
}
3 Likes

Great that you managed to make it work! Happy to help :slight_smile:

1 Like