Extensions are one of the coolest new features in iOS8. Nearly every iOS developer (and user) has waited for this for a long time. Finally very [convenient scenarios](http://oleb.net/blog/2014/06/the-power-of-ios8/) come true. In fact [AgileBits](http://agilebits.com/) (creator of 1Password) has already [published](https://github.com/AgileBits/onepassword-app-extension) a class to integrate 1Password extension support into every App. This is really cool.

Now let's say we want to build a share extension for a social networking App. To post to the social network the user has to be logged in (usually this means the user needs a valid access token). We don't want to force the user to log into the network twice. We want to share the access token between the App and the extension. How can we do this?

One possibility is to use a shared user defaults. But in this case the access token would be stored unencrypted on the device. This is not a good idea.

What we need is to store the access token in the keychain of iOS and access this keychain from the App and the extension. Let's do exactly this. (The demo project is on [github](https://github.com/dasdom/KeychainDemo).)

> As far as I understand it, I'm not allowed to show screenshots from Xcode 6 and iOS8 because those are still under NDA. I will update this post with screenshots when the NDA is lifted.

Open Xcode6 and create a new project. Select the Single View Application template. Chose a name, select the language Swift and select iPhone as the target device.

We need to access the keychain in the App and in the extension. Therefore the code to do that needs to be accessible from both targets. This is the perfect use case for a framework.
In the project navigator select the project. Add a new target to the project and make it framework. Chose the name KeychainAccess. Let the 'Project' and the 'Embed in Application' as it is.

In the project navigator navigate to the folder KeychainAccess. Add a file to this folder. Select an iOS-Swift file and name it KeychainAccess.swift. Replace the content of the file with this:

import Foundation

public class DDHKeychain {
    
    private class func secClassGenericPassword() -> String {
        return NSString(format: kSecClassGenericPassword)
    }
    
    private class func secClass() -> String {
        return NSString(format: kSecClass)
    }
    
    private class func secAttrService() -> String {
        return NSString(format: kSecAttrService)
    }
    
    private class func secAttrAccount() -> String {
        return NSString(format: kSecAttrAccount)
    }
    
    private class func secValueData() -> String {
        return NSString(format: kSecValueData)
    }
    
    private class func secReturnData() -> String {
        return NSString(format: kSecReturnData)
    }

    
    public class func setPassword(password: String, account: String, service: String = "kDDHDefaultService") {
        var secret: NSData = password.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
        let objects: Array = [secClassGenericPassword(), service, account, secret]
        
        let keys: Array = [secClass(), secAttrService(), secAttrAccount(), secValueData()]
        
        let query = NSDictionary(objects: objects, forKeys: keys)
        
        SecItemDelete(query as CFDictionaryRef)
        
        let status = SecItemAdd(query as CFDictionaryRef, nil)
    }
    
    public class func passwordForAccount(account: String, service: String = "kDDHDefaultService") -> String {
        
        let queryAttributes = NSDictionary(objects: [secClassGenericPassword(), service, account, true], forKeys: [secClass(), secAttrService(), secAttrAccount(), secReturnData()])
        
        
        var dataTypeRef : Unmanaged<AnyObject>?
        let status = SecItemCopyMatching(queryAttributes, &dataTypeRef);
        
        let retrievedData : NSData = dataTypeRef!.takeRetainedValue() as NSData
        
        let password = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
        
        return password as String
    }
    
}

This is basic keychain access. Please don't use this in production code. This is just for demo purposes. (As a bare minimum this class needed some error handling. But for the demo this is just enough.)

To add an extension to the project, add another target. Make it a share extension and call it `LinkShare`. Again 'Project' should be your project and 'Embed in Application' should be your application. If Xcode asks you whether it should activate a "LinkShare" scheme, select Activate.

To share a keychain between the application and it's embedded extension both have to have keychain sharing activated.
Select your App target and open the 'Capabilities' tab. Activate Keychain Sharing. Now select the LinkShare target and activate Keychain Sharing as well. In the LinkShare target add a keychain group and give it the same identifier as the keychain group in the main target. Delete the other keychain group. Now both targets share the same keychain.

In the LinkShare target in the 'General' tab link against the KeychainAccess.framework.

Now open the 'Info' tab of the LinkShare target and navigate to
NSExtension > NSExtensionAttributes > NSExtensionActivationRule
. Change the NSExtensionActivationSupportsWebURLWithMaxCount to 1.

In this demo we want to type a "password" in the application and we want to read it in the extension. (In a real application we would log into an API and receive an access token. This would then be stored in the shared keychain and accessed from both, the application and the extension.)

Open the main storyboard of the application target and ad a textfield. Add constraints. Make the View Controller the delegate of the textfield. Replace the code in `ViewController.swift` with:

import UIKit
import KeychainAccess

class ViewController: UIViewController, UITextFieldDelegate {
    
    func textFieldShouldReturn(textField: UITextField!) -> Bool {
        KeychainAccess.setPassword(textField.text, account: "SharedAccount")
        textField.resignFirstResponder()
        return false
    }
    
}

In the folder of the share extension open the file `ShareViewController.swift`. Import the KeychainAccess module ( import KeychainAccess ) and add the function:

override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        
        let password = KeychainAccess.passwordForAccount("SharedAccount")
        textView.text = password
    }

Now, build and run with the application scheme. Enter a password in the textfield. Then open a website in Safari and select the share button. In the popup select more and activate the LinkShare extension. Select the LinkShare extension.

You should now see the password you have entered in the textfield of the application.

It's magic, isn't it?

**Update:** Updated for Xcode 6.1 and Swift 1.1.