Skip to content
This repository has been archived by the owner on Dec 13, 2021. It is now read-only.
Thomas Van Lenten edited this page Aug 19, 2015 · 8 revisions

Using the OAuth Controllers

Introduction

OAuth 1 is a protocol allowing your application to obtain authorization to read or modify a user’s files or data on an external server.

The server generates a web page for the user to sign in with her name and password, including a button explicitly granting access to some of her data. Upon successful authentication, the server gives a token to your application representing the user's authorization.

With the Objective-C OAuth controllers, the web page can be presented as an iOS view or a Mac sheet within your application. The controllers also provide authentication objects that simplify your application's future requests for the user's data.

OAuth 1 relies on a fragile and complex request-signing process, and so is generally being supplanted by the newer OAuth 2 standard.

Using the iOS and Mac OS X OAuth Controllers

The OAuth controllers are useful for authenticating to a variety of services which require OAuth 1.

There are example iOS and Mac applications using the OAuth controllers in the library's Examples directory.

Adding the Controllers to Your Project

The project has targets for building a static library for iOS and a framework for Mac OS X. Alternatively, the source files and xibs may be dragged directly into your project file and compiled with your application.

Check out the "top-of-trunk" OAuth controller sources with a Mac terminal window. The source files required are:

iOS and Mac OS X iOS Mac OS X
GTMOAuthAuthentication.h/m GTMOAuthSignIn.h/m GTMHTTPFetcher.h/m GTMOAuthViewControllerTouch.h/m GTMOAuthViewTouch.xib (optional) GTMOAuthWindowController.h/m GTMOAuthWindow.xib

These source files can be browsed in the project's source directory.

When linking against a static library build of the controller, specify the -ObjC build option for the application target's "Other Linker Flags".

ARC Compatibility

When the controller source files are compiled directly into a project that has ARC enabled, then ARC must be disabled specifically for the controller source files.

To disable ARC for source files in Xcode 4, select the project and the target in Xcode. Under the target "Build Phases" tab, expand the Compile Sources build phase, select the library source files, then press Enter to open an edit field, and type -fno-objc-arc as the compiler flag for those files.

System Requirements

The Mac controller is compatible with Mac OS X 10.5 and later. The iOS controller is compatible with iPhone OS 3 and later.

The OAuth controllers require linking to the system frameworks Security.framework and SystemConfiguration.framework.

Signing in to Services

To sign in to a service, you should consult the service's API documentation to obtain a pre-assigned consumer key and secret string, and to find the required scope string for API operations.

To use the OAuth 1 controllers with services, your application should create an authentication object with the appropriate keys, like this:

- (GTMOAuthAuthentication *)myCustomAuth {
  NSString *myConsumerKey = @"abcd";    // pre-registered with service
  NSString *myConsumerSecret = @"efgh"; // pre-assigned by service

  GTMOAuthAuthentication *auth;
  auth = [[[GTMOAuthAuthentication alloc] initWithSignatureMethod:kGTMOAuthSignatureMethodHMAC_SHA1
                                                      consumerKey:myConsumerKey
                                                       privateKey:myConsumerSecret] autorelease];

  // setting the service name lets us inspect the auth object later to know
  // what service it is for
  auth.serviceProvider = @"Custom Auth Service";

  return auth;
}

Displaying the sign-in view with a custom auth also requires providing the OAuth endpoints (URLs) and scope string to the controller, as shown here:

- (void)signInToCustomService {

  NSURL *requestURL = [NSURL URLWithString:@"http://example.com/oauth/request_token"];
  NSURL *accessURL = [NSURL URLWithString:@"http://example.com/oauth/access_token"];
  NSURL *authorizeURL = [NSURL URLWithString:@"http://example.com/oauth/authorize"];
  NSString *scope = @"http://example.com/scope";

  GTMOAuthAuthentication *auth = [self myCustomAuth];

  // set the callback URL to which the site should redirect, and for which
  // the OAuth controller should look to determine when sign-in has
  // finished or been canceled
  //
  // This URL does not need to be for an actual web page
  [auth setCallback:@"http://www.example.com/OAuthCallback"];

  // Display the autentication view
  GTMOAuthViewControllerTouch *viewController;
  viewController = [[[GTMOAuthViewControllerTouch alloc] initWithScope:scope
                                                              language:nil
                                                       requestTokenURL:requestURL
                                                     authorizeTokenURL:authorizeURL
                                                        accessTokenURL:accessURL
                                                        authentication:auth
                                                        appServiceName:@"My App: Custom Service"
                                                              delegate:self
                                                      finishedSelector:@selector(viewController:finishedWithAuth:error:)] autorelease];

  [[self navigationController] pushViewController:viewController
                                         animated:YES];
}

The application service name is used to save the token on the user’s keychain, and should identify both your application name and the service name(s). If appServiceName is nil, the token will not be saved, and the user will have to sign in again the next time the application is run.

When the user signs in successfully or cancels signing in, the view or window controller will invoke your finishedSelector’s method:

- (void)viewController:(GTMOAuthViewControllerTouch *)viewController
      finishedWithAuth:(GTMOAuthAuthentication *)auth
                 error:(NSError *)error {
 if (error != nil) {
   // Authentication failed
 } else {
   // Authentication succeeded
 }
}

If [error code] is kGTMOAuthErrorWindowClosed (-1000), then the user closed the sign-in view before completing authorization. Otherwise, any error reflects the server response in validating the user's access.

The controllers also support Objective-C block completion handlers as alternatives to the delegate and finished selectors.

Using the Authentication Tokens

If authentication succeeds, your application should retain the authentication object. It can be used directly to authorize NSMutableURLRequest objects:

[auth authorizeRequest:myNSURLMutableRequest];

Retrieving Authorization from the Keychain

If your application saves the authorization to the keychain (by setting the controller's appServiceName), it can be retrieved the next time the application launches:

- (void)awakeFromNib {
  // Get the saved authentication, if any, from the keychain.
  GTMOAuthAuthentication *auth = [self myCustomAuth];
  if (auth) {
    BOOL didAuth = [GTMOAuthViewControllerTouch authorizeFromKeychainForName:@"My App: Custom Service"
                                                              authentication:auth];
    // if the auth object contains an access token, didAuth is now true
  }

  // retain the authentication object, which holds the auth tokens
  //
  // we can determine later if the auth object contains an access token
  // by calling its -canAuthorize method
  [self setAuthentication:auth];
}

If no authorization was saved, then “auth” will still be a valid authorization object but will be unable to authorize requests:

BOOL isSignedIn = [auth canAuthorize]; // returns NO if auth cannot authorize requests

Signing Out

To completely discard the user’s authorization, use the view or window controller calls to remove the keychain entry:

[GTMOAuthViewControllerTouch removeParamsFromKeychainForName:kAppServiceName];

Finally, release the authorization object.

Debugging Tips

Getting OAuth 1 to work with a service provider can be challenging, especially with providers that implement extensions to the basic standard protocol. Here are a few times for getting GTMOAuth working.

HTTP Logging

Turn on http logging to inspect the server requests and responses. To enable http logging, add GTMHTTPFetcherLogging.h/m to your project, and call

[GTMHTTPFetcher setLoggingEnabled:YES];

The log will be written to a folder on the desktop or in the device data directory. Often, helpful server errors can be found in the responses in the log.

More information about http logging is in the GTMHTTPFetcher documentation here.

Signature Base String

If the server signature check is failing, turn on signature diagnostics by specifying

#define GTL_DEBUG_OAUTH_SIGNING 1

at the top of GTMOAuthAuthentication.m. The console output will then list the components being signed and, more importantly, the base string being signed for a sign-in attempt.

Compare the GTMOAuth base string to the base string shown in the provider's documentation.

Design Notes

The library's classes are designed in three layers.

Window/View Controller :: user interface & application API
Sign-In :: networking (OAuth dance)
Authentication :: data handling, request signing, and keychain

Classes are written to be independent of the layers above them.

The window and view controllers are retained only during the user's sign-in interaction.

The sign-in object is typically invisible to the client application.

The authentication object must be retained by the client app to sign NSMutableURLRequests. It is also used to save authentication to and read authentication from the keychain.

Questions and Comments

You can learn more about the OAuth protocol for desktop and mobile applications at Google's documentation.

Additional documentation for the controllers is available in the header files.

If you have any questions or comments about the library or this documentation, please join the discussion group.