Monday, December 12, 2011

Callback security in mobile OAuth 2.0

OAuth 2.0 defines how mobile native applications can obtain an access token from an Authorization Server – this token used on calls to the API behind which sits the application data (e.g. their calendar, their TripIt data , etc) that the native application seeks.

Obtaining the first access token typically happens via the browser – the sequence

1)    The user indicates they wish to ‘authorize the app’ or equivalent
2)    the native application pops an external browser window and loads the AS login page
3)    the User logs into the AS (and may be asked for their consent for that native application to be able to access particular resources)
4)    if successful, the AS redirects the browser to a specified callback URL, including in the redirect URL an ‘authorization code’
5)    The browserpasses the authorization code to the native application
6)    The native application sends the authorization code back to the AS, and is returned the desired access token (as well as optionally a refresh token, which the native application can use going forward to get new access tokens)

Step 5 in the above might have caused you to wonder just how exactly does the browser, after grabbing the code from the callback URL, pass it to the native application?

Good question.

One emerging best practice is to leverage the mobile OSes (Android & iOS at least) support for custom schemes as a means of inter-application messaging. When the native application is installed, it registers itself as the handler for URLs of a particular scheme (just like the browser handles HTTP URLs, and the markets have their corresponding schemes).

Below is the Android manifest for an app registering itself as the handler for the 'coolmobileapp' scheme.

<activity android:name=".AppActivity" android:label="@string/app_name">
            <intent-filter>
                <data android:scheme="coolmobileapp" android:host="cma.ex.com" /> 
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.BROWSABLE" />
                <category android:name="android.intent.category.DEFAULT" />  
            </intent-filter>
</activity>


Once registered as a handler for a given scheme, whenever the OS sees a URL in that scheme, it will pass that URL to the application.

If then, the callback URL that the AS redirects the browser to belongs to a scheme that the relevant native application ‘owns’, then the browser, upon seeing that URL, will pass it onto the OS for appropriate forwarding to the app.

Once the native application is passed the URL, it can grab the authorization code, and use it to obtain the desired tokens.

The hitch in the above mechanism is that nothing prevents multiple native applications from registering themselves as the handler for a given URL scheme. If you have multiple browsers installed on your phone you will have seen how Android deals with multiple such handlers – it asks the user which to use for a given URL (unless a default is set). Nothing in the OS prevents such collisions, nor mediate conflicts other than this user query mechanism.

Consequently, it is theoretically possible for a rogue application to lay claim to the very same custom scheme handler as a valid native app with the hope that it would obtain the authorization code as part of the OAuth authorization process rather than the valid & appropriate app.

In the next installment, I will present ideas as to how to mitigate the above callback attack - based on discussions with my Ping colleagues Scott Tomilson, Travis Spencer, and Brian Campbell (to be fair, Brian has contributed very little).