IETF submitted a draft on the best approach to implement OAuth in a mobile native app. They recommended a specific flow and some security considerations.
I am going to show how to implement these in the code on both mobile platforms iOS, and Android using Facebook authentication service as an example of OAuth provider, and then show how Facebook and Google SDK for those platforms are implementing this apporaches.
This is not an OAuth tutorial, so I am assuming that you are familiar with OAuth terminologies and workflows.


The security considertations for native app

IETF submitted a draft on the best approach to implement OAuth in a mobile native app, and in that draft IETF made the statement that:

OAuth 2.0 authorization requests from native apps should only be made through external user-agents, primarily the user’s browser.
This practice is also known as the AppAuth pattern, in reference to open source libraries that implement it.

In order to statisfy the previous statement and to provide more solid, security solution for OAuth on native app, IETF provide the following security considertations:

  • Don’t use embeded user agent like web-view, because the native app can capture user credentials when entered on OAuth website.
  • Register your application with the OAuth provider and specify it is a native app.
  • It is not recommended to use OAuth implicit flow with a native app.
  • Don’t store your application secret (which you obtain upon registering your application) in the code. There is a work around to use your secret when required which we are giong to see later.
  • Most OAuth providers provide the parameter state in their service to protect against CSRF attacks.
  • If you are building your own OAuth authentication services, then make sure the HTTP redirect address will have the application identifier as schema of the URL, which we are going to show it later.

AppAuth or Authorization Code Flow

Section 4.1 in that draft shows the authorization flow of the AppAuth approach and it is very similar to Authorization Code Flow. Don’t worry about getting its details, because I am going to describe them later:

+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
|          User Device           |
| +---------------------------+  |                     +-----------+
| |                           |  | (5) Authz Code      |           |
| |        Client App         |----------------------->|  Token    |
| |                           |<-----------------------|  Endpoint |
| +---------------------------+  | (6) Access Token,   |           |
|    |              ^            |     Refresh Token   +-----------+
|    | (1)          | (4)        |
|    | Authz        | Authz      |
|    | Request      | Code       |
|    v              |            |
| +---------------------------+  |                   +---------------+
| |                           |  | (2) Authz Request |               |
| |          Browser          |--------------------->| Authorization |
| |                           |<---------------------| Endpoint      |
| +---------------------------+  | (3) Authz Code    |               |
|                                |                   +---------------+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+


I am going to re-represent the same flow in the previous diagram with a more graphics in a simpler diagram that anyone can understand (including me).

smtp


I am going to implement that using the Facebook Authorization service as an example of the OAuth provider. But, I am just showing this as an example, becuase in real life if you want to connect using Facebook, then I recommend using Facebook SDK for iOS and Android, and not using my code. Anyway, my code is going to be conceptual steps that show only the exact step implementations, and not a whole application.


step 1 & 2: Request Auhorization

In this step we are going to launch the external web browser with URL of the Facebook Authorization EndPoint:
The Facebook Authorization EndPoint is:

https://www.facebook.com/v2.8/dialog/oauth?
  client_id={app-id}
  &redirect_uri={redirect-uri}
  &state={state}
  &response_type=code

The parameters are as follows:

  1. redirect_uri is the URL that you want to redirect the process back to. For a native app, the redirect url should be special which we should see how later.
  2. state: is an arbitrary unique string that is used to protect against CSRF.
  3. response_type: has many options, but for our AppAuth it is proper to use “code”.

Launching the browser from the native code.

 // For Android:
// ---------------------------------

AppUri authzUrl =Uri.parse("https://www.facebook.com/v2.8/dialog/oauth?client_id=xxxx&state=abcd&response_type=code");
Intent launchBrowser = new Intent(Intent.ACTION_VIEW, authzUrl);
startActivity(launchBrowser);


And for iOS:

 // For iOS:
// ---------------------------------

NSString* launchUrl =@"https://www.facebook.com/v2.8/dialog/oauth?client_id=xxxx&state=abcd&response_type=code";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: launchUrl]];

Facebook will direct you to enter your credentials, and then ask you to allow the application to access your token.
When the user confirm the authorization server will respond with HTTP redirect like the following:

HTTP/1.1 302 Found
Location: my-app-id://oauth.callback?code=the-code-returned-by-service

pay attention to the shceme in the URL: my-app-id:// which we are going to talk about in the next step.
Let’s move to step 3 & 4.

step 3 & 4: Authorization endpoint response

In Step 4 we should return back to the App from the external browser. The most common way is to use Custom URI Scheme.
Custom URI Scheme is a technique used in both iOS and Android to support inter-app communication, so app1 can communicate with app2 by launching a request like this:

app2://some-page-and-parameters

So, now let’s see how to define custom URI scheme in both platforms.

In Android we create an activity that will handle the redirect by defining its intent-filter to respond to BROWSABLE activites. the code will be similar to this:

<!-- android -->
<activity android:name=".my-activity-handler">
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="my-app-id" />
  </intent-filter>
</activity>



In iOS we define the custom URI Scheme in the plist file:

smtp

and in the application delegate file we write a handler for application:openUrl

 // For iOS:
// in AppDelegate.m
// --------------------------------

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
{ 
  NSString *queryString = [url query]; 
  for (NSString *param in [queryString componentsSeparatedByString:@"&"]) { 
    NSArray *keyValuePair = [param componentsSeparatedByString:@"="]; 
    if([keyValuePair objectAtIndex:0] isEqualToString:@"code")
    {
      // continue with authorization code in [keyValuePair objectAtIndex:1]  //
    }
  }; 
}



step 5 & 6: Trading authorization code with the token

The final step is to communicate with the Token Endpoint and send the authorization code received from the previous step.
To do that in Facebook, we call Facebook Token Endpoint as follows:

GET https://graph.facebook.com/v2.8/oauth/access_token?
   client_id={app-id}
   &redirect_uri={redirect-uri}
   &client_secret={app-secret}
   &code={code-parameter}

Now there is a huge problem with this, because it requires the client secret, which is something that you should never use from your native code, becaues someone can hack it and get it.
It is highly recommended to call this service from a back-end server, so you might have to have a back-end server.
P.S: You can build a simple server component with a perse-server and host it on Redhat openshift free cloud servers.
So, we will assume that we have a back-end server that will call this for us, and we have to call it passing our authorization code we received from previous step, like this.

GET https://my-token-service?code={code-parameter}

To call this service in iOS:

 // For iOS:
// --------------------------------
NSMutableURLRequest *request= [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL: [NSURL URLWithString:@"https://my-token-service?code=xxxx"]];

For Android

 // For Android:
// ---------------------------------
DefualtHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet("https://my-token-service?code=xxxxx");



Final statment

Just reminder that the code above was conceptual to describe the process in more practical way. If you are going to use Facebook OAuth, then it is way easier and better to use Facebook SDK.