Basic Security in iOS 5 – Part 1

This is a post by Chris Lowe, an iOS application developer and aspiring game developer living in San Antonio, Texas. He warns that this tutorial is pretty Epic in length, but promises you’ll learn a thing or two along the way. :] One of the most important aspects of software development also happens to be […] By Chris Lowe.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Time To Code!

Enough with the Storyboard editor for now – let’s code something before we go cross-eyed hooking up Segues and tweaking table view cells! :]

We’ll start with the first View Controller that we tweaked in the Storyboard. Create a new file with the iOS\Cocoa Touch\UIViewController subclass template, name it ChristmasRootViewController, and make it a subclass of UIViewController. Leave the bottom two options unchecked.

Open ChristmasRootViewController.h and add a property for a BOOL that will tell us whether the user is authenticated. Call it “pinValidated.” Also, since we are going to be using several text fields in this class, go ahead and add yourself as a UITextField delegate ().

#import <UIKit/UIKit.h>

@interface ChristmasRootViewController : UIViewController <UITextFieldDelegate>

@property (nonatomic) BOOL pinValidated;

@end

Jump over to ChristmasRootViewController.m and synthesize the property we just created:

@synthesize pinValidated;

Next add the implementations for viewDidLoad and viewDidAppear:

#pragma mark - View lifecycle
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.pinValidated = NO;
}

- (void)viewDidAppear:(BOOL)animated 
{
    [super viewDidAppear:animated];
    [self presentAlertViewForPassword];
}

Two lines of code were added here. First we initialize our pinValidated property to NO. Then, once our view is on the screen, we call a method called presentAlertViewForPassword.

What does this do? Well, exactly as the method signature indicates, we are going to prompt the user for their PIN if they have one, or require them to set one up if they don’t. Add this above those two methods:

- (void)presentAlertViewForPassword 
{
    
    // 1
    BOOL hasPin = [[NSUserDefaults standardUserDefaults] boolForKey:PIN_SAVED];
   
    // 2
    if (hasPin) {
        // 3
        NSString *user = [[NSUserDefaults standardUserDefaults] stringForKey:USERNAME];
        NSString *message = [NSString stringWithFormat:@"What is %@'s password?", user];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Enter Password" 
                                                        message:message  
                                                       delegate:self 
                                              cancelButtonTitle:@"Cancel" 
                                              otherButtonTitles:@"Done", nil];
        // 4
        [alert setAlertViewStyle:UIAlertViewStyleSecureTextInput]; // Gives us the password field
        alert.tag = kAlertTypePIN;
        // 5
        UITextField *pinField = [alert textFieldAtIndex:0];
        pinField.delegate = self;
        pinField.autocapitalizationType = UITextAutocapitalizationTypeWords;
        pinField.tag = kTextFieldPIN;
        [alert show];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Setup Credentials" 
                                                        message:@"Secure your Christmas list!"  
                                                       delegate:self 
                                              cancelButtonTitle:@"Cancel" 
                                              otherButtonTitles:@"Done", nil];
        // 6
        [alert setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
        alert.tag = kAlertTypeSetup;
        UITextField *nameField = [alert textFieldAtIndex:0];
        nameField.autocapitalizationType = UITextAutocapitalizationTypeWords;
        nameField.placeholder = @"Name"; // Replace the standard placeholder text with something more applicable
        nameField.delegate = self;
        nameField.tag = kTextFieldName;
        UITextField *passwordField = [alert textFieldAtIndex:1]; // Capture the Password text field since there are 2 fields
        passwordField.delegate = self;
        passwordField.tag = kTextFieldPassword;
        [alert show];
    }
}

This looks like a lot of code, but actually it’s quite simple. Let’s go over it step by step.

  1. First we check if the user has set up a PIN before. We do that by checking for a BOOL that we saved to the NSUserDefaults. Notice that we are checking for a key called PIN_SAVED. That seems kind of odd – it’s actually a macro from a Constants class we will get to in a moment.
  2. Then we evaluate if we have the BOOL or not. If we do, that means the user has launched this app before and gone through the setup process. If not, then the user hasn’t been here or setup the PIN before, so let’s prompt him again.
  3. Next we get the user’s name, also stored in NSUserDefaults, and then we ask “What is [your name here]’s password?” Notice we also assign a value to alert.tag, from an enum also in the Constants class.
  4. A great new feature in iOS5 is that we now have multiple types of UIAlertViews at our disposal! Here we are going to use the UIAlertViewStyleSecureTextInput type, which simply gives us an alert view with a text field for entering a password.
  5. Another great new thing in iOS5: out of the box, we get access to the UITextFields that are shown in an alert view! No more hacks to navigate the view hierarchy, etc. Notice that the UIAlertView class now has a nice method for us called “textFieldAtIndex,” which gives us the UITextFields available to us! Also, we can do ANYTHING that you can do on a normal UITextField – here we are setting the delegate, the capitalization settings, and the tag.
  6. Like #4 above, we are going to use another new Alert View style, but this time have two text fields for a user name and password. Again, we can customize the UITextField to our liking. So, for example, you could set the keyboard type on the Password input if you want to restrict the password to numbers only.

OK, from here let’s create our Constants class (this will house all of our Macros, enums, etc.), update our Storyboard, then hit our first real Build and Run!

For the Constants class, create a new file with the iOS\Cocoa Touch\Objective-C class template, set the class as ChristmasConstants, and make it a subclass of NSObject. For this tutorial, we only need the .h, so you can delete the .m.

Then replace ChristmasConstants.h with the following:

// Used for saving to NSUserDefaults that a PIN has been set, and is the unique identifier for the Keychain.
#define PIN_SAVED @"hasSavedPIN"

// Used for saving the user's name to NSUserDefaults.
#define USERNAME @"username"

// Used to specify the application used in accessing the Keychain.
#define APP_NAME [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]

// Used to help secure the PIN.
// Ideally, this is randomly generated, but to avoid the unnecessary complexity and overhead of storing the Salt separately, we will standardize on this key.
// !!KEEP IT A SECRET!!
#define SALT_HASH @"FvTivqTqZXsgLLx1v3P8TGRyVHaSOB1pvfm02wvGadj7RLHV8GrfxaZ84oGA8RsKdNRpxdAojXYg9iAj"

// Typedefs just to make it a little easier to read in code.
typedef enum {
    kAlertTypePIN = 0,
    kAlertTypeSetup
} AlertTypes;

typedef enum {
    kTextFieldPIN = 1,
    kTextFieldName,
    kTextFieldPassword
} TextFieldTypes;

Basically, all this file does is contain strings that we’ll use throughout the application.

We use enums here (remember our ChristmasKeeperRootViewController class) so that we can easily identify the Alert Type. We don’t have to remember that 0 means password only and 1 means username/password. The same goes for the TextFieldTypes enum.

Ignore the SALT_HASH meaning for now – we’ll get to that soon.

Now, go back to ChristmasRootViewController.h and import this class:

#import "ChristmasConstants.h"

Finally, jump back to the MainStoryboard.storyboard, select our first View Controller, and set its Class type under the Identity Inspector to ChristmasKeeperRootViewController (its likely still set to ViewController by default).

w00t – it’s finally time to BUILD AND RUN!!! When it starts up you should see a nice popup appear:

CKAlertSetup

Chris Lowe

Contributors

Chris Lowe

Author

Over 300 content creators. Join our team.