20

The OAuth2 spec describes the Resource Owner Password Credentials grant type and authorisation flow here. I understand that only 'trusted' client applications would be allowed to use this grant, for example the 'official' iPhone or Android client application to by backend API.

My question is: how can I guarantee that requests from sources claiming to be this client application can be trusted? For example:

  • I have registered my android app on my OAuth2 server with the client_id of android_app with access to the grant type of password (i.e. Resource Owner Password Credentials).

  • As the Android app is a client application so I have assumed it is not trusted to keep the client secret 'secret' and so haven't assigned it one. The app config contains the client_id and grant_type as well as the authentication endpoint.

  • A user decompiles / unzips / de-obfuscates my app and finds the client_id and endpoint

What's to stop them client making authentication requests to that endpoint with the client id? I'd consider assigning the client a client_secret, but it just seems like that won't solve the issue because a user could just find it in the app.

3 Answers 3

11

These are really two questions.


How can I guarantee that requests from sources claiming to be this client application can be trusted?

You can't. The specification says:

The resource owner password credentials grant type is suitable in cases where the resource owner has a trust relationship with the client [...]

The resource owner (aka. user) has to decide if he trusts the client, not the authorization server. If the user decides to trust a third-party app so much that he enters his plain password, you can't automatically detect if the third-party app is trustworthy.


What's to stop them client making authentication requests to that endpoint with the client id? I'd consider assigning the client a client_secret, but it just seems like that won't solve the issue because a user could just find it in the app.

OAuth2 differentiates between confidential and public clients. Confidential clients are "capable of maintaining the confidentiality of their credentials", for example a web application which access another on server-side.

Native applications (like an Android app) are mentioned explictly as public clients:

A native application is a public client installed and executed on the device used by the resource owner. Protocol data and credentials are accessible to the resource owner. It is assumed that any client authentication credentials included in the application can be extracted. [...]

Therefore a client secret won't add security to a native application in most use cases.

4

How can I guarantee that requests from sources claiming to be this client application can be trusted?

You can't.

To quote another SO answer:

The thing is though, in mobile, the application is already trusted, once the user has installed the application he has chosen to trust it [...] Ultimately I don't think that it's possible to completely protect users from an application once they've decided to trust it by installing it.

What's to stop them client making authentication requests to that endpoint with the client id?

Nothing.

You can only focus on protecting your users' username/password, for instance:

  • don't store them inside your app.
  • educate your users with clear explanations on where to get your official apps and why they should not trust any other app asking for they credentials.

A little explanation:

In order to access resources, an app needs to obtain an access token (and eventually an optional refresh token).

To obtain the access token a first request including the username and the password has to be sent to the endpoint. Note: the client_id and client_secret are only mandatory for confidential clients or for any client that was issued client credentials.

So the malicious app can't access any resource until it obtains the username and password, otherwise it won't be able to obtain an access token. Even if it uses the identity of your official app.

5
  • 3
    Downvoter, could you explain why ?
    – thomas.g
    Commented Aug 15, 2014 at 6:42
  • I believe what you are describing is the authorization code grant type, which is different from OP's scenario.
    – 0leg
    Commented Oct 2, 2014 at 20:18
  • That's because in Resource Owner Password Credentials grant, which is the grant type the OP asked about, the resource owner first has to provide username/password to the client in order that the client requests an access token... see tools.ietf.org/html/rfc6749#section-4.3 and tools.ietf.org/html/rfc6749#section-10.7
    – thomas.g
    Commented Mar 1, 2015 at 8:41
  • Question was: "how can I guarantee that requests from sources claiming to be this client application can be trusted?". End of my answer is a quote saying "The thing is though, in mobile, the application is already trusted, once the user has installed the application he has chosen to trust it [...] Ultimately I don't think that it's possible to completely protect users from an application once they've decided to trust it by installing it.". It clearly answers the question. But if you want, I can edit and write: "You can't, users have to be careful . And don't store the credentials in the app"
    – thomas.g
    Commented Mar 2, 2015 at 10:21
  • I've edited the answer so that the questions are answered more directly. Thank you for your feedback.
    – thomas.g
    Commented Mar 3, 2015 at 9:56
2

The provided example is actually a really bad example for the exact reason you mentioned -- an attacker can just extract the client secret and impersonate the client.

The security of this grant relies on how well that client secret can be protected. Further, it relies on how well the channel can be protected, such that an attacker can't create a man in the middle and extract the secret from the request. If you can protect both of these then you're in a pretty good spot, but thats really difficult to do for mobile apps.

To answer your question: you really can't. You can mitigate some of these problems by:

  • using unique client IDs and secrets for each instance of the application, but that seriously complicates management
  • or you can store the secrets in a trusted hardware store, but the protocol requires the secret verbatim
  • or you can modify the protocol to use a token-based client identifier like using a JWT or SAML token signed by the client secret, that way an short-lived assertion signed by the secret is passed instead of the secret, etc.

Add all of those together and you have a pretty solid way to identify the client, but its certainly not foolproof and it definitely has its drawbacks: manageability is a PITA, how do you do the initial secret exchange?, etc.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .