I spent the last few days running OAuth. Not on Android, but on my web server, which will act as a proxy for the OAuth security service. I'm going to implement my Android client, and my head is still worried about security and implementation issues.
OAuth is dirty enough when the client is just a web browser. You have the following steps:
- (client web browser) makes a request to my proxy server
- (proxy server) requests an unauthorized token from the OAuth provider (for example, the web service API).
- (proxy server) ask the OAuth provider to authorize this token. Redirecting a web browser to a URI of a URI authorization provider
- (OAuth provider) after the user logs in, redirects the browser to your callback URI
- (proxy server :: callback URI) Exchange authorization locator for access token, and then save it for future calls
- Make API calls for the OAuth provider and return the response document to the client’s web browser.
Now that’s enough. But when using the same mechanics with a mobile application as the client, it becomes even more attractive. The problem, of course, is that you need to do some acrobatics to inject a browser session into the stream of your mobile application, performing OAuth dances. This means that you need to further complicate the OAuth dance as follows (I use the Android application for this example to make things specific):
- (mobile web application: native code) makes a request from a proxy server using Java / HTTP
- (proxy server) requests an unauthorized token from the OAuth provider (for example, the web service API).
- (proxy server) returns a response document to a mobile web application containing a URI redirect to authorize the user with the OAuth provider, preferably confusing, to hide the consumer key and other data to restrain over-the-air tracking.
- (mobile web application) Run a web browser action with an authorization URL with the intent filter set. However, save and then replace the specified proxy callback URI with a special "fake" URI created for the convenience of identifying the URI using an intent filter (see the following steps).
- (OAuth provider), after the user completes the authorization, redirects the browser to your "fake" callback URI.
- (mobile web application) The intent filter detects a “fake” callback URI and uses this signal to regain control. Reinstall the proxy callback URI and use Java / HTTP to execute the request.
- (proxy server :: callback URI) Exchange authorization token for the access token, and then saves it for future calls, as before
- Make API calls to the OAuth provider and return the response document to the mobile web application.
This is pretty disgusting, as you can see. If there is a much easier way to do this, I really want to hear it. As far as I know, there are only two alternatives, each of which has its own serious problems.
1) Forget about the proxy server and do everything directly from the mobile web application. The big security hole here is that you must “bake” your user key and OAuth secret key in your application. If an attacker decompiles your code and hunts for these lines, this is a fairly simple operation for those who have experience with reverse engineering, they can harm your application and users.
2) Switch to XAuth, where the user will provide you with their username and password, and you “agree” not to store them and exchange them directly for the access token with the XAuth server. The first problem is gaining the trust of users to provide this information, the OAuth problem was created to solve, and, of course, what about people who do not comply with their obligation to refuse registration data? Even worse, the XAuth server must support XAuth and offer HTTPS (SSL) connections, and I have seen many web APIs that also do not support. Of course, an SSL connection is required because without it, you send the username and password of the user over the wire in plain text when you execute your XAuth request.
http://blog.zyber17.com/post/1283741364/why-xauth-is-a-really-dumb-idea
FYI, although it does not use a proxy server, the following example illustrates the above method for entering a browser session into your interaction with the OAuth of your mobile application and intercepting the callback URI:
http://blog.doityourselfandroid.com/2010/11/10/oauth-flow-in-android-app/
So it seems pretty ugly no matter what you look at it, and I didn't even get into the additional annoyance of creating and managing your own user ID for the user so you can look for your access tokens stored on your proxy server (including clutter another PIN or user access code).
An interesting note: when conducting some research on the security of the session of the Android web browser, I was glad to know that you are not allowed to access the current HTML page of the web page. If you could access it, then a hostile Android-encoder could easily sniff out the user's login and password, thereby completely defeating the goals and intentions of OAuth. I was alarmed to learn that there might be a way to get this HTML through a CacheManager object. It is curious that the object is now outdated and plans to delete it in accordance with Android documents, so I hope this means that Google has detected a (potential) security hole and is taking steps to delete it in the upcoming build:
http://developer.android.com/reference/android/webkit/CacheManager.html
In conclusion, I would like to hear the thoughts of those there who struggled with the same problems when creating their OAuth applications.
- roschler