If you're using Pugpig and you want to secure your content, you'll probably need to write a custom authorisation provider. The provider decides if the user should have access to a given document, and provides credentials for the document if access should be permitted. The credentials should be a username and a password. Pugpig will assume the document is protected by HTTP Basic Authentication and use these credentials to access the document.
Pugpig comes with optional providers for the Apple app store, allowing your users to purchase single products and subscriptions.
Understanding the provider interface
An authorisation provider must implement the
KGAuthorisation protocol, which has two required methods (see KGAuthorisation.h in the Pugpig framework):
typedef void (^KGAuthCompletionHandler)(NSString *identifier, NSString *userid, NSString *password, NSError *error); .. - (BOOL)hasPurchasedProductIdentifier:(NSString*)identifier; - (void)requestCredentialsForProductIdentifier:(NSString*)identifier completionHandler:(KGAuthCompletionHandler)completion;
hasPurchasedProductIdentifier determines if the provider thinks that a user should have access to a given document. It should usually indicate that a call to
requestCredentialsForProductIdentifier will succeed. When the framework wants to determine the current state of the document it asks this function - for example, the issue selector will use it to display either a “buy” button (user doesn't yet have access and must purchase the document) or “download” button (user has rights to the document, so requesting credentials will succeed and these credentials can then be used for the download).
requestCredentialsForProductIdentifier requests the credentials for a document. This will be called when you try to authorise a protected document for the first time. Your provider should use the provided
KGAuthCompletionHandler callback to specify credentials.
If the authorisation fails, the callback should set the username and password to
nil, and the error to an
NSError object with the domain
KGAuthErrorDomain, and one of the following error codes:
|Error code||Error message displayed|
|KGAuthErrorNetworkFailure||We were unable to connect to the network.|
|KGAuthErrorProductUnavailable||This item is not yet available for purchase.|
|KGAuthErrorSubscriptionExpired||Your subscription has expired.|
|KGAuthErrorUnknown||There was a problem with the authorisation service.|
|KGAuthErrorPurchaseCancelled||No message is displayed|
In the case of
KGAuthErrorUnknown you can also include more details about the error via the
NSError object's userInfo dictionary. You can set the value of the dictionary key “originalError” to another NSError object - typically this would be an error from some underlying API that caused the authentication to fail. If this originalError is provided, its localizedDescription property will also be displayed as part of the error message.
It is important that these calls do not block, so if they aren't going to run quite quickly you should process them in the background. For example, our app store provider's credentials request talks to a server to validate an app store product receipt, so we need to keep a queue of requests and process them one at a time in the background.
Handling updates to authorisation status
Your authorisation provider must keep Pugpig up to date on any changes in authorisation status. For example, if your provider polls a server to ensure that a user still has access to documents and that status changes (either blocking access when previously allowed, or vice versa), you must post a notification:
[[NSNotificationCenter defaultCenter] postNotificationName:KGAuthChangeNotification object:self];
Adding your provider
You must tell Pugpig to include your provider in the list of available authorisation providers. This is generally done within your app delegate's
didFinishLaunchingWithOptions method. The document manager allows you to add providers with a single call:
KGDocumentManager *dm = [KGDocumentManager sharedManager]; self.myProvider = [[[MyAuthorisation alloc] init] autorelease]; // MyAuthorisation *myProvider is a property on our app delegate [myProvider addAuthorisation:myProvider];
If you have built your app from the Pugpig template, you will see a commented out TODO that adds the providers for the Apple app store. You can choose to have your provider in addition to the app store providers. When there are multiple providers, Pugpig will query them in the order that they were added and will stop on the first provider that responds. Generally speaking, you want to put providers that have good fallback first. If you wish to support the app store, we would usually suggest having the KGAppStoreAuthorisation and KGAppStoreSubscriptionAuthorisation providers first.