Igor Sutton

Where unconformity and hubris meet technology

iCloud as Authentication Provider

Everybody is complaining about iCloud these days, and a lot of people smarter than me are elaborating that you should build your business using your own stack (which is certainly a smart thing to do). But this isn’t what I’d like to explore here. Probably other people, also smarter than me have thought about it, but I didn’t read anywhere. So here it goes:

Wouldn’t be awesome if iCloud served as authentication service for third party application’s back end services?

I came to this conclusion after realizing that this is one of the core issues with using, for instance, Dropbox to store and synchronize files between devices, or access to authenticated back end providers such as Parse or StackMob: yet another set of credentials.

If iCloud served as authentication provider for trusted third party applications, this wouldn’t be an issue anymore. Of course, you could still use iCloud’s synchronization services—in fact, Apple’s applications would be clients of this distributed infrastructure–if you feel it is appropriate for your needs.

So, on a really high level overview, how this would work?

Here is my take:

  • When creating your application at the Apple Store, you inform that you’d like iCloud to serve as your authentication provider. You’d create then an DSA or RSA key, and upload your public key for use in the authentication scheme. At this point you’d be able to download Apple’s public key as well, so you can use in your back end to validate the authentication token.

  • The application asks iCloud for an access token for the current device. iCloud links then the current device to the application that asked for an authentication token. This should use Apple’s provided APIs, since they can access the device’s iCloud credentials and also the device’s unique identifier, which is verboten for third party developers.

  • The application uses this token then to communicate with the third party application back end. This token is involved in each network request (either at the protocol negotiation phase or through special HTTP headers such as X-Apple-Token). The token is then verified at the third party application’s back end, and if it passes the checks the communication is then allowed. Since the token is signed with Apple’s private key and your application server’s public key, only those having access to your private key can validate it.

Conclusion

This would benefit everybody:

  • Would remove the weight of Apple shoulders to provide a generic yet bullet-proof synchronization solution;
  • Give developers a lot of freedom to do what fits their business needs (remember, each application synchronizes data on a different way); and
  • Would prevent the people that pays our bills to create yet another account in yet another service.

It would be a win for everybody, and also would slap Google’s “we are open” face.

How Can Singletons Be a Pain in the Arse

I’ve got into a discussion about the Singleton pattern a couple of days ago, and since I’m quite opinionated about the subject, I’ll register here the reasons I prefer other techniques over this design pattern here for future reference.

In my opinion, overusing the Singleton pattern leads to some problems such as:

  • Implicit dependency; and
  • Makes testing a pain in the arse.

I will try to illustrate these points.

Implicit Dependency

This is quite easy to identify: every dependency that isn’t explicitly stated, is implicit. For instance, if you have a class–let’s call it CarsViewController, which is a UIViewController subclass that displays a list of cars using a UITableView. You take a look in the header and in the implementation block for instance variables, and can’t find anything unusual. You think it is safe to reuse this class in another project.

You then import the source files into your project and the build phase fails when it reaches a piece of code like this, buried inside your CarsViewController implementation:

1
2
3
4
5
- (Car *)carAtIndexPath:(NSIndexPath *)indexPath
{
	NSString *carID = [_carIDs objectAtIndex:indexPath.row];
	return [[CarsDataSource sharedInstance] carWithID:carID];
}

(For the sake of the argument, let’s assume CarsDataSource is being used in several places in the project and was imported in the project’s pre-compiled headers.)

Interesting enough, you now have a dependency on CarsDataSource that you didn’t know, and probably a other code that you weren’t interested in should be also imported to your project.

To avoid this kind of problem, the approach I try to follow is to inject all the dependencies as explicit as possible. On the CarsViewController example, I’d have instead property declared in the interface like @property (weak) CarsDataSource *dataSource, and let the piece of code responsible to create a new instance of the CarViewController class fill it.

The interface definition (the header file) would look similar to the following:

1
2
3
4
5
6
7
8
9
@class Car;

@interface CarsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

@property (strong) CarsDataSource *dataSource; // The data source can not disappear until we're done!

- (Car *)carAtIndexPath:(NSIndexPath *)indexPath;

@end

And after refactoring the -carWithIndexPath: message implementation, it would look like the following:

1
2
3
4
5
- (Car *)carAtIndexPath:(NSIndexPath *)indexPath
{
	NSString *carID = [_carIDs objectAtIndex:indexPath.row];
	return [self.dataSource carWithID:carID];
}

With this implementation, we shed the light on the relationship between the CarViewController and its dataSource property. The -tableView:didSelectRowAtIndexPath: message of UIViewController subclass presenting a list of car brands would look similar to the following:

1
2
3
4
5
6
7
8
9
10
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
	CarsViewController *vc = [[CarsViewController alloc] init];

	// A reference to the dataSource we want to use. If we were using a Singleton in
	// the CarsViewController implementation, we wouldn't have the following line.
	vc.dataSource = self.dataSource;

	[self presentModalViewController:vc animated:YES];
}

Makes Testing a Pain in the Arse

Let’s continue speculating about the original CarsViewController class implementation, where it uses a singleton instead of a declared property.

How do we test the piece of code using the CarsDataSource shared instance, since it is calling the +sharedInstance message on CarsDataSource class to obtain a CarsDataSource instance?

Certainly we’d have to create some mechanism in the CarsDataSource to be able to swap the instance returned by the +sharedInstance message, exemplified by the following code block:

1
2
3
4
5
6
7
8
+ (CarsDataSource *)sharedInstance
{
#ifdef TEST
	return testInstance;
#else
	return productionInstance;
#endif
}

This obviously has its drawbacks, mainly because we’d have to change the code conditionally, and we wouldn’t be testing the real production code. Not good at all.

Another approach to solve this problem the hard way would be create a category that is included only when running the test suite and inject the shared instance in the class, but this would much probably require a refactoring of the class itself depending the way +sharedInstance was implemented. Also not good.

My approach to solve this, while keeping the same explicit dependency idea exposed in the section above, is to change the signature of the dataSource property to id instead of CarsDataSource, and introduce a formal protocol stating the messages the dataSource instance should implement:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@class Car;

@protocol CarsDataSource <NSObject>

- (Car *)carWithID:(NSString *)carID;
- (NSUInteger)numberOfCars;

@end

@interface CarsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

@property (weak) id <CarsDataSource> dataSource;

@end

This would, automagically, add some test capabilities to our CarsViewController class, since we could inject any object conforming with the CarsDataSource protocol.

Below you can see an example of how I’d test the CarsViewController class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@implementation CarsViewControllerTests {
	CarsViewController *_carsViewController;
	MockCarsDataSource *_mockCarsDataSource;
}

- (void)setUp
{
	_carsViewController = [[CarsViewController alloc] init];
	_mockCarsDataSource = [[MockCarsDataSource alloc] init]
}

- (void)tearDown
{
	_carsViewController = nil;
	_mockCarsDataSource = nil;
}

- (void)testCarViewControllerHasOneCar
{
	Car *testCar = [[Car alloc] initWithName:@"Golf"];
	[_mockCarDataSource setCar:testCar forID:@"1"]];

	// Internally uses the CarsDataSource's -numberOfCars method.
	NSInteger numberOfCars = [_carsViewController tableView:nil numberOfRowsInSection:0];
	STAssertTrue(numberOfCars, 1, nil);

	Car *car = [_carsViewController carAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
	STAssertEqualObjects(car, testCar, nil);

	// more tests here...
}

@end

Conclusion

Yes, you can use Singletons. But use it carefully. This will add dependencies you may not be aware of, and you’ll probably have to do a bunch of unnecessary work to be able to test your application.

Instead, prefer to make the relationship between your entities explicit by adding properties. This will lead to a loosed coupled, easily testable and reusable code.