Login from iOS to WordPress with OAuth2

It’s been a little over a year since first posting this tutorial. A lot has changed with iOS, Swift and WordPress between then and now, so instead of brieflly revising this tutorial, I’ll do a full rewrite.

Login from iOS to WordPress with OAuth2…

..but this time with Swift 3 and WordPress 4.7.2

The following tutorial is for iOS 9+, Swift 3, WordPress 4.7.2+

OAuth2

OAuth2 allows us to use a more secure, stateless, token based system to enable communication between our app and WordPress and additional domains if needed.

But why not OAuth1a?

To be honest, I still couldn’t get it to work on mobile without avoiding the server-side login screen. While that in and of itself not a problem, in my opinion it is disruptive to the user experience. And I am also fully aware of the security concerns around OAuth2, but in this tutorial you’ll learn how to alleviate some of those concerns.

Before we get started

This tutorial assumes you have a working knowledge of Xcode, Swift, OAuth2, WordPress and CocoaPods.

Testing and staging for this tutorial MUST take place on WordPress installation with a valid SSL Certificate
This tutorial will not support any of the earlier plugins used in previous tutorials 
This tutorial will not work on localhost unless your installation has an SSL Certificate. If you’re using a remote host, I highly recommend using Let’s Encrypt.

Both setups are easy and straight forward. If you don’t have hosting you can get setup with Digital Ocean for as low as $10.

Now let’s get started

Before proceeding please download the forked WP OAuth2 Server & Client plugin 
Login to your WordPress installation and install the WP OAuth2 Server & Client plugin. Next navigate to Dashboard > OAuth Server > Advanced Configuration. For Grant Types, check the following:

  • Authorization Code
  • User Credentials
  • Refresh Tokens

grant-types Under Misc Settings, check: Require Exact Redirect URI require-exact-redirect-uri Under the Clients tab, click Add New Client. You can call your client anything you want, I named mine “iOS Wp OAuth”. The most important field in this dialog box is the Redirect URI. this will display your site url by default. For this tutorial, we will append the parameter ?_wpoauth_callback=standard. I will discuss this paremeter in detail later in this tutorial. AddNewClient After adding your new client you’ll notice a generated Client ID and Client Secret. We’re done with the OAuth settings for now.

Create a test user

If you don’t already have one, create a test user, preferably a subscriber. There is no registration process in our iOS app, but I’m confident that you’ll be able to create one after following this tutorial.

Creating the iOS app

Now that we have OAuth2 in place server-side, let’s create the app. Fire up Xcode, and name your project. This will be a Single View App. Single View Application Name Your App Now close the app. If you are familiar with CocoaPods, continue, if not, please visit https://cocoapods.org to get a primer on how to use it to install dependencies in your Xcode project.
This Xcode project relies on the following dependencies:

After familiarizing yourself with CocoaPods, create a Podfile inside the project folder and add the following:
Make sure the target is the same as your project name. Next, open the Terminal, cd into your project folder, and run:
Now reopen the project, but open it from the .workspace file. Next, we’ll need to add 2 Swift files to our project. The first will be the OAuthWP file which will contain the necassary protocols for our app to communicate with WordPress. Go to File > New > File… Select iOS > Swift File and name the file OAuthWP Create Swift File Name Swift File Paste the following in the OAuthWP swift file:
There will be a break down of the OAuthWP protocols later.
Make sure you don’t forget to add your domain to the
line, or else the app won’t function.
Repeat the steps above, but this time create the EventHandler file. The Swift Events Gist can be found on GitHub is courtesy Colin Eberhardt. The event handler is a lot cleaner than using the NSNotificationCenter that I originally used when creating this project. The notification center lead to too many nested closures which lead to code stink. Inside the created EventHandler file, paste the following:
Next we’ll create 2 UIViewControllers, one named LoginViewController, the other ProfileViewController Cocoa Touch Class Create View Controllers

Setting up the Login Screen

Navigate to the Main.storyboard. Click the header of the initial view controller. In the Attributes Inspector, set the size to iPhone 4.7 under Simulated Metrics. Set Size In the Identity Inspector, set Class to LoginViewController Set Class Add another View Controller to the storyboard and repeat the steps above, but this time set the class to ProfileViewController. Drag 2 Text Fields and a Button on the Login View Controller. You can style these however you like. Please note for this tutorial I did not add contraints. The lack of constraints will throw a warning at runtime.  Login View Controller Next, create IBOutlets for both text fields and button. Open the Assistant Editor and collapse the right utilities bar. IBOutlet Username IBOutlet Password IBAction Login Button Name the 2 Text Field Outlets

And an IBAction for the login button

Here’s finished LoginViewController class:

Next, add a Text Field and a Button to the Profile View Controller: Profile View Controller Add add an IBOutlet for the Text field labeled displayName

and also and IBAction for the button labeled updateDisplayName

The finished ProfileViewController class:

Segues

We will need to create 2 segues, 1 from the Login View Controller to the Profile View Controller and vice versa. These segues will be programatically triggered based on the JSON response from our server. As shown in the 2 examples below, Control-Click the yellow View Controller indicator on top of the Login Controller and drag to the Profile View Controller. Select Show in the segue options dialig box: Repeat for the Profile View Controller The last step in this process is labeling the segues. Select the segue coming from the Login View Controller going to the Profile View Controller and label it ProfileController in the Attributes Inspector: ProfileController Repeat the step by selecting the Profile View Controller segue and labeling it LoginController: LoginController

Programatically selecting the Initial View Controller

After the app is launched, we want to determine if the Access Token is valid and hasn’t expired. If it’s legit, show the Profile View Controller, if not, show the Login View Controller. I didn’t include any initial token check in this tutorial, for the sake of keeping it simple. However there are a few ways one can go about this. You can make a call to the server and check the status of the Access Token. Keep in mind that this may interfere with UX if the network connection is slow. You could add a preload screen or animation to indicate to the user to standby. Another option is to save the expire value that’s returned with the access token upon successful authentication. A time tracking method created in Swift can keep track of the upcoming exiration date of the access token. Navigate to the AppDelegate and add the following above the application method:

Add the folloing inside the application function:

But does it work?

Let’s review my test user:

before

The usual display name

Login Screen

No tokens, so login is a must

Login Credentials

Imput username and password

Display Name

And there is my boring display name

New Display Name

Let’s change it to something cool…

Update Successful

My self hosted WordPress installation like it too…

Backend Updated

Didn’t think it worked ha?

The Breakdown

What’s going on in the AppDelegate, LoginViewController and ProfileViewController is self explanatory. All of the OAuth2 magic happens in the OAuthWP swift file.

Session Management and Certificate Pinning in Alamofire

Instead of performing the standard heirachical certificate checks, I’m telling the app to trust certificates only signed by wlcdesigns.com. This technique mitigates (not solves) man-in-the-middle attacks. We must also prevent the Alamofire session from deallocating from memory when before we initiate a secure connection with the our server. The Session class will prevent those annoying Error Domain = NSURLErrorDomain Code =-999 "cancelled" errors. If you plan on getting serious about iOS/WP development, I highly recommend Charles. Charles allows you to analyze your app’s performance over the http/https, including simulating man-in-the-middle attacks. Code with Chris has a great tutorial on how to debug your app with Charles.

OAuthWP Protocol

A protocol oriented approach enables us to use only what’s needed instead of inheriting a bunch of methods that we’ll never use (OOP). And if you don’t need all the functions contained in this protocol, you can always omit them or place them a separate protocol(s).

Extensions

If you’re coming from a Javasript background, extensions might remind you of Prototype or a Factory function. Extensions are accessable/inherited from within whatever struct/class the protocol is attached to.

Redirect URI and Authentication

Added to the WP OAuth2 Server & Client plugin is a standard authentication class. That class if called via the parameter (?_wpoauth_callback=standard) in the redirect uri. If you change the value of the ?_wpoauth_callback parameter, you can access the tokens in the wpoauth_finish hook e.g.:

If you want to use a completely different authentication function/class, then uncheck Use built In authentication: The StandardAuthentication class can be found in the wp-oauth2-server/library/authentication/ of the plugin.

Handling multiple clients

The WP OAuth2 Server & Client plugin was also modified to handle multiple clients. Let’s say your WordPress installation is accommodating 2 or more apps, but you want to use a different client for each app. This is achieved when you initially add the client. Make sure each client name is unique. After adding your client, click the Show Client Slug link below the client name.

Inside the OAuthWP.swift file you’ll find the Client Slug line:

that reflects the slug above. If you want to use a different client in your app, change the Client Slug accordingly.

What happened to the WP-REST-API?

The WP OAuth2 Server & Client plugin already comes with a “me” endpoint (as seen in the Xcode project)  that will authenticate without any additional bootstrapping. The built in wp-rest-api is currently not compatible with OAuth2, however you can still use it in place of the custom queries… or not. How you retrieve your WordPress data after the OAuth2 process is up to you.

Support

Due to my hectic schedule I’ll probably won’t be able to provide help or support. However I am open to maybe creating a forum for my tutorials to facilitate discussion and solutions.

Feedback

While this approach has worked without incident in my apps, I’m not an expert in security. If you find a flaw or have suggestions for improvments, please leave a comment below.