Monday, January 27, 2014

Back from MarsJUG hackengarten#2

Last Saturday in Marseille, I participated in MarsJUG hackengarten#2. A bunch of known faces from my previous visit of the first edition of MArsJUG hackengarten (Hey, it looks like I'm part of the usual participants). Thanks to Julien and Benjamin for organizing the event and making such a nice place to be.

The day started with a short introduction of the proposed open source projects. Very different subjects: CRaSH, DataFari, CodevTT, RHQ, Audela and AeroGear. Having presented AeroGear last Wednesday with my fellow Sebastien Blanc (you can find slides here), I gave a very short introduction and presented the list of possible contributions from hackengarten wiki page.

Quick lunch (with Quick food) and back to work. Several teams formed: Nico and Thomas want to use AeroGear Push for RHQ Alert mobile app, trying out Cordova Push plugin. And making a double contribution to AeroGear and RHQ projects. Sylvain is brave enough to upgrade to XCode 5 and delve in iOS code with OAuth2 and Facebook. There's even a JIRA code for this one. Xavier tried simple push quickstart and even submitted his first PR. Time is always too short, but we can carry on those ideas. Mailing list is our friend.

I'm always impressed with all the ideas that come up during a hack-together day, but the best is the enthusiasm that you can feel. The reward of course is the Pull Request being accepted. Keep in touch and let's work for the holy graal: the Pull Request.



Sunday, January 19, 2014

Secure your runtime #Groovy #Hackengarten

Hackengarten is over, we had such a great time!

Thank you all for coming and making this event so special (after a long week of work). Special thanks to Nicolas Berge (@LesSatellites) for giving us a roof (useful by this rainy day). And for @CedricChampeau (who left Bretagne to see the sun) and @fabricematrat for organising and driving the event.

Wanna see in how it went? Here the twitter story:
Early start with french croissants. Sebi didn't forget them:
Meeting time, Cedric talk about AST, giving tricks how to work with the beast. How to read the GroovyConsole and some very useful debug tips. (Cedric talking with hands like a real South of France guy). Fabrice took over delving in SecureRuntimeASTCustomizer. Code is showing up!

We warm up with some coding using GroovyConsole and making test passed. One by one, step by step.
Geek lunch with ...

Pizza and beers, of course! (Greasy hands couldn't tweet that one)
Back to work in the afternoon, people working in pair, talking, coding, designing, talking again, merging... Hard work, man. And to finish, what did we produce: What our French Riviera community said about it: What's next?
Still some failing tests to go over before sending the Pull Request. The core design is here, you're welcome to hack more tests making them passed. Same approach as we did. Pick an item in wiki page, fix it commit on secureruntime branch. Once all use cases are treated will come the time to refactor (lots of ideas showed up).
Other related blog:
Fabrice talks about it too

Sunday, January 12, 2014

RivieraGUG - Groovy hackengarten

Remember the RivieraGUG coding WE back in the old days?
That was fun. A whole WE of live coding and snoring;)
Just browse our etherpad log to get the idea.

We decided to get back together for some hacking. The event will be hosted at Les Satellites, Saturday 18th January (note that les Satellites has moved - still in Nice). And this time we have Cedric Champeau (core committer on Groovy) with us!

What are we going to do?
Nothing less than contributing to Groovy language! We'd like to work on SecureASTCustomizer to secure your Groovy scripts not only at compile time but at runtime too. Be prepared to code some AST transform... Get all the details in our announcement page.

Brainstorming is ongoing, check out the forked repo groovy-core with secureruntime branch. This is a proposal, nothing written in marble. Feel free to add new ideas on Groovy-Secure hackengarten wiki page, try the code snippets, comment on it or simply add your contribution. The more we have, the more we can discuss and make progress during our hackengarten. Come and join us, this is an wonderful opportunity to contribute to an open source project.

OSS needs you!!
And remember we have a goal: make a pull request by the end of Saturday!



Wednesday, January 8, 2014

OAuth2 discussion - part2

We talked about OAuth2 protocol in part 1, let's see it in action in this second part. We'll take a demo app from aerogear-ios-cookbook and I'm going to drive you through it step by step.

GroogleDrive app displays the list of documents in your Google Drive using OAuth2 to authorize with aerogear-ios library.

Let's do Google setup

Before we start you will need to register your app, follow the steps below:
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. Enter a correct bundle id as it will be use in URL schema (if you don't know about URL Schemas I suggest you read about it) to specify the callback URL.

Once completed you will have your information displayed as below:



You'll get a Client Id, a Client Secret and a callback URL, open Xcode (or AppCode whathever you like best), go to GoogleDrive-Info.plist and add an new URL schema entry as shown below:



Show me the code

In AGViewController.m:

- (IBAction)authorize:(UIButton *)sender {
    AGAuthorizer* authorizer = [AGAuthorizer authorizer];

    _restAuthzModule = [authorizer authz:^(id config) {              [1]
        config.name = @"restAuthMod";
        config.baseURL = [[NSURL alloc] initWithString:@"https://accounts.google.com"];
        config.authzEndpoint = @"/o/oauth2/auth";
        config.accessTokenEndpoint = @"/o/oauth2/token";
        config.clientId = @"XXXXX";
        config.redirectURL = @"org.aerogear.GoogleDrive:/oauth2Callback";
        config.scopes = @[@"https://www.googleapis.com/auth/drive"];
    }];

    [_restAuthzModule requestAccessSuccess:^(id object) {                           [2]
        [self fetchGoogleDriveDocuments:_restAuthzModule];                          [4]
    } failure:^(NSError *error) {
    }];
}
[1]: configuration with all required URLs and endpoints.
[2]: requestAccessSuccess:failure: is the method dealing with all the steps needed to authorize. Within this method, we're going to bring the UI grant web page, once authorization is granted, we go back to the mobile app and then we exchange code for access token. this is the heart of OAuth2 dance ;)

In AGAppDelegate.m:

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{                                                                                   [3]
    NSNotification *notification = [NSNotification notificationWithName:@"AGAppLaunchedWithURLNotification" 
    object:nil userInfo:[NSDictionary dictionaryWithObject:url forKey:@"UIApplicationLaunchOptionsURLKey"]];
    [[NSNotificationCenter defaultCenter] postNotification:notification];

    return YES;
}
[3]: once popup has been answered, go back to GoogleDrive app and notified AeroGear framework. If this method is not well implemented, the browser won't be able to callback the application. Back to the app, access code is excahnge with access token (step 2).
[4]: the success callback takes the access token as parameter. The access token is stored in memory with AGAuthzModule. It's up to the developer to store permanently the access token for next app launch. Note that access token has an expiration date (1h for Google).

In AGViewController.m:

-(void)fetchGoogleDriveDocuments:(id) authzModule {
    NSString* readGoogleDriveURL = @"https://www.googleapis.com/drive/v2";
    NSURL* serverURL = [NSURL URLWithString:readGoogleDriveURL];
    AGPipeline* googleDocuments = [AGPipeline pipelineWithBaseURL:serverURL];

    id documents = [googleDocuments pipe:^(id config) {       [5]
        [config setName:@"files"];
        [config setAuthzModule:authzModule];                                        [6]
    }];

    [documents read:^(id responseObject) {                                          [7]
        _documents = [[self buildDocumentList:responseObject[0]] copy];
        [self.tableView reloadData];
    } failure:^(NSError *error) {
        // when an error occurs... at least log it to the console..
        NSLog(@"Read: An error occured! \n%@", error);
    }];
}
[5]: create your Pipeline and Pipe objects as usual.
[6]: setting authz module in your pipe configuration will pass the access token for each pipe operations transparently.
[7]: read the pipe as usual.

As a conclusion

No need to learn and use different providers SDK, Aerogear-iOS library allows you to use OAuth2 with any providers. Once you're authorized, you can use the pipes transparently (no need for you to pass the access token, the framework does it for you).
OAuth2 will be shipped in 1.4.0. Give it a trial, give us your feedback and enjoy!

Monday, January 6, 2014

OAuth2 discussion - part1

Sometimes pronounced with one syllable "oath", but I like it better with two syllables "Oh Auth", add a 2 at the end and here is OAuth2, an open standard for authorization. It allows users to share their private resources (e.g. photos, documents etc...) stored on one site with another site or application without having to hand out their credentials. Widely adopted from Google to Facebook, easy and less cumbersome than his elder brother OAuth1, let's see together how to practice the OAuth2 dance.

Actually, the dance comparison is often used to describe OAuth2, but I think it's more a 3 players discussion so we're going to use a script metaphor. Here is our casting: Mr Google (our cloud based service provider), MyGoogleDrive app (our native mobile app which main functionality is to list Google Drive files) and Bob our end user who want to access his Google drive content via MyGoogleDrive app. We want to write a native iOS client app using third party backend.

Before we start, MyGoogleDrive developer has already registered his app to consume Google Drive services.  Each provider offers an admin console: GoogleCloud console... Depending on provider, you can choose want kind of access you need (read/write). Once registered you should get a client id, a client secret and a callback URI.

Bob starts MyGoogleDrive app on his iPhone.

1. Hello, Mr Google I'm GoogleDrive app, could I get access to Google Drive services? Here is my client id and the URL you can call me back on.
2. Which account, please identify yourself?
3. I am Bob, here's my login and password
4. Hello, Bob, do you want to grant access to GoogleDrive app?
5. Yes I do. I trust this app.
6. Ok fine, Let me use the client callback URL to get back to the app. Here is an access code for you GoogleDrive.
7. Thanks. Mr Google may I exchange my code for an access token?
8. Here's your access token GoogleDrive Enjoy.
9. So Mr Google could I get access to Bob's list of files, here's my access token.
10. Let me see if your access token is still valid, ok fine here's the list your requested.

Easy peasy.
One of the reasons of OAuth2 (apart from the cryptographic signatures vs SSL/TLS protection) is the need to serve not only web app but also, mobile app. OAuth2 defines 3 type of profiles: web application (end user has no access to credentials, access tokens), web browser client (OAuth credential not trusted, some provider won't issue a client_secret) and native application (dynamically issued credentials such as access tokens or refresh tokens can receive an acceptable level of protection).

For native app one of the main challenge is somehow to include a third party UI to grant access either by forwarding your app to a web browser or by embedding a WebView and, once successfully authenticated and authorized, to go back to the original app. With minimal provider configuration, AeroGear libraries handles it for you.

In the second part of this blog, we'll see how using AeroGear iOS libraries, we managed the OAuth2 back and forth discussion easily and how the OAuth2 implementation integrates transparently with Pipes.

Monday, November 25, 2013

Keep it secret!

With the latest release, AeroGear iOS 1.3.0 comes with more enhanced security features. Latest adding is encryption. In this release we deal with symmetric encryption.

Symmetric encryption: what is it?


Sometime talking about security topics might seem a bit overwhelming. But no worries, let's get the right vocabulary. When talking about encryption, there are actually two basic techniques for encrypting information: symmetric encryption (also called secret key encryption) and asymmetric encryption (also called public key encryption).

Today, we're going to delve into symmetric encryption as asymmetric one will be included in next AeroGear release. As said, symmetric encryption is when the same key is used to encrypt and decrypt data. Again, let's get the right jargon. Private key encryption is best defined with the following concepts:
  • Encryption key is a block of bytes of a _specific length_. Key can be derived from password using for example, PBKDF2 algorithm. Key must be kept secret.
  • IV (Initialisation Vector) is a random value that is used to encrypt data. Encryption algorithms usually work on fixed-size blocks, IV defines the first encrypted block.
You can derive the encryption key using a password or phassphrase and salt with AGPBKDF2.
  • Password is easy to remember and usually defined by user and must be kept secret. A password is not a key.
  • Salt is a random value that is used together with a password to derive an encryption key. A salt value does not need to be kept secret.
AeroGear-Crypto symmetric encryption provides you an easy way to encrypt your sensitive data. No need to be a security expert to use the library. See by yourself.

An example please: Xmas


Christmas is coming, it's all around us. Papillotes (french Christmas chocolate) and clementine is in the air. Surrounded by nephews and friends, it's time to organize your Santa Claus list. But you don't want your secret list to leak. Here comes into the scene your aerogear-crypto libraries.

In Xmas, we want to achieve local encryption of the present description but keep information like to whom the present is for, clear and searchable. The flow is simple you add a present to the list with an associated password and you saved it. It is first encrypted and then locally saved.

The list of present is displayed with a generic picture. If you want to remember what the item is. just click on it entered the password used for encryption, and the card will be flipped to show you the content description in clear.



Show me the code


Derive Key


First of all, to encrypt your data you need an encryption key. Your key can be derived from your password using PBKDF2 algorithms.
 -(NSData*) getKeyFromPassword:(NSString*)password {
     AGPBKDF2* derivator = [[AGPBKDF2 alloc] init];
     
     return [derivator deriveKey:password salt:_salt];
 }
To derive you key from your password you need to introduce some randomness (remember we talked about salt). For random generation of salt or IV, use AGRandomGenerator. By default, AGRandomGenerator generates 16 bytes key, but you can also specify the length if you wish.
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
    _salt = [defaults objectForKey:@"xmas.salt"];
    
    if(!_salt) { // if first launch, initialize params for subsequent reads
        _salt = [AGRandomGenerator randomBytes];
        [defaults setObject:_salt forKey:@"xmas.salt"];
        [defaults synchronize];
    }

You need to store your salt to be able to regenerate the exact same key when you want to decrypt this description information. In this example, we've chosen to store this information in NSUserDefaults.

Encrypt


Once you've got your encryption key, use AGCryptoBox to do the actual encryption. With AGCryptoBox, you can encrypt/decrypt data using your encryption key and a randomly generated IV as shown below:
 -(void) saveAndEncryptData:(id)gift withPassword:password {
     // Generate key from password
     NSData* key = [self getKeyFromPassword:password];
     
     // Use CryptoBox to encrypt/decrypt data
     AGCryptoBox* cryptoBox = [[AGCryptoBox alloc] initWithKey:key];
     
     // transform string to data
     NSData* dataToEncrypt = [gift[@"description"] dataUsingEncoding:NSUTF8StringEncoding];
     
     // encrypt data
     gift[@"description"] = [cryptoBox encrypt:dataToEncrypt IV:_IV];
     
     // Store data with encrypted description
     [_store save:gift error:nil];
     
     [self.gifts addObject:gift];
 }
Same as for the salt, IV need to be store to be able to decrypt the encrypted data. We'll put it into NSUserDefaults too.

Decrypt


To be able to decrypt, fetch salt, prompt the user for password, regenerate the encryption key. Fetch IV data and decrypt!
 -(NSString*)decrypt:(NSData*)data {
     NSData* key = [self getKeyFromPassword:_password];
     AGCryptoBox* cryptoBox = [[AGCryptoBox alloc] initWithKey:key];

     return [[NSString alloc]
             initWithData:[cryptoBox decrypt:data IV:_IV] encoding:NSUTF8StringEncoding];
 }

That's all folks!
If you want to see it all in action, git clone cookbook, go to xmas app and pod install it :)

Saturday, November 23, 2013

Storyboard and unwind segue

With iOS 5, storyboards made their entrance, with iOS6 they went popular and with iOS7, there're well settled. I've sparely used storyboard in the past and when a friend of mine told me about unwind segue, I thought it was time to revisit it. Here's my story:

A bit of history


First there was Interface Builder


Interface Builder (IB) allows you to work on a graphical interface to define you app layout and components. Customising a table view cell through IB saves you tone of UI code that clutters your app.

Does IB generate code behind the scene? Not quite, it's not really code that is generated when you use storyboards or nibs. The views are encoded into a binary file (using NSCoder) and decoded at runtime. Think of it as the objects being created and frozen in Interface Builder, then defrosted during runtime.

Then came Storyboard


Storyboard goes one step further...

As the name said it all, it's about putting the story of your app on a board. With IB you can work with one view, with storyboard you can have multiple views on a same board. It introduces segues. Segues represent transitions between screens. Opening a storyboard and your have pretty good idea of the UI flow at a glance. In XCode 5, application templates scaffold storyboard by default (no check box to ask you). So when I switch to iOS7, I thought it was time to give storyboards another trial and I had a perfect use case for that.

On the AeroGear project, we have a great Android Cookbook where you demo the features of the libraries without being cluttered by too much UI code. I thought having a version for iOS will be wonderful.

Storyboard and its segue


So I settled on writing one and I thought it was a great use case for using storyboard. I was new to it, I already tried and actually blog about it here. Coding with storyboard I've discovered unwind segue and I love it. You can replace delegate with unwind segues. Making even less to write.

Let's see it with an example


Taken from iOS cookbook, Xmas is a short example where we have 2 view controllers: "Gifts list" controller (let's name it VC1) and "Add present" controller (VC2) as shown in XCode storyboard.



We are going to create a segue from scene one (list controller) to scene two (add present), implementing prepareForSegue:sender: in VC1.

Going from VC1 to VC2


In storyboard with the magic keys combinaison ctrl+drag from VC1 to VC2, choose the push segue. In the code implement prepareForSegue:sender: to move data from VC1 to VC2:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
 if ([segue.identifier isEqualToString:@"addPresent:"]) {
        // nothing to do
 }
    if ([segue.identifier isEqualToString:@"updatePresent:"]) {
        // pass selected gift from VC1 to VC2
        AGAddPresentViewController* destinationController = segue.destinationViewController;
        destinationController.toWhomTextField.text = [_store read:_currentGiftId];
 }
}
But what about transitioning and sending context back in the other direction? with iOS 6, we have a new technique named unwind segues...

Going back: VC2 to VC1


Now you add a new present and you want to be able to hist save and go back to the list controller. Prior to iOS6, going back was implemented using well known Delegate approach. With iOS6, we can do it with unwind segue. In you VC1 controller (the controller you want to unwind to), you have implement an IBAction method with one parameter segue, called it whatever you want. Then, from the story board ctrl+drag from ViewController to its exit icon. Xcode gives you a list of possible unwind methods (here we have implemented only one), choose it and you're done!
-(IBAction)unwindToRootVC:(UIStoryboardSegue *)segue {
    AGAddPresentViewController* source = segue.sourceViewController;
    
    // Get data from source
    NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
    dict[@"toWhom"] = source.toWhomTextField.text;
    dict[@"description"] = source.description.text;
    
    // save data in the list
    [self saveData:dict withPassword:source.password.text];
    [self.collectionView reloadData];
}
Elegantly in a few lines of code and some ctrl drag and drop magic we've got everything settled. You can find the complete code for this example in my github repository.