Saturday, November 15, 2014

Devoxx 2014 in the eyes of a mobile developer

This year was my first Devoxx edition. On Sunday evening, going out of Antwerpen central station, I'm struck by all those sparkling shops on Keyserlei main road: diamonds all over the place!

As I’ll learn it later, Antwerpen is a well-known place for its diamond commerce.

Here is a summary of this Devoxx 2014 cru. As a disclaimer, I shall say that although I’ve been a Java guy for many years as a mobile developer, I very often do JavaScript and when going native, my platform of heart is not Android but iOS… As Ted said in his Swift for busy Java developer: I’m gonna tell you about Swift wearing my .NET T-shirt in a Java conference, it’s how it is nowadays…


With this in mind, I’d like to share with you my take-away sessions:

- “Using Traits, Mixins and Monads in JVM Languages”. What I like best about Venkat’s talks is how he goes from “what's the problem?” to the different solutions implemented in several languages (true polyglotism). And the problem starts with … diamond! (remember this old diamond issue in C++). Through live coding examples in Scala And Groovy we explore how to overcome the inheritance collidance with collaboration chaining behaviour like train wagons. Still on Monad, the very popular session “What Have the Monads Ever Done For Us?” (by Dick Wall) is the place where you learn you don’t need to know about Monads to use them. But to sound smart this winter, powder your tech chat with monoid, functor and monad off course (could be really handy as you talk about Swift actually).

- Swift made some buzz this year with 2 main sessions and being mentioned on several others: an university walk-through with interactive playground where Mike drives us through the intricacies of the language with playground samples. “Busy Java Developer's Guide to Apple's Swift” takes the same playground format with a very personalised style. Yes no cool CSS in playground but plenty of geek humour :) As I didn’t find any of those playground source code here is the link to one of mine.

- Develop your mobile app once in your favourite language and deploy it on iOS and Android. Still the Nirvana mantra for quick-win mobile development… If your language of choice is Java, see “Real cross-platform Java on mobile devices” session and how to use JavaFX to build your app on Android (LodgON) and iOS (RoboVM). UI is not yet native feel but it’s in the pipe for future as well as using Java8. If you’re a JavaScript ninja, go to “Use JavaScript to build Mobile Apps with Native UI” session to hear about Titanium. You have to learn a titanium specific API to build all your app including UI. but, UI get bridged into native widgets. As … stresses a lot no lowest common denominator, When you need to go platform specific use a if/else :))

- “Testing your Android app” to go through all testing layers from unit testing to instrumentation testing. Followed by “Espresso: What else?” makes me feel… jealous: so many testing frameworks for Android and soon Espresso part of development toolkit.

- Wednesday keynotes was done by Red Hat and our team work was show cased #ProudAeroGearDeveloper, let’s see it in picture:

and if you want to read more about it, see Markus’ blog.

- On security topic, I really enjoyed “Death to Cookies, Long Live JSON Web Tokens” from Auth0 team where you learn how to decode a json web token with utilities like jwt.io

- My favourite Java8 talk focuses on hidden gems rather than shining Stream and Lambdas. "50 new things we can do with Java 8": Let's ends this post with José Paumard final word: Diamonds are developer's best friends.

I couldn't agree more!

Corinne
PS: not to forgot the reason why I was there: my tools in action session OAuth2 for native apps ;)

Thursday, November 13, 2014

OAuth2 for Android and iOS with Keycloak

Like Jo, our brave iOS developer, you might have bumped into OAuth2 when writing an app that posts messages on Facebook wall. All cool social apps need to go through OAuth2 or OpenID authentication and authorization. Why?
Because so far it is the only broadly adopted open standard. So you might have heard : "It's complicated etc..". Not really if you use the right tools.

Mary, a cool mobile developer too, knows all about OAuth2. Follow Jo and Mary in their coffee break chat to learn in 5 mins OAuth2 howtos.

What's the problem?



- So Mary, to start with what is the problem we're trying to solve with OAuth?

- Easy. On one hand you have services… in the form of APIs. For example, we have twitter API to get list of followers, tweets etc… Those APIS handle your confidential data. As far as your data are protect by a login/password account, all is fine. But on the other hand, you have lots of apps that need to consume those services. The question is simple: do you trust them all to share your twitter login/password with them?

- I don't want my password all over the Internet!!!

- Therefore, use OAuth. OAuth2 allows users to grant third-party access to their web resources without sharing their passwords. We talk about a “delegated access" between mobile and user resources using a security token called an "access token".

Different actors and grants



- Mary, very often I hear about OAuth2 dance, who's involved? What is it?

- Actually there are 4 actors: authorization server (see our police man), responsible of authentication and authorization by providing an access token. The resource server, responsible for serving resources checking if there a valid token. The resource-owner, the end-user of the app, it could be you. And the client, in our case the mobile app.

- What is the dance all about?

- The interactions between those actors is described in OAuth2 spec as grant flows. This is the dance. There are different grant flows to fit different client app needs. A mobile app has diff needs that a single page browser-based app. In the spec, there are 4 different flows, you can group them in 2 different families:
3-legged flows where you grant permission from user. It includes "implicit grant" for browser based app not capable of keeping tokens secure and the "authorization code grant".
2-legged flows where the credentials are given to the app. In "resources owner credentials", this is the login/password whereas "client credential grant" takes client_id and client_secret.

- How do I know which one to use?

- It actually all boils down to two questions: "Is your client app capable of securely storing access tokens?" and "What is your trust relationship with the client app?" In your case, Jo, you should go for "authorization code grant".

Authorization Code Grant

step0: registration


- One of the pre-requisites you need to go through Jo, is to register your mobile app. For example, you go to Google cloud dev console, you create a project, fill in the form (add your redirect URI). And eventually you get a client_id and client/secret

step1: authz code




- With this client_id you’re all set to develop your OAuth2 app. Your Shoot'nShare app will send a request (including the client_id and the redirect_uri its scope) to the third-party service asking for an Authorization code. The app switches to external browser.

- Do you have to switch context?

- Actually, there are different approaches, you can also embed a web view in your app. It's better from a usability perspective. But from a security point of view it's seen as less secure, as your app sits between the login/password form and the provider.

- With external browser, it's actually the real Facebook login page?

- Exactly. The user logs in (if not already logged in), authz server shows a grant page to the end-user: Shoot’nShare would like to access yours contacts and photos Allow/Deny. If the user clicks on "Allow", the server redirects to the client using the redirect_uri (the one we talked during step0) and sends the Authorization Code to the mobile application.

step2: exchange for access token


- Now that we’ve got this temporary code we can go to the token endpoint to exchange it for a proper access token.

step3: get resources


- Using this token, our mobile app can access protected resources on server. Here you can do your upload!

How to implement OAuth2 on iOS?

- Mary, if I want to start coding the iOS version of Shoot'nShare just after our coffee, what are my options:

- You could use Social.famework from Apple, it will fit well for Facebook and a couple of other providers but it’s limited to those providers defined in settings. Here you actually provide your login/password but you trust your OS don’t you?

- ...

- You could use Facebook sdk but same here, limited to Facebook. If you want to share your photo to Google+, you need to use Google sdk and so on… - But Mary, there must be an open source library to help us…

- Yes! actually let me tell you more about AeroGear OAuth2 library... OAuth2 is one of the lib offers by AeroGear mobile suite. All client sdk are declined in iOS, Android, Windows(work in progress) for native paltforms. There is also a JavaScript sdk (and its Cordova plugins when needed). AeroGear is not only client SDKs, it also offers server bits like its UPS (UnifiedPush Server), if you want to send push notification to iOS/Android/Windows.



Want to see it in action?

- Let's see it in action, follow me in this screencast:


OAuth2 Server Side

- Mary, I try to foresee my product owner needs, what about if he wants an OAuth2 secured rest endpoint, server side? - No worries, I've got an answer for you and it's all Open Source: Keycloak

Shootn'Share demo

- Let's see it in action, follow me in this screencast:



Any feedback please drop us a line on AeroGear mailing list or contact Keycloak mailing list for more in-depth question on OAuth2/SSO server.

Happy OAuth2!

Thursday, October 16, 2014

AeroGear with Keycloak, OAuth2 friends for iOS apps... running with Swift

You might have bumped into OAuth2 when writing an app that posts messages on Facebook wall. All cool social apps need to go through OAuth2 or OpenID authentication and authorization. Why?
Because so far it is the only broadly adopted open standard. So you might have heard : "It's complicated etc..". Not really if you use the right tools.

Want to see it in action?



Shootn'Share demo

You want to take cool photos and share them with friends using GoogleDrive or Facebook account? With Shoot'nShare you can take pictures, browse your camera roll, pick a photo and share it! Photos get uploaded to your GoogleDrive or Facebook wall. You can also run this demo with its associated Keycloak backend and upload photo to your own social network :]

The purpose of this blog is not to show you how to take picture in iOS, so let's work on existing Shoot'nShare. Just clone it from github:


git clone https://github.com/aerogear/aerogear-ios-cookbook
cd aerogear-ios-cookbook
git checkout swift
open Shoot/Shoot.xcodeproj

Shoot'nShare project

In this initial project you will find aerogear-ios-oauth2 as a source dependency in Shoot/libs/AeroGearOAuth2 the library we will use for OAuth2 on iOS.

Google setup (optional)

NOTES: This step is optional if your want to try the GoogleDrive app out of the box. You can reuse the Shoot client id for 'GoogleDrive'. However if you want to create your own app, you will have to go through your provider setup instruction. Here's how to do it for Google Drive.

1. Have a Google account
2. Go to Google cloud console, create a new project
3. Go to APIs & auth menu, then select APIs and turn on Drive API
4. Always in APIs & auth menu, select Credentials and hit create new client id button Select iOS client and enter your bundle id.

NOTES: Enter a correct bundle id as it will be use in URL schema to specify the callback URL.

Once completed, you will have your client id!

Shoot'nShare redirect URI for Google

Open Info.plist of your project as source code to see XML format and define
 CFBundleURLTypes
 
  
   CFBundleURLSchemes
   
         org.aerogear.Shoot
   
  
 
This URL has to be unique (making it match your bundle id ensures unicity) and has to match OAuth2 server side configuration.


Google sharing

Let's start by implementing sharing with Google. In Shoot/shoot/ViewController.swift go to shareWithGoogleDrive:
    func shareWithGoogleDrive() {
        let googleConfig = GoogleConfig(
            clientId: "873670803862-g6pjsgt64gvp7r25edgf4154e8sld5nq.apps.googleusercontent.com",
            scopes:["https://www.googleapis.com/auth/drive"])
        
        let gdModule =  OAuth2Module(config: googleConfig)
        var http = Http()
        http.authzModule = gdModule
        
        gdModule.requestAccess { (response:AnyObject?, error:NSError?) -> Void in
            let filename = self.imageView.accessibilityIdentifier;
            let multiPartData = MultiPartData(data:UIImageJPEGRepresentation(self.imageView.image, 0.2),
                name: "image",
                filename: filename,
                mimeType: "image/jpg")
            http.POST("https://www.googleapis.com/upload/drive/v2/files", parameters: ["data": multiPartData], completionHandler: {(response, error) in
                if (error != nil) {
                    println("Error uploading file: \(error)")
                } else {
                    println("Successfully uploaded: " + response!.description)
                }
            })
        }
    }

In line 3 and 4, we use the client id (associated to Shoot Google app) and we specify the scope, here we share with google drive.

Line 6 and 7, we create an OAuth2 module. By default this module will create a TrustedSessionStorage to permanently store your tokens. Therefore every time your open your shoot app you can share photos without having to grant access everytime (see Notes below on iOS settings pre-requisites). You can choose a less secure MemorySessionStorage but each time you close your app and reopen it you will be prompted the first time to grant access.

Line 7 we initialize an http object and inject it the OAuth2 module.

In line 9, we actually request access. This method checks if the OAuth2Session (here stored in keychain) contains non-expired access token. If there is no token, it will go through the authorization code grant. If the token is expired (which happens every hour), a refreshed token will be asked transparently without any prompt.

NOTES: System requirement iOS8. Because this demo securely stores OAuth2 tokens in your iOS keychain, we've chosen to use WhenPasscodeSet policy for TrustedSessionStorage as a result to run this app you need to have your passcode set. For more details see WhenPasscodeSet blog post and Keychain and WhenPasscodeSet blog post.

Implicit http call

An even easier way to go, is to use aerogear-ios-http implicit grant. In the previous example we explicitly call requestAccess method. In Shoot/shoot/ViewController.swift change shareWithGoogleDrive by:
    func shareWithGoogleDrive() {
       let googleConfig = GoogleConfig(
           clientId: "873670803862-g6pjsgt64gvp7r25edgf4154e8sld5nq.apps.googleusercontent.com",
           scopes:["https://www.googleapis.com/auth/drive"])
        let gdModule = AccountManager.addGoogleAccount(googleConfig)
        self.http.authzModule = gdModule
        self.http.POST("https://www.googleapis.com/upload/drive/v2/files", parameters:  self.extractImageAsMultipartParams(), completionHandler: {(response, error) in
            if (error != nil) {
                self.presentAlert("Error", message: error!.localizedDescription)
            } else {
                self.presentAlert("Success", message: "Successfully uploaded!")
            }
        })
   }

In line 5, we use AccountManager to create an OAuth2 Module an factory method to create OAuth2 module.

In line 7, we just post our image to Google without having ask for access. POST method underneath checks if an OAuth2 module is plugged to http and will make the right call for you:
  • either start authz code grant
  • or refresh access code if needed
  • or simply run the POST if all tokens are already available

  • OAuth2 with Keycloak

    Ready to build your own social network app, let's use Keycloak and build OAuth2 protected service...

    First of all, you can download Keycloak all appliance distribution.

    Then, clone Shoot backend repo:


    git clone https://github.com/aerogear/aerogear-backend-cookbook
    cd aerogear-backend-cookbook/Shoot


    Following README instructions, import shoot-realm into Keycloak, your admin console should look like:



    NOTE: Here too the redirect URI matches our bundle id. For Keycloak, you can put whatever you want but as we have Google config using bundle ID, let's reuse :)

    Similar to the other providers, you can create your Keycloak OAuth2 module using AccountManager, simply use addAccount with the class type of your OAuth2 module, as shown below:
        func shareWithKeycloak() {
            println("Perform photo upload with Keycloak")
            
            var keycloakConfig = Config(base: "http://localhost:8080/auth",
                authzEndpoint: "realms/shoot-realm/tokens/login",
                redirectURL: "org.aerogear.Shoot://oauth2Callback",
                accessTokenEndpoint: "realms/shoot-realm/tokens/access/codes",
                clientId: "shoot-third-party",
                refreshTokenEndpoint: "realms/shoot-realm/tokens/refresh",
                revokeTokenEndpoint: "realms/shoot-realm/tokens/logout")
    
            let gdModule = AccountManager.addAccount(keycloakConfig, moduleClass: KeycloakOAuth2Module.self)
            self.http.authzModule = gdModule
            self.performUpload("http://localhost:8080/shoot/rest/photos", parameters: self.extractImageAsMultipartParams())
        }

    And that's it! Go and check uploaded pictures in shoot web-app:



    Any feedback please drop us a line on AeroGear mailing list or contact Keycloak mailing list for more in-depth question on OAuth2/SSO server.

    Happy OAuth2!

    Saturday, September 27, 2014

    Authenticate with TouchID



    Last blog, you saw how to store sensitive data in keychain and how to trigger touchID authentication when accessing them. In this post, you'll see how to use TouchID API for local authentication. No Keychain here.

    I've used this KeychainWrapper in a small app KeychainTouchIDTest hosted on github very much inspired by the one used on session 711 of WWDC 2014. but this one is written in Swift ;)

    Passcode Set

    TouchId is used in complement to passcode feature. If you want to use it you will need to have your passcode set in your iOS8 settings.

    LocalAuthentication and TouchID

    In your AppDelegate.swift class, define promptTouchId method:
        func promptTouchID() {
            var myContext = LAContext()
            var authError: NSError? = nil
            var myLocalizedReasonString:String = "Authenticate using your finger"
            if (myContext.canEvaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics, error:&authError)) {   // [1]
                
                myContext.evaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics,         // [2]
                    localizedReason: myLocalizedReasonString,                              // [3]
                    reply: {(success: Bool, error: NSError!)->() in
                        
                        if (success) {
                            println("User authenticated")
                        } else {
                            switch (error.code) {
                            case LAError.AuthenticationFailed.toRaw():
                                println("Authentication Failed")
                                
                            case LAError.UserCancel.toRaw():
                                println("User pressed Cancel button")
                                
                            case LAError.UserFallback.toRaw():                               // [4]
                                println("User pressed \"Enter Password\"")
                                
                            default:
                                
                                println("Touch ID is not configured")
                            }
                            
                        println("Authentication Fails");
                        let alert = UIAlertView(title: "Error", message: "Auth fails!", delegate: nil, cancelButtonTitle:"OK")
                        alert.show()
                    }
                })
            } else {
                println("Can not evaluate Touch ID");
                let alert = UIAlertView(title: "Error", message: "Your passcode should be set!", delegate: nil, cancelButtonTitle:"OK")
                alert.show()
            }
        }
    
    In [1], you first check wether passcode is set and touchId feature is available on this device.

    In [2], you call the authentication process. DeviceOwnerAuthenticationWithBiometrics is an enum which (for now) contains only one value. But future will open room for other means of authentication, let's keep an eye on WWDC next sessions.

    You can add an additional string in [3] which describes why you are doing this operation. You should always inform the user why he is prompted for Touch ID authentication.

    Allow a user fallback in [4]. Your user might want to authenticate by other means than finger recognition. You will have to implement your own password strategy, passcode fallback is not yet available on programmable API.

    To prompt at start-up, call promptTouchID method from application:didFinishLaunchingWithOptions: in AppDelegate:
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            promptTouchID()
            return true
        }
    
    I hope this serie of three posts: helped you get a view on what's new on TouchID and Keychain APIs on iOS8. Feel free to share your experience with it, I'd love to hear it.

    Happy iOS8!

    Sunday, September 14, 2014

    TouchID and Keychain, iOS8 best friends

    Last blog, we saw how to store sensitive data in iOS keychain and the different problems when switching from passcode on to passcode off set. Default access to keychain WhenUnlocked does not prevent access to keychain items when the device is not protected by passcode any more. In iOS8 with the new attribute kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, when trying to access keychain items, we end up with an error message if the device configuration set to passcode off. In this post, we'll go a step further in securing access to our sensitive data every times you access them. Welcome to TouchId.

    TouchID: What is it?

    It's a fingerprint recognition feature and is only available on the iPhone 5S and plus. Fingerprint data is stored on the secure enclave of the Apple A7 processor that is inside the device itself. To read more the existing and mysterious topic of secure enclave check apple security paper here.

    If the user's phone has been rebooted, or has not been unlocked for 48 hours, only the user's passcode, not a fingerprint, can be used to unlock the phone.

    Since iOS8, you can programatically use touchID APIs to:
  • either do local authentication,
  • or store in Keychain
  • Let's revisit our previous example hosted on github. We had the option to add an item in Keychain, update and read it. But we want to make sure every times the app reads the item the user is required to authenticate via touchID.

    Keychain Access with TouchID

    The existing ACL attributes on keychain:
  • kSecAttrAccessGroup: is used for WHAT are the apps which can access it. If you want the new keychain item to be shared among multiple applications, include the kSecAttrAccessGroup key
  • kSecAttrAccessible: expresses WHEN the user can access it. Among the different options: WhenUnlocked and the newbie WhenPascodeSet.
  • kSecAttrAccessControl: is for GRANTing. This is a new iOS8 attribute. It allows you to define a fine-grained access control. You use it with the method SecAccessControlCreateWithFlags. For now the enum contains only one value (but there will be room for more configuration) "UserPresence".
  • Let's code it, we're going to replace the generic createQuery by a more specific createQueryForAddItemWithTouchID for adding an item and createQueryForReadItemWithTouchID for retrieving it:
        func createQueryForAddItemWithTouchID(# key: String, value: String? = nil) -> NSMutableDictionary {
            var dataFromString: NSData? = value?.dataUsingEncoding(NSUTF8StringEncoding)
            var error:  Unmanaged?
            var sac: Unmanaged
            sac = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
                        kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, .UserPresence, &error)
            let retrievedData = Unmanaged.fromOpaque(sac.toOpaque()).takeUnretainedValue()
            
            var keychainQuery = NSMutableDictionary()
            keychainQuery[kSecClass] = kSecClassGenericPassword
            keychainQuery[kSecAttrService] = self.serviceIdentifier
            keychainQuery[kSecAttrAccount] = key
            keychainQuery[kSecAttrAccessControl] = retrievedData
            keychainQuery[kSecUseNoAuthenticationUI] = true
            if let unwrapped = dataFromString {
                keychainQuery[kSecValueData] = unwrapped
            }
            return keychainQuery
        }
    
    
    Line 4, we create an AccessControl object with the policy set to kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly. Note the flag item is set to the only possible UserPresence. we set the attribute kSecUseNoAuthenticationUI because we don't want to be prompted on Add.

    Read Keychain with TouchID popping up

    For the read, we only need to customize the pop-up window content with the attribute kSecUseOperationPrompt.
        func createQueryForReadItemWithTouchID(# key: String, value: String? = nil) -> NSMutableDictionary {
            var dataFromString: NSData? = value?.dataUsingEncoding(NSUTF8StringEncoding)
    
            
            var keychainQuery = NSMutableDictionary()
            keychainQuery[kSecClass] = kSecClassGenericPassword
            keychainQuery[kSecAttrService] = self.serviceIdentifier
            keychainQuery[kSecAttrAccount] = key
    
            keychainQuery[kSecUseOperationPrompt] = "Do you really want to access the item?"
            keychainQuery[kSecReturnData] = true
            
            return keychainQuery
        }
    
    Things to remember

    Accessibility and AccessControl work together. One key implication of using TouchID and Keychain is: the user has to authenticate using standard UI, therefore the app must be in foreground. Be aware that broad queries on Keychain may request items that need user auth. Last but not least, the keychains items stored using kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly are not synchronised or back-up on iCloud.

    That's all for today, next blog post we can see how to use TouchID for LocalAuthentication and how to fallback when touchID is not available. Stay tuned!

    Happy iOS8, Happy Swift!

    Friday, September 12, 2014

    New kids on the block: WhenPasscodeSet policy on iOS8

    ... oki, its real name, a bit less glamour, is kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly.

    TL;TR: What is it all about? A cool option which let you save sensitive data on Keychain only if the user's device configuration is set with passcode on. It's up to Keychain to deal with configuration changes (ie: user changes his phone's configuration from passcode on to passcode off) in a secure way.

    Keychain

    Keychain is a database, whose rows are called Keychain items. Keychain items have values, and those values are encrypted. You define keychain with attributes to later help you do queries. Typically Keychain is used to store passwords or encryption key, not large amount of data.

    Keychain exists in OS X version and iOS version. Those versions are quire different. Here we're going to focus on iOS.

    iOS Keychain

    In iOS, an application always has access to its own keychain items and does not have access to any other application’s items. The system generates its own password for the keychain (no prompt for password), and stores the key on the device in such a way that it is not accessible to any application.

    When a user backs up iPhone data, the keychain data is backed up but the secrets in the keychain remain encrypted in the backup. The keychain password is not included in the backup. Therefore, passwords and other secrets stored in the keychain on the iPhone cannot be used by someone who gains access to an iPhone backup.

    All keychain items are protected by user's passcode plus device secret (unique secret for each UID only known by the device itself). An encrypted iCloud backup is available in case of stolen device.

    Keychain wrapper

    Here is a simple KeychainWrapper, that let you save a key/value item, in Swift, of course :)
    public class KeychainWrap {
        public var serviceIdentifier: String
        
        public init() {
            if let bundle = NSBundle.mainBundle().bundleIdentifier {
                self.serviceIdentifier = bundle
            } else {
                self.serviceIdentifier = "unkown"
            }
        }
        
        func createQuery(# key: String, value: String? = nil) -> NSMutableDictionary {
            var dataFromString: NSData? = value?.dataUsingEncoding(NSUTF8StringEncoding)
            var keychainQuery = NSMutableDictionary()
            keychainQuery[kSecClass] = kSecClassGenericPassword
            keychainQuery[kSecAttrService] = self.serviceIdentifier
            keychainQuery[kSecAttrAccount] = key
            //keychainQuery[kSecAttrAccessible] = kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
            if let unwrapped = dataFromString {
                keychainQuery[kSecValueData] = unwrapped
            } else {
                keychainQuery[kSecReturnData] = true
            }
            return keychainQuery
        }
        
        public func addKey(key: String, value: String) -> Int {
            var statusAdd: OSStatus = SecItemAdd(createQuery(key: key, value: value), nil)
            return Int(statusAdd)
        }
        
        public func updateKey(key: String, value: String) -> Int {
            let attributesToUpdate = NSMutableDictionary()
            attributesToUpdate[kSecValueData] = value.dataUsingEncoding(NSUTF8StringEncoding)!
            var status: OSStatus = SecItemUpdate(createQuery(key: key, value: value), attributesToUpdate)
            return Int(status)
        }
        
        public func readKey(key: String) -> NSString? {
            
            var dataTypeRef: Unmanaged?
            let status: OSStatus = SecItemCopyMatching(createQuery(key: key), &dataTypeRef)
            
            var contentsOfKeychain: NSString?
            if (Int(status) != errSecSuccess) {
                contentsOfKeychain = "\(Int(status))"
                return contentsOfKeychain
            }
            
            let opaque = dataTypeRef?.toOpaque()
            if let op = opaque? {
                let retrievedData = Unmanaged.fromOpaque(op).takeUnretainedValue()
                // Convert the data retrieved from the keychain into a string
                contentsOfKeychain = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
            } else {
                println("Nothing was retrieved from the keychain. Status code \(status)")
            }
            
            return contentsOfKeychain
        }
    }
    
    Here we defined addKey, updateKey and readKey. I also provide a resetAll method (not shown in code snippet but use source code for reference). As line 18 is commented out, we're on kSecAttrAccessibleWhenUnlocked accessibility mode, the one per default.

    I've used this KeychainWrapper in a small app KeychainTouchIDTest hosted on github very much inspired by the one used on session 711 of WWDC 2014. Now it's time to play with it and see how it behaves...

    Let's play On/Off game

    WhenUnlocked policy for keychain (with line 18 commented)
    • in Settings -> TouchID & Passcode, choose "Turn passcode on"
    • start KeychainTouchIDTest
    • click Add item, should return success
    • click Query item, should return success
    • in Settings -> TouchID & Passcode, choose "Turn passcode off"
    • switch to KeychainTouchIDTest
    • click Add item, should return success
    • click Query item, should return success
    Here you touch the problem, you initially saved your credit car number in a very secure place (keychain), your phone being secured with passcode but as you remove authentication (passcode off) from you phone configuration, what happens?

    You left the door wide open. Anyone can take you phone and use your credit card! Let's carry on doing some more testing to see how WhenPasswordSet behaves...

    WhenPasscodeSet policy for keychain (with line 18 uncommented)
    • in Settings -> TouchID & Passcode, choose "Turn passcode on"
    • switch to KeychainTouchIDTest
    • click reset all
    • click Add item, should return success
    • click Query item, should return success
    • in Settings -> TouchID & Passcode, choose "Turn passcode off"
    • click Query item, should return not found error
    • click Add item, should return error
    Much more secure.
    Since you changed your passcode configuration to off, Keychain has securely removed the sensitive data. Switching it back to passcode on will not restore them. They're gone for good.

    One step further: TouchID

    Suppose you want to authenticate every times this sensitive data is accessed. Let's say it's a credit card information and you want to approve all transaction personally. In iOS8 it's possible using WhenPasscodeSet's little friend API: TouchID!

    I won't spoil the pleasure after a too long blog, this will be for a second post. Stay tuned!

    Sunday, September 7, 2014

    Meet my new friend: Charles

    Last week, while coding/debugging some https code on iPhone, I was looking for a tool to simply display the request/response and http headers running on mac.

    I met Charles. Charles is an HTTP proxy that let you view all of the HTTP and SSL / HTTPS traffic between their machine (or phone) and the Internet. Here is a sample doc on how to configure it to view requests sent from your device.

    http proxy set up

    To set up Charles as a proxy for spying http traffic on your iPhone





    • Go to Settings -> Wifi, on your wifi name select info
    • Enter your IP + port 8888
    • Open Charles on you mac





    Note: Once you finished your work and you closed Charles app, remember to switch off the proxy settings otherwise your internet connection won't work.

    SSL setup

    To use Charles with SSL, simply:
    • Get a certificate for your phone: open a browser go to http://www.charlesproxy.com/charles.crt
    • Install it, you will be prompted to enter your passcode
    • On your mac, go to Charles menu: Proxy ->Proxy settings… -> SSL tab and the https address (for ex: account.google.com:443) or a generic wild character
    You're ready to fire, and you can browser your call:



    Charles you're a great friend though not an open source dude, you have a license fee. If you're looking on open source side you have Wireshark option, but on mac it means installing X11 separately and a bit more work to configure SSL.