Secure your ChatGPT API key on mobile and avoid leaks

Vivien Mahé
9 min readJan 30, 2024
Photo by Levart_Photographer on Unsplash

If you’ve been keeping up with recent news on products utilizing the OpenAI API, you may have come across some unfortunate stories. There have been incidents of ChatGPT API keys being leaked and subsequently exploited by hackers. This has led to substantial, unexpected bills for the affected parties.

Many stories are available, but I’ve preselected a few for you:

If this is news to you, let me offer a quick summary that could save you both time and money.

A little bit of context

To integrate ChatGPT, DALL·E, or other models into your project, you need to utilize the OpenAI API. This API facilitates communication between your project and the service. Be aware that the API is not free, and costs vary based on usage. (For a more detailed understanding of their pricing, I recommend visiting the OpenAI pricing page, though I won’t delve into those details here).

Authentication is required for the API to identify the client (whether it’s a mobile or web app) and to monitor API usage. To achieve this, you must create an API key through your OpenAI account and include it in every request to the API. This is typically done through the Authorization HTTP header in the format: Authorization: Bearer {OPENAI_API_KEY}.

And this is precisely where the security leaks occur!

When you send an HTTP request to a server, the headers, which include your API key, are visible. These can be easily intercepted using tools like Proxyman, Charles Proxy, and others.

What are the implications? For example, if you incorporate ChatGPT in your mobile app, anyone who has downloaded your app could potentially intercept the communication between your app and the OpenAI API. In doing so, they could retrieve your API key.

Proxyman screenshot - edited to show the OpenAI API key in HTTP headers

At this point, to prevent hackers from misusing your API key and to control your expenses, your only option is to delete the key from your OpenAI account and remove your app from the stores. (Simply updating your app with a new, rotated key doesn’t solve the problem, as it’s susceptible to the same issue.)

Remember, this caution isn’t exclusive to your OpenAI API key; it applies to any secret API key that shouldn’t be exposed.

Since I needed to use ChatGPT for my latest project, I began searching for a solution before even considering publishing my app. If you’re curious about my app, Quotell, you can check it out here: quotell.me.

Solution: Firebase + Google Secret Manager

If you’re a mobile developer like me, you often face situations where backend logic is necessary, but deploying a full-fledged backend might not be desirable. It can be time-consuming and require more effort than you’re willing to invest.

That’s why I opted for Firebase. It’s user-friendly and quick to set up. Firebase takes care of various aspects like authentication, database management, remote configuration, and more. Most importantly for our discussion, it offers Cloud Functions.

A Cloud Function is essentially an API endpoint hosted on Firebase. For example, if your project is named MyNewProject and you create a function called addUser, your endpoint would be something like:
https://us-central1-mynewproject.cloudfunctions.net/addUser

The solution, in brief, involves two key steps:

  • Use Cloud Functions as a middleman: Think of it as our backend. The workflow goes like this: The mobile app sends a request to Cloud Functions > Cloud Functions then calls the OpenAI API > The OpenAI API responds to Cloud Functions > Finally, Cloud Functions relays this response back to the mobile app.
  • Use Google Secret Manager for storing the OpenAI API key: This is a secure and cost-effective way to manage all your confidential data, usually at little to no cost.

(Note: There are alternative solutions that you might consider, depending on your specific needs. I chose this approach because it’s straightforward to set up and doesn’t require a separate backend.)

Let’s break down the process into clear, manageable steps for setting up the entire system:

1. Select a Firebase project
2. Store OpenAI API key in Google Secret Manager
3. Setup Firebase Cloud Functions
4. Create and configure your function locally
5. Get the code to call OpenAI API with Firebase Cloud Functions
6. Install required dependencies
7. Test on local Firebase emulators
8. Deploy your function to production
9. Add permissions to call your function
10. Configure your mobile app to call your function

1. Select a Firebase project

First, create a new Firebase project if you haven’t already (you can follow the official documentation for guidance), or select an existing one to proceed with.

2. Store OpenAI API key in Google Secret Manager

  • Navigate to Google Secret Manager and set up your account by following the provided instructions.
  • After setting up your account, select your project using the drop-down menu located in the top left corner of the screen.
  • Click on the “+ Create secret” button.
Create a new secret
  • On the creation screen, enter OPENAPI_API_KEY in the ‘Name’ field. Then, in the ‘Secret value’ field, paste your OpenAI API key, which you can find in your OpenAI account.
Save your OpenAI API key to Google Secret Manager

Your OpenAI API key is now securely stored in your Google Secret Manager account. You can return to this platform anytime you need to rotate, delete, or create a new key.

3. Setup Firebase Cloud Functions

In Firebase, ensure that your project is selected. Then, navigate to ‘Functions’ by clicking on ‘Build’ and then ‘Functions’ in the left-hand menu. You will be prompted to upgrade your plan from the free ‘Spark’ to the ‘Blaze’ pay-as-you-go plan. (It’s important to read through the pricing details, but note that you will not incur charges until you reach a significant usage limit.)

Firebase left panel to access Functions

4. Create and configure your function locally

To set up a Cloud Function on Firebase, you’ll first need to create and test it locally on your machine using the Firebase CLI, and then deploy it.

Follow the steps in this documentation to install Firebase CLI on your local machine, focusing on steps 2 through 4.

➡️ When selecting a language, choose JavaScript (this is important for our purpose).

➡️ You can skip step 5 (Add the "add message" function) and step 6 (Add the "make uppercase" function) as they are not necessary for our project.

When using Firebase CLI, begin by authenticating with the command firebase login. This command will provide a URL to open in your browser.

⚠️ If you encounter an error like Failed to get Firebase project MyNewProject. Please make sure the project exists and your account has permission to access it., it's likely due to an expired session. To resolve this, type firebase logout and then firebase login again.

5. Get the code to call OpenAI API with Firebase Cloud Functions

To streamline the process, I’ve prepared a gist containing the necessary code for the Cloud Function. On your local machine, simply replace the contents of functions/index.js with the code from this gist:

Here’s what it does in a few words:

  • Retrieves the OpenAI API key from your Google Secret Manager account.
  • Verifies that the request method is a POST.
  • Checks for user authentication against Firebase and validates the user’s ID token.
  • Configures and sends the request to the OpenAI API and then forwards the received response to the Firebase client, which is your mobile app.

This is just one example of how you can use Google Cloud Function to interact with the OpenAI API. Feel free to modify it according to your project’s requirements!
As I’m not primarily a JavaScript developer, any feedback, suggestions for improvement, or corrections are greatly appreciated 🙂

Extract from the gist — Request sent to OpenAI API

6. Install required dependencies

To ensure the script from the gist functions correctly, we need to install two essential dependencies:

  • Axios: A HTTP client for Node.js.
  • CORS (Cross-Origin Resource Sharing): A mechanism used to restrict access to specific domains.

To install these, open the terminal on your machine and navigate to the root directory of your project. Then, move into the functions directory using the command cd functions/. Once in the directory, execute the following command: npm install axios cors.

7. Test on local Firebase emulators

By this stage, you should be ready to test your Firebase Cloud Function locally on your machine. Firebase CLI will provide you with a URL to use for testing. This URL typically looks something like this:
http://127.0.0.1:5001/mynewproject/us-central1/addUser

I highly recommend testing the setup using an API platform like Postman. This will help you ensure that the communication between Firebase Cloud Functions and the OpenAI API is functioning as expected. Once you’re satisfied with the test results, you can then proceed to implement the mobile part of your project.

Firebase CLI on emulators

8. Deploy your function to production

Once everything is functioning flawlessly on your local machine, it’s time to deploy your project to production using Firebase Cloud Functions.

You can follow step 8 of the provided documentation, or simply execute the following command in your terminal: firebase deploy.

Upon successful deployment, Firebase will provide you with the production URL, which should look something like this:
https://us-central1-mynewproject.cloudfunctions.net/addUser

9. Add permissions to call your function

By default, your function is not accessible via the production URL due to missing permissions. To enable access, you need to grant permission for anyone to call this URL.

Firstly, ensure that you complete a successful deployment of your function. Once the deployment is successful, the next step is to grant access permissions. You do this by adding the Cloud Functions Invoker role to allUsers:
https://cloud.google.com/functions/docs/securing/managing-access-iam?hl=en#allowing_unauthenticated_htpp_function_invocation

Google Cloud — Add permission

You’ve now successfully set up Firebase Cloud Functions to interact with the OpenAI API, with your API key securely stored in Google Secret Manager.

10. Configure your mobile app to call your function

Now, the remaining task is to integrate this function into your mobile app.

Personally, I found using the Firebase Functions SDK quite time-efficient — it conveniently manages user authentication against Firebase, endpoint configuration, and more.

However, if you prefer a more hands-on approach, you can directly call your production URL and manage the configurations yourself.

And voilà! Congratulations on accomplishing this setup!

While this might not be the simplest solution available, it’s straightforward to set up and doesn’t require a separate backend. The entire setup, including implementation in my mobile app, took around 6 hours.

It’s an investment worth making — protecting your API key from leaks is crucial, and it’s far better to be proactive than to deal with the consequences later.

This is my first article on Medium, and I would greatly appreciate your feedback! 🙏

Feel free to leave a comment below or reach out to me directly:

--

--

Vivien Mahé

Creating mobile apps while sharing my journey and learnings.