Using Property Lists for API Keys in Swift Applications

Categories:

Xcode 7.3 Swift 2.2

You’ve written an open source application for demonstration or illustrative purposes, and your application requires REST API keys for services such as Facebook, Twitter, Wunderground, or Parse or… You get the idea. How do you submit your application to Github for others to use without exposing your own API keys? I can’t take credit for the original idea, but here’s a Swift take on technique described by Mike Lazer-Walker.

We’ll be using iOS property list files and a Swift wrapper. The highlights here are that we are not checking our property list into source control (Git), but our project will reference a file called ApiKeys.plist. If you download the project from Bitbucket and try to run you’ll get an error because the file ApiKeys.plist is missing. This is where you create your own ApiKeys.plist and put in your own API keys.

Note: This technique we are using here is specific to git. If you are using a different revision control system look up the feature for how to ignore certain files in your source tree (for example, in Subversion you would use the svn:ignore property).

The general technique is to add a .gitignore file to the root directory of our project and add the following line:

ApiKeys.plist

and then, to create a ApiKeys.plist local to your machine with something similar to the following content:

[code]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_CLIENT_ID</key>
<string>MyAPIClientID</string>
<key>API_SECRET</key>
<string>MyAPISecret</string>
</dict>
</plist>
[/code]

Once we have that we need a clean mechanism for obtaining the values for our keys. This is done through a utility file in Swift (we call it ApiKeys.swift for simplicity) with the contents:

The code is straightforward and meant to be called like this:

The routine looks for the ApiKeys.plist file in the application’s resource bundle, loads it as an NSDictionary and then looks up the value for the given key as a String.

It should be pointed out that what this code does not do is in any way obfuscate the contents of the plist. That is, your iOS binary will have the keys included in the resource bundle and could be extracted by someone intent on getting at them.

Now, let’s look at the specifics on how to use this technique in your Swift projects.

Step 1. Add ApiKeys.plist to your .gitignore file

This is important; failure to do so will cause Xcode to try to automatically add your plist file to revision control. We don’t want that.

Step 2. Create ApiKeys.plist

You can either create ApiKeys.plist by hand or use Xcode to create it. Just make sure that you’ve added ApiKeys.plist to your .gitignore file!

To create ApiKeys.plist use File – New – File in Xcode and create a Resource file of type Property List. Select Next and name the file ApiKeys (the plist file type will be created automatically). If you name it something other than what you put in your .gitignore, it will get added to revision control, which is not what you want..

createPropertyList

Also ensure that the file is included in your application target.

addApiKeysFile

Now add the API keys you need for your application to your ApiKeys.plist file. Select the ApiKeys.plist file in Xcode and click on the Root dictionary line, then right-click and choose Add Row. Double-click on the text that says New item and rename it to API_CLIENT_ID. Double-click on the Value column and type in your actual string. For our purposes I’ve just put MyAPIClientID.

SetAPICLIENTID

Step 3. Create ApiKeys.swift

We want a simple wrapper for obtaining our keys, so create a new file called ApiKeys.swift and in it place the following:

Step 4. Use the valueForAPIKey Routine

And that’s it! Once you have your clientID you can add it to whatever REST calls you need to (or if you are dealing with an annoying API add it as a special HTTP X- header).

Now, I will confess, it is unclear why there isn’t a more elegant way to do this in Xcode. Although this technique is serviceable it isn’t very DRY (don’t-repeat-yourself), but then again, how many times have started a new project only to repeat the same “bootstrap” steps such as adding AFNetworking, CocoaLumberjack, and all of the other popular frameworks? What would be handy is the ability for Xcode to obtain API keys and other confidential information from an application like Keychain and compile them in a secure manner. Que serĂ¡, serĂ¡ I suppose.

5 thoughts on “Using Property Lists for API Keys in Swift Applications”

  1. Great job but… With this you can only return Strings from .plist. So I made a little bit different function so you can return any value from .plist. This is the code:

  2. Even if this method will hide the API key in a git repository, how secure is this method in the app binary? I guess it’s not the securest method to store an API key in an app.

Leave a Reply

Your email address will not be published. Required fields are marked *