Yesterday evening I worked on a Mac App and on my agenda was authentication. This app (maybe later on more details about it) is an App.Net client. If you have a look at the developer documentation you see that there are three options available:
web flow (server side)
web flow (client side)
I decided to use the client web flow. At first I wasn’t sure if this will work, but I saw other apps that used this successfully, too. The alternative would be password flow, here your app offers a login screen and you have to obtain a special secret via email. This takes some time, because ADN staff needs to approve you explicitly. I wanted to start directly, so this was out.
I use ADNKit, which is available for Cocoa and Cocoa Touch. In the wiki, there is a page, where it is described what to do for authentication.
Step 1 Create a new app in your ADN profile
Here it is important, that you have registered a custom URL scheme. After you created a new application, you see a client ID and a client secret. The client secret must be kept confidential. You will need both later on.
Step 2 Manage dependencies
I use CocoaPods to manage third party libraries and their dependencies. This is my Podfile:
pod 'AFNetworking', '1.2.0'
pod 'ADNKit', '~> 1.2'
pod 'SSKeychain', '~> 1.0.4'
Disclaimer: I explicitly added AFNetworking here because version 1.2.1 did not compile on my machine. Actually CocoaPods solves the depedencies automatically so this is not necessary.
Step 3 Implementation
Create a .h and an .m file to store these parameters in constants:
Include WebKit.framework to your project. I created a LoginController which handles the authentication stuff and shows a web view:
I called the LoginController in my AppDelegate. Note, that the callback you pass to the authenticate method is called when the complete authentication process finished.
Explanation step by step:
When an access token is obtained, it needs to be saved somewhere, because we do not want the user to relogin again when he opens the app next time. So we use the keychain for that. Or more specific: SSKeychain. This wraps all calls to Objective-C. NSUserName() returns the current Mac OS X user.
Check if we already have an access token. If no, show login screen.
This method is called, when the user allowed access to its account. Here the oAuth access code needs to be parsed from the url.
The access code needs to be authenticated on App.net. Note that this call is non-blocking – you return immediately.
If the access code was authenticated, you get this callback. Now you can grab the actual token from the sharedClient and save it into the keychain.
If the user starts the application and has authenticated himself before, we only need to set the previously fetched access token from keychain to [ANKClient sharedClient].