NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

What's the right way to compile in app secrets?

Forums > macOS

So, I'm writing a Twitter client. The Twitter API wants me to have an app key and an app secret, so that Twitter can keep track of how badly my app is behaving versus others. These tokens need to be compiled in to the application, so they should be part of the source code somehow. However, I'd like to keep these out of the code repository, so that if I release the source code there aren't a zillion clones with code I know nothing about but which are still using my app credentials to access the API.

With other languages and other build environments, I've seen many different ways of solving this class of problem. A code generation build step, which reads the secrets out of an environment variable or a key store is one solution. Another is to inject the tokens directly during compilation, using pragmas, environment variables, and compiler flags (essentially rolling the code generation into the compilation step). Or even just putting the secret(s) in a file by themselves and not checking that file in to source control.

What is the Xcode + Swift way of solving this problem?

1      

Also interested in this answer, in my current app that's in testing I have stored it in the Info.plist, accessed via

Bundle.main.object(forInfoDictionaryKey: "YourKey")

and not checking the Info.plist in, but that's not really a solution for a production app I don't think.

I was thinking of maybe having the app call an API on first launch and storing the key from their in UserDefaults

edit: just realised this is macOS forum, not even sure that's available in a macOS app..

1      

I put this question in the macOS forum just because that's the app I'm working on, but the Bundle API applies across all the platforms. I'm currently thinking that you're on the right track, and based on this (old) Stack Overflow discussion I think the way to go is to put the secrets in their own file that is not checked in. So, instead of Info.plist, put the data in AppSecrets.plist and read it from there.

1      

This approach would get round the repository issue but the file would still be in the packaged app, so especially on macOS just a right click and show package contents and your file and subsequently the API key/secret is exposed.

The API I am using costs money per request, so I don't think I will risk it.

1      

Hmm. Yeah, that's a point I hadn't thought of. So the flow of behavior has to go something like this:

  1. app starting up
  2. connect to some repository of secret knowledge, proving that the app is the app and not a bad guy
  3. request the secret knowledge

In my enterprise development days, that repository of secret knowledge was a separate application running on the same hardware and compiled and installed by one of the few people trusted with the knowledge.

In your case, a phone app, you might create a web service that requires some public/private key and where the transport is wrapped through SSL. That sounds complicated, but it's really not that bad so long as your source isn't available -- you can compile the key in and if someone packet-sniffs the transaction all they'll get is enciphered bits. I've been looking at CryptoKit and Apple has made it way more understandable than the bouncycastle APIs I had to deal with in Java.

For a desktop app, I'm going to have to think about this for a bit.

2      

You should be aware that on a desktop app anyone with a hex editor and a bit of skill will be able to capture the key even if the app only briefly knows what the key is.

If someone getting the API would be bad for you then you may be better off writing a service that has some sort of authentication that would act as an intermediary between the app and the API.

1      

For critical API keys (like banking ones and similar) -> Never store them in your app / frontend whether it is encrypted or not !!

The workaround is to store your API keys in a private server which will do the role of a proxy between your app and the API. Your app will call your private server, the private server will use your key to make the API calls, receive the data and send the data to your app.

This is pretty cumbersome I agree, but way safer than putting you api keys directly in your app. I hope Apple can provite a simple way to do that directly with Cloudkit but I havent seen anything yet...

However, if you have non critical API keys (like a free Twitter key), you dont really need to use the proxy server method, you can put it in your app because if it got stolen, they wont be able to do any thing harmful or steal your ID / money

Hope this can help you

2      

Hacking with Swift is sponsored by MadMachine

SPONSORED Want to try Swift on microcontrollers? MadMachine provides ways to interact with the physical world in a Swift way. Join us and have fun!

Get it now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.