WrapFast includes a simple Node.js backend to make requests to OpenAI’s and Anthropic’s API.
The purpose of this is prevent storing the API keys within the mobile app and making the requests from there. It’s a pretty bad practice because anyone can easily sniff your HTTP requests and extract the key, for example using the utility proxy Charles.
To avoid this, and save thousand of dollars for you being hacked, WrapFast hides the HTTP request behind a custom backend.
<aside> 💡 If you do not want to deploy a backend, as another option WrapFast supports AI Proxy to make requests securely to OpenAI without exposing your API key. You will find implementations of ChatGPT, Vision and DALL-E in each service class.
Feel free to create an account and check their documentation here: aiproxy.pro Integration Guide: https://www.aiproxy.pro/docs/integration-guide.html Docs: https://github.com/lzell/AIProxySwift?tab=readme-ov-file#how-to-update-the-package
</aside>
The backend implements 4 endpoints that are called from the iOS boilerplate:
/auth GET Endpoint to authenticate and obtain a secret key/chatgpt POST Endpoint to make requests to ChatGPT API/vision POST Endpoint to make requests to Vision API/dalle POST Endpoint to make requests to DALL·E API<aside> ⚠️
For using the new GPT Image Generation you need to “Verify your Organization”, which for OpenAI means just authenticating your ID. It’s pretty fast and straightforward step and it’s enough with your driving license and so on.
</aside>
/gpt-image POST Endpoint. Works same as Dall-E but using the latest GPT Image generation API/gpt-image-edits POST Endpoint for sending a prompt and an image in order to make edits. This is the one you would use for creating images in ghibli style. GPT Image generation API/anthropic-messages POST Endpoint to make requests to Anthropic APILet's take a closer look at them later, but first let's learn how to set up and deploy our backend.
First of all you need to have installed Node.js and NPM in your Mac.
The minimum required Node version is 21.2.0
To install it just open a Terminal and paste this commands:
brew install node
<aside> ⚠️ If you don’t have Homebrew installed, paste this on your Terminal: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
</aside>
Type node -v to check that Node is correctly installed.
You can find the variables that the WrapFast backend uses in the .env.example file.
Remove the trailing .example and open it and replace the values with the proper ones:
<aside>
⚠️ Take into account that the .env file is ignored by Git, because it is included in the .gitgnore file.
</aside>
API_KEY Your OpenAI’s API key. You can find it in your OpenAI Dashboard, within API Keys section.ANTHROPIC_API_KEY Your Anthropic’s API key. You can find it in your Anthropic Console, within API Keys section.AUTH_SECRET_KEY and HMAC_SECRET_KEY Secret keys to authenticate your iOS app against the backend. You have to generate them executing the script secret_generator.js in a Terminal:node secret_generator.js
It generates a new secret key every time you execute it. Generate two and paste it in AUTH_SECRET_KEY and HMAC_SECRET_KEY
You will learn below how the Authentication Flow works. For now just replace the variables 🙂
AUTH_LIMIT Number of requests per user, per 5 minutes allowed to authentication endpoint. These limits are for preventing abuse to your backend. Tweak it if you need it.PROMPT_LIMIT Number of requests per user, per 5 minutes allowed to OpenAI endpoints. These limits are for preventing abuse to your backend. Tweak it if you need it.VISION_MAX_TOKENS Maximum tokens of Vision text response to prevent excessive costs. Tweak it regarding your needs. The more tokens used, the more API cost.ANTHROPIC_MAX_TOKENS Maximum tokens of Messages text response to prevent excessive costs. Tweak it regarding your needs. The more tokens used, the more API cost.NODE_VERSION This is not necessary for deploying in a local environment. This is necessary to tell a hosting service (like [Render.com](http://Render.comhttps://render.com)) which version should it use to deploy your web service. Check the proper section below to learn how to deploy with a hosting service.TELEGRAM_BOT_KEY and TELEGRAM_CHANNEL_ID These are completely optional. Use them if you want to send messages to your Telegram Bot.HMAC is a way to make sure messages sent between two places online stay secret and unchanged.
It's like sealing a letter in an envelope with a special wax seal, where the seal is made using a secret recipe.
Only the sender and the receiver know the recipe, so if the seal is intact when the receiver gets the letter, they can be sure it hasn't been opened or changed along the way.
In the WrapFast backend, we use HMAC to add this kind of security to messages or data we send and receive in our apps.
We use two keys that you have to generate with this included script secret_generator.js
Open a Terminal and type to generate a secret key:
node secret_generator.js
Set the two keys generated as AUTH_SECRET_KEY and HMAC_SECRET_KEY
You have to set the AUTH_SECRET_KEY also in the Xcode Project, within Constant.swift file:
enum Api {
// Auth key generated with the script 'secret_generator.js'
// It also needs to be configured in the backend side
static let authKey = "YOUR_GENERATED_AUTH_KEY"
}
In order to authenticate to the backend from the WrapFast iOS app:
GET request to /auth endpoint. We pass a X-Signature header, containing the path of the request, hashed with the authKey. You can find this in the Xcode Project at Endpoints.swift:"X-Signature": "\\(CryptoUtils.shared.createHmac(key: Const.Api.authKey, phrase: "/" + path))"
HMAC_SECRET_KEY that we safely store it in the device’s Keychain.chatgpt, vision, and dalle including a X-Signature header in the same way we did with auth endpoint:var header: [String : String]? {
switch self {
case .auth:
return [
"X-Signature": "\\(CryptoUtils.shared.createHmac(key: Const.Api.authKey, phrase: "/" + path))"
]
// To make requests to our backend endpoints, we fetch the auth secret key stored in the keychain and send it
// within a X-Signature header.
// We also send our app identifier to allow handle custom login within the backend depending on which app
// make the request.
case .vision, .chatgpt, .dalle:
let keychain = KeychainSwift()
let signature = CryptoUtils.shared.createHmac(key: keychain.get(Const.Keychain.tokenKey) ?? "", phrase: "/" + path)
return [
"X-Signature": "\\(signature)",
"X-App-Identifier": "\\(Const.Api.appIdentifier)"
]
}
}
<aside>
⚠️ In order to be able to make requests to GPT endpoints, you need to have fetched the HMAC_SECRET_KEY from /auth endpoint at least once from your app, and store it securely in the Keychain.
For instance, in the WrapFast boilerplate we do it within the init() of VisionVM, which is the first View that appears once the user has signed in:
**await** fetchBackendAuthIfNecessary()
</aside>
Once you have the Environment Variables properly set, you can deploy the backend locally in your Mac. Thus, you can develop your app and use the backend in debug. To do so:
cd wrapfast-backend
npm install
node wrapfast_backend.js
Your server will start running on http://localhost:10000/
Run WrapFast iOS app in a Simulator and try the built-in integration with DALL·E, Vision and ChatGPT
The server’s URL that the iOS app uses is set in the Constants.swif file, in the Api.baseURL parameter.
<aside>
⚠️ It is important that the URL you set as baseURL ends with a Slash /
</aside>
In DEBUG it is set to local host and in production you should set your production URL.