Add network credentials to the keychain on behalf of the user.
Use keychain services to enable simple, secure storage for users’ passwords. In this way you avoid repeatedly asking the user for a password, and you don’t have to implement your own encryption, which can be error prone.
Get Set Up
To get started, define a structure to hold the credentials as they move around your app in memory:
Next, define an error enumeration that you can use to communicate keychain access outcomes:
Then, identify the server that your app is working with:
Create an Add Query
Using an instance of the credentials structure and the server constant, you can create an add query:
The query dictionary’s first key-value pair indicates that the item is an Internet password, from which keychain services infers that the data is secret and requires encryption. This also ensures that the item has attributes that distinguish it from other Internet passwords, such as the server and account to which it applies. Indeed, the next two key-value pairs in the query provide this information, attaching the user name acquired from the user as the account, along with a domain name appropriate to this password as the server.
Although not necessary in this case, you could further characterize the password by specifying additional attributes, such as the port number or the network protocol. For example, if you needed to store distinct FTP and HTTP credentials for the same user working on the same server, you could add the
k attribute to distinguish between them.
Finally, the query contains the password from the user, encoded as a
Add the Item
With the query complete, you simply feed it to the
Although you typically ignore the return data supplied by reference in the second argument on an add operation (as demonstrated here), always check the function’s return status to ensure that the operation succeeds. The operation might fail, for example, if an item with the given attributes already exists.
To be able to find the item later, you’re going to use your knowledge of its attributes. In this example, the server and the account are the item’s distinguishing characteristics. For constant attributes (here, the server), use the same value during lookup. In contrast, the account attribute is dynamic, because it holds a value provided by the user at runtime. As long as your app never adds similar items with varying attributes (such as passwords for different accounts on the same server), you can omit these dynamic attributes as search parameters and instead retrieve them along with the item. As a result, when you look up the password, you also get the corresponding username.
If your app does add items with varying dynamic attributes, you’ll need a way to choose among them during retrieval. One option is to record information about the items in another way. For example, if you keep records of users in a Core Data model, you store the username there after using keychain services to store the password field. Later, you use the user name pulled from your data model to condition the search for the password.
In other cases, it may make sense to further characterize the item by adding more attributes. For example, you might include the
k attribute in the original add query, providing a string that marks the item for the particular purpose. Then you’ll be able to use this attribute to narrow your search later.