OAuth 2.0 with Swift Tutorial

In this OAuth 2.0 Swift tutorial you will learn how to use two different open source libraries to implement OAuth 2.0 in an iOS app. By Owen L Brown.

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

Step 3: Get Resources

Using the access token, Incognito can access protected resources on the server — that is, the resources the end-user granted access to. Your upload is free to proceed.

Ready to see this in action? First, you need to register with the OAuth 2.0 provider: Google.

Registering With your OAuth 2.0 Provider

If you don’t have a Google account, go create one now. It’s OK; I’ll wait for you. :]

Open https://console.developers.google.com/ in your browser; you’ll be prompted to authenticate with Google.

Click Create Project and name your new project Incognito:

Next, you need to enable the Drive API.

Click Library in left menu and search for Google Drive API and select it. On the next screen, click Enable:

Now you need to create new credentials to access your Drive accounts from the app.

Select Credentials in left menu and from the blue Create Credentials drop down, select OAuth client ID.

Then click Configure consent screen and in the screen that appears, fill out the following information:

  • Email address: Select your email address
  • Product name: Incognito
  • Homepage URL: http://www.raywenderlich.com

Click Save and you’ll return to the Client ID screen. Select select iOS and enter com.raywenderlich.Incognito as your Bundle ID.

The authorization server will use the bundle id entered above as the redirect URI.

Finally, click Create. A popup with the Client ID appears, just click Ok.
The important parameter needed for later is the Client ID. You can grab it anytime by clicking Credentials in the left menu and picking your client ID from the OAuth ID list.

Now that you’ve registered with Google, you’re ready to start your OAuth 2.0 implementation using the first OAuth 2.0 library: AeroGear with an external browser.

Authenticating with AeroGear and External Browsers

Open ViewController.swift and add the following imports to the top of the file:

import AeroGearHttp
import AeroGearOAuth2

Now, add the following instance variable inside the ViewController class:

private let http = Http(baseURL: "https://www.googleapis.com")

You’ll use this instance of Http, which comes from the AeroGearHttp library, to perform HTTP requests.

Still in ViewController.swift, find the empty share(_:) method and add the following code to it:

//1
let googleConfig = GoogleConfig(
  clientId: "YOUR_GOOGLE_CLIENT_ID",                           
  scopes:["https://www.googleapis.com/auth/drive"])            
    
//2
let gdModule = AccountManager.addGoogleAccount(config: googleConfig)
//3
http.authzModule = gdModule                               
//4
let multipartData = MultiPartData(data: snapshot(),       
  name: "image",
  filename: "incognito_photo",
  mimeType: "image/jpg")
let multipartArray =  ["file": multipartData]
//5    
http.request(method: .post, path: "/upload/drive/v2/files",  parameters: multipartArray) {
  (response, error) in
  if (error != nil) {
    self.presentAlert("Error", message: error!.localizedDescription)
  } else {
    self.presentAlert("Success", message: "Successfully uploaded!")
  }
}

Here’s what’s going on in the method above:

  • start the authorization code grant if no access token exists.
  • refresh the access token if needed.
  • if all tokens are available, simply run the POST call.
  1. Create a configuration. You’ll need to replace YOUR_GOOGLE_CLIENT_ID above with the Client ID from your Google Console to use the correct authorization configuration. At initialisation you also define the scope of the grant request. In the case of Incognito, you need access to the Drive API.
  2. You then instantiate an OAuth2 module via AccountManager utility methods.
  3. Next you inject the OAuth2 module into the HTTP object, which links the HTTP object to the authorization module.
  4. Then you create a multi-part data object to encapsulate the information you wish to send to the server.
  5. Finally, you use a simple HTTP call in to upload the photo. The library checks that an OAuth2 module is plugged into HTTP and makes the appropriate call for you. This will result in one of the following outcomes:
Note: For more information on how to use AeroGear OAuth2, either check out AeroGear’s online documentation and API reference, or browse through the source code in the Pods section.

Build and run your app; select an image, add an overlay of your choosing, then tap the Share button. Enter your Google credentials if you’re prompted; if you’ve logged in before, your credentials may be cached. You’ll be redirected to the grant page. Tap Accept and…

Boom — you receive the Safari Cannot Open Page error message. :[ What’s up with that?

Invalid address in OAuth2 flow

Once you tap Accept, the Google OAuth site redirects you to com.raywenderlich.Incognito://[some url]. Therefore, you’ll need to enable your app to open this URL scheme.

Note: Safari stores your authentication response in a cookie on the simulator, so you won’t be prompted again to authenticate. To clear these cookies in the simulator, go to Hardware\Erase All Content and Settings.

Configuring the URL Scheme

To allow your user to be re-directed back to Incognito, you’ll needs to associate a custom URL scheme with your app.

Go to the Incognito\Supporting Files group in Xcode and find Info.plist. Right click on it and choose Open As\Source Code.

Add the following to the bottom of the plist, right before the closing </dict> tag:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>com.raywenderlich.Incognito</string>
        </array>
    </dict>
</array>

The scheme is the first part of a URL. In web pages, for example, the scheme is usually http or https. iOS apps can specify their own custom URL schemes, such as com.raywenderlich.Incognito://doStuff. The important point is to choose a custom scheme that it unique among all apps installed on your users’ devices.

The OAuth 2.0 dance uses your custom URL scheme to re-enter the application from which the request came. Custom schemes, like any URL, can have parameters. In this case, the authorization code is contained in the code parameter. The OAuth 2.0 library will extract the authorization code from the URL and pass it in the next request in exchange for the access token.

You’ll need to implement a method in Incognito’s AppDelegate class for the app to respond when it’s launched via a custom URL scheme.

Open AppDelegate.swift and add the following import statement to the top of the file:

import AeroGearOAuth2

Next, implement application(_:open:options) as shown below:

func application(_ app: UIApplication,
                 open url: URL,
                 options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {

  let notification = Notification(name: Notification.Name(AGAppLaunchedWithURLNotification),
                                  object:nil,
                                  userInfo:[UIApplicationLaunchOptionsKey.url:url])
  NotificationCenter.default.post(notification)
  return true
}

This method simply creates an Notification containing the URL used to open the app. The AeroGearOAuth2 library listens for the notification and calls the completionHandler of the POST method you invoked above.

Build and run your project again, take a snazzy selfie and dress it up. Click the share button, authenticate yourself, and lo and behold:

You can download the finished Incognito AeroGear project from this section if you wish.

Switching context to an external browser during the OAuth 2.0 authentication step is a bit clunky. There must be a more streamlined approach…