0

Following up on the design outlined in Design for Facebook authentication in an iOS app that also accesses a secured web service, and specifically the concern listed in https://stackoverflow.com/a/12912616/5154090: what would be the mitigation?

Specifically, I have a web server that exposes a REST API which is consumed by a mobile app. I'd like users to authenticate to the server (via the app) using Facebook.

Now, an apparently common flow is for the app to redirect the user to Facebook, where they will login with their credentials. The app will then get a token which it will send to the server, and the server will validate the token using the graph API.

But how can the server make sure that the token really came from the app? Specifically, what's to prevent a malicious app vendor from re-using my app ID? After all, the app ID is hardcoded into the app and can therefore be extracted and used by a malicious app. If users log into that malicious app with Facebook, then the malicious vendor can get tokens with my app ID and can impersonate users of my service.

How can one protect against this?

Community
  • 1
  • 1
YSK
  • 1,572
  • 10
  • 19
  • https://developers.facebook.com/docs/facebook-login/security – CBroe Apr 10 '17 at 08:06
  • @CBroe thank you for the link. Haven't watched the video yet (will do so later), but from a brief read I don't see there an answer to my question. Indeed, they say that `access tokens should never be assumed to be from the app that is using them, instead they should be checked using debugging endpoints` but the linked page indicates that the app ID is used for this verification. Perhaps the implication is that these access tokens should not be sent to servers? – YSK Apr 10 '17 at 09:04
  • No, sending them to the server is fine. Especially since for server-side requests you can activate additional security measures, such as requiring the app-secret proof. – CBroe Apr 10 '17 at 09:47
  • @CBroe Can you elaborate how appsecret proof helps here? As I understand it, it is a means of proving to Facebook that the server has the app secret. But I'm focusing on proving to the _server_ that the _user_ authenticated to my app. I agree with you that tokens can be sent to the server; I guess I should have said that access token should not be sent to servers _for the purposes of authentication_ ? – YSK Apr 10 '17 at 10:34
  • _“But I'm focusing on proving to the server that the user authenticated to my app”_ – you send the token to the server, and debug it. If it does not belong to your app, you’ll see at this point. – CBroe Apr 10 '17 at 10:36
  • @CBroe I understand that the debug API retruns the app ID and that I can compare it my own app ID. But anybody can decompile my app and extract the app ID from it. My question is what happens if another, malicious app uses _my_ app ID to authenticate _its own users_. Won't that app obtain tokens that it can send to _my_ server? How can my server tell that these tokens did not come from my app, given that the same app ID is being used? – YSK Apr 10 '17 at 10:42
  • Debugging the token requires your app access token, or a user token from an app developer. – CBroe Apr 10 '17 at 10:44
  • @CBroe But the server has the app access token, doesn't it? Sorry if I'm being dense, but what would be the difference between: 1) a token legitimately generated by my app; and 2) a token generated by a different app that uses the same app ID (which the author presumably obtained by decompiling my app)? It seems to me that these two tokens would be equivalent and the server won't be able to tell them apart. – YSK Apr 10 '17 at 10:49
  • Other apps can not just use your app id. And if they did, the user would still have granted permissions to _your_ app. – CBroe Apr 10 '17 at 10:54
  • @CBroe what's stopping other apps from using my app ID? Isn't it just a string that's hardcoded into the app? I'm assuming malicious apps here. And if these malicious apps implement the same login flow that I'm implementing in my app, but use _my_ app ID, then they will obtain tokens that my server will also accept. No? – YSK Apr 10 '17 at 10:57
  • For example the various settings that you have to make for each platform, stop them - in general. But if someone else managed to use your app id in their code, the user would still log in to _your_ app - _because_ your app id was used. – CBroe Apr 10 '17 at 11:00
  • @CBroe can you elaborate what settings you're referring to? And re. "the user would still log in to _your_ app" - my concern is that the malicious app will obtain a token that it can then use to authenticate with my server. – YSK Apr 10 '17 at 11:10
  • Website URLs, Valid OAuth Redirect URIs, package names, ... – CBroe Apr 10 '17 at 11:11
  • @CBroe are they used as part of the "standard" login process? I missed that; guess I'll have to read more... – YSK Apr 10 '17 at 11:23
  • @CBroe So having read a bit more, I still think spoofing the app ID should be easy. The Facebook SDK only requires the ID and nothing more. Other settings such as OAuth URIs don't seem to come into play as part of the standard, app-based login. It seems there's no way the server can tell whether the token was generated by a malicious app or a real one. All it can do is find the app ID that was used, but anyone can spoof it. I believe the only secure way to have a server authenticate via Facebook is with true OAuth. – YSK Apr 11 '17 at 12:31
  • _“It seems there's no way the server can tell whether the token was generated by a malicious app or a real one”_ – yeah, but what actual difference does it make? The user logged in to an app with your app id - so all permissions they grant, are only valid for your app id as well. I don’t really see what the actual attack vector would be here ... – CBroe Apr 11 '17 at 14:50
  • @CBroe In the [original question I linked to](http://stackoverflow.com/questions/4623974/design-for-facebook-authentication-in-an-ios-app-that-also-accesses-a-secured-we) the proposed design was as follows: 1) App authenticates user through Facebook and obtains a token; 2) App sends the token to the server; 3) Server verifies the token using the app ID, extracts the username/email from the token and _considers this a successful login of the user to the server_. I believe this flow is broken as an authentication flow (to the server) because a malicious app/website can spoof the App ID. – YSK Apr 11 '17 at 17:26
  • Again: What would that malicious app _achieve_ by doing that? The user would still log in to your app, and grant permissions to your app. The app-scoped user id would belong to your app, and name and email won’t differ either. So where is the actual attack vector here? – CBroe Apr 12 '17 at 10:55
  • @CBroe By doing this, the malicious app can log in to my server as one of my users. This will allow the attacker to carry out operations on my server on behalf of the unsuspecting user. I am not interested in the authentication to the app _per se_: I only care about the authentication to my server. If a user downloads an unrelated app, logs in to that app via FB, and then that malicious app can carry out actions on my server on behalf of that user - that's a problem. From the user's perspective, he never logged in to my service, and hasn't run my app. – YSK Apr 12 '17 at 12:49

1 Answers1

0

To summarize for anyone else who happens to contemplate this - there is indeed no way to prevent the client ID from being spoofed. This is one reason that developers are discouraged from using the OAuth implicit flow in native apps as pointed out by Andre D in https://stackoverflow.com/a/17439317/5154090:

the use of the Implicit Flow with native apps is NOT RECOMMENDED.

(see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps-09#section-8.5).

In practice, if anyone mounts this attack, then the user will download App A (a malicious app) and will then be asked to authorize App B to make actions on their behalf. As far as I can tell, this is generally the only indication that an attack is taking place.

Community
  • 1
  • 1
YSK
  • 1,572
  • 10
  • 19