Relying parties may also want to develop an mobile App (on Android or iOS) to use the resources on their site, such as accessing the user’s private info like photo, order detail etc. Such mobile Apps usually use protocols like OAuth to get the user’s authentication via tokens and use the tokens to retrieve the user’s private data. This document describes the detailes of implementing a particular technique for the iphone and Android.
Workflow of a typical user resource retrieval includes:
User login into the RP site (with federated login or legacy login). The RP site ask user’s permission for accessing some of the user’s private data, user grant the permission and finish the login process.
The RP site sends the token back to the mobile App, and the mobile App detects that the RP site has finished the login/authentication process and the token is available. The mobile App fetch the token.
The mobile App uses the token to call the RP’s web service API to retrieve the data.
The iOS provides both the default Safari browser and the UIWebView component for mobile Apps to launch a browser and the view the specified URL. But the default Safari browser is a stand-alone application which is very hard to communicate with the App to deliver the token. The UIWebView component provides similar features like the Safari browser, and it is compiled as part of the mobile App, so it is convenient to access the UIWebView’s page title or cookie etc. In our practice, we choose UIWebView to do the login/authenticate process.
(1) Create the UIWebView page in InterfaceBuilder
Create a new UIViewController and drag the UIWebView component onto it in InterfaceBuilder. Add some necessary buttons like “back” and “forward” (this is optional).
(2) Display the UIWebView page using UINavigationController
We recommend to use the UINavigationController to display the login page and navigate back the main page after getting the token.
1. Create a UINavigationController (directly in the main window delegate in our example).
UINavigationController *theNavController = [UINavigationController alloc];
self.navigationController = theNavController;
self.window.rootViewController = self.navigationController;
Note that we have set our main page as the first view (startView) in the UINavigationController so that it will be displayed when the program starts. Our start view looks like below, but this view is entirely up to the RP.
(3) Set the request URL display the web page
In the login view, we should call the “loadRequest” method of UIWebView to load the login web page that we want to use. Here is a sample code to do this work:
Note that in the above sample code, we did several key steps.
After the RP site finishes the login/authentication process, it will redirect the user’s browser to a success page. In that success page, a cookies is set with key = ‘oauth_token’ and the value is the the access token. This token should be delivered back the the mobile App’s main program so that it can use this token to get the user’s private data. The code that extract the token from the cookies is shown below:
Note that the “webViewDidFinishLoad” is a delegate function that UIWebView calls when it finish loading any page. The page may not be the confirmation page which carries the user’s authorized token, so we have to check if the token is already in the cookies and if so we will close the login view, call the user delegate to pass the token and go back to main page.
After getting the token, we could use NSURLConnection to retrieve the data.
You can create a menu item called ‘login’ or ‘sign in’ to allow users to start the authentication.
(1) Create a menu resource
The easiest way to create a menu is defining a menu and all its items in an XML menu resource file, then inflating the menu resource in your application code. Here’s the example menu resource named ‘my_menu.xml’:
(2) Inflate the menu resource and respond to user action
You can use MenuInflater.inflate() to inflate a menu resource in Activity.onCreateOptionsMenu() callback method. In Activity.onOptionsItemSelected() callback method, you can respond to the user action. The following sample code shows that if the user click the ‘login’ menu item, a WebViewActivity, which we’ll elaborate later, is started to handle the authentication and return the result to the calling activity.
The Android os provides a default web browser. Since the web browser is a stand-alone application and only provides its bookmark and history information to other applications, it is difficult to get the OAuth token from it. The Android os also provides a widget called WebView, which allows you to display web pages in it and to access the page’s information such as page title, cookies etc. In our practice, we choose WebView to do the work.
(1) Create the WebView activity
The activity is simple, which only contains a WebView widget.
(2) Make WebViewActivity to behave like a web browser
The default behavior of a WebView is not what you expect. When you click a link in the WebView, it starts the default web browser to view the new page instead of displaying it in the WebView itself. There are several customization points where you should add your own behavior.
Second, it’s always a good practice to show the user which page is being viewed and whether the page is loading or loaded. Create and set your own WebChromeClient and WebViewClient to add these functions.
(3) Get the token via cookie/title
After the site finishes the authentication, it will redirect the page to a success page, in which the token is contained. The site may use the cookie or page title to deliver the token. For instance, when the success page is loaded, a cookie is set like ‘oauth_token=YOUR_OAUTH_TOKEN’. You can check the cookie each time a page is finished. If the ‘oauth_token’ cookie is found, you can extract the token from the cookie and return it to the calling activity. The following sample code shows how to detect and extract the token from the cookie.
If the site delivers the token by page title, you can get the title string by WebView.getTitle(), and extract the token from the title string.
After the WebViewActivity destroys itself, the workflow is return to the calling activity. Since the WebViewActivity is called by startActivityForResult, the calling activity’s onActivityResult() callback will be called. Here’s the example:
First, when you create your main activity, create a CookieSyncManager with the application context also.
Then, in your WebViewActivity, you can start the sync process when WebViewActivity is resumed and stop the process when it is paused. The CookieSyncManager will start up another thread to sync the cookie between RAM and permanent storage periodically. You can also force the sync manually instead of waiting for the timer to trigger, for instance, in WebViewClient.onPageFinshed().