6

I know that this question has been asked in various forms before. However, I'm not looking for the "use https" answer. I'm already using HTTPS and I'm not worried about the sensitivity of the payload being transmitted back and forth.

However, an iPhone application that I am working on is talking to a REST API that I have built (I have control of the application and server - so any suggestions are welcome).

I use the OAuth2 protocol for authentication, which means that my "API key" is a combination of a Client ID and Client Secret that only need to be transmitted to acquire an access_token. After that, all requests are sent to the server using the access_token and a header containing an HMAC of the request body (using the client secret as a key). The only reason for this addition was so that someone couldn't make API requests with JUST an access_token.

The API that I'm talking to is going to be made public when I release the application. So I'm not necessarily worried about others being able to make API calls to it.

What I care about is:

  • People being able to make API calls using my application's client credentials (which means that I can't detect on the server side that it didn't come from my application)
  • People being able to abuse the additional scopes that my client ID will allow them to have, and traditional API users will not have

My guess is that there's not really a solution to this problem (other than using UIWebView and making a glorified webapp) but I thought I would ask around here anyway.

Can you all think of a way to protect the client ID/client secret if it needs to be consumed by the app?

David Haynes
  • 933
  • 5
  • 14
Colin M
  • 13,010
  • 3
  • 38
  • 58
  • are you saying that oauth isn't secure enough for your app? an oauth client must sign all params, so only a client with an access token and secret can include some param _and_ sign it correctly. – danh Mar 07 '13 at 16:07
  • @danh Actually, OAuth2 doesn't sign parameters (that was part of OAuth1 which has ditched that spec). But no, I'm saying that with relatively minimal effort, someone can reverse engineer my app and get my client ID and secret, and issue requests against the API as my application. – Colin M Mar 07 '13 at 16:12
  • If you could (somewhow) grant anyone who purchases your iPhone app a unique identifier, you could link it to a single user's credentials. With that you would be able to distinguish clients that have obtained the iPhone application from those calling your API from another source. – AardvarkSoup Mar 07 '13 at 16:48

1 Answers1

7

I know this isn't the answer you were hoping for, but unfortunately I don't think you can accomplish your objectives with absolute assurance. At the end of the day, you can't trust a client which you don't control, and you don't control it once it leaves your hands.

In order to achieve your two objectives, you need to verify that the client accessing the API was written by you. The way to do this is using public/private keys pairs. You would need to embed a private key into the client that it can use to sign something. This way the server knows the request came from your client and not someone else's. This would also allow you to restrict certain calls to only your client.

However, this is not bullet-proof because a savvy user could reverse engineer and extract the private key from your app and use it to spoof the source. Although not bullet-proof, it is bullet resistant because doing that would require A LOT of work and would be highly technical, especially if you use anti-RE techniques like buffer smearing, mass red-herrings, etc.

If I were you, I would ask myself what type of damage would result if someone for sure hacked it. If you are Facebook it is catastrophic. If you are serving an internal organization it may not be a big deal at all. If you can't afford a single abuse, then you need to reconsider your design because this one isn't going to work. You simply cannot trust code that you don't control, and you don't control the client anymore once it's on someone else's device.

Freedom_Ben
  • 11,247
  • 10
  • 69
  • 89
  • Appreciate the comments. It's not really that someone could *hack* anything by getting the `access_token` (or my client ID/secret). It's just that they could make requests to the API that look like they came from me. Who knows, this may be why Facebook is distributed as a webapp. – Colin M Mar 07 '13 at 17:20
  • If you can tolerate a few requests that look like they came from you but didn't, then you should be ok to use the private/public key model, otherwise you might be stuck. I think you're right that this is why Facebook is distributed as a webapp :-) – Freedom_Ben Mar 07 '13 at 17:24
  • @Freedom_Ben, can you explain more how facebook is handling this and distributed webapp approach? or direct me to any place i can get more info? thanks – nightograph Mar 16 '15 at 18:51
  • Is it really that difficult to extract that private key if it is bundled with the app? I mean it is just to unzip the app? https://objcsharp.wordpress.com/2014/01/22/how-to-extract-the-images-from-any-app-in-the-app-store/ – hfossli Jul 23 '17 at 06:13