3

We're currently in the process of implementing OAuth2 to secure our new API and not sure how to securely provide required functionality. We need to allow the following from a mobile device:

Immediately after downloading the app the user is able to take a picture and submit it without having to first log in.

While we want to allow anonymous user access, where a user does not need to log in or register to use certain functionality, we do not want to allow unauthenticated access to the API. This would normally be accomplished using the client credentials authorization flow to obtain and app access token, however this requires knowing the client secret. From what I've read, a mobile device is not considered a trusted client and should not contain the client secret, and hence should not be able to generate an app access token on its own.

We've come up with a few options to accomplish this requirement, but would like some input on them:

  1. Embed the client secret in the app. Doesn't seem ideal from a security standpoint, but maybe we're missing an obvious way to secure it? We're targeting at least iOS and Android.
  2. Generate an app access token offline and embed that in the app. Still not very secure, but at least the secret isn't exposed.
  3. Allow access to certain functionality using only the client ID instead of an access token. This may be the simplest, but it introduces an inconsistency and requires multiple ways of authenticating the client.
  4. Build and use a companion web app to generate app access tokens for the mobile app. On the surface seems like a winner, but now you have to secure access to the companion app!

How would you securely authenticate access to an API using OAuth2 from a mobile device without requiring the user to first log in?

Community
  • 1
  • 1
John Clayton
  • 1,081
  • 1
  • 9
  • 21
  • What exactly are you trying to "secure"? You are not trying to authenticate the user because you have stated anonymous access. Are you trying to authenticate the client app? Trying to communicate over an encrypted connection? "Secure" is a little bit vague. – Fantius Dec 05 '11 at 17:32
  • Maybe 'secure' wasn't the best term. What we don't want is anonymous access to the API - we want to know which app is making the request. What we do want is to allow apps to make requests without the user needing to log in. I'll update the question to try to clarify. – John Clayton Dec 05 '11 at 17:39
  • Then the app needs to have some secret that nothing else has. That's the only way to do it. If something gets that secret, it can impersonate the app. – Fantius Dec 05 '11 at 19:15
  • Hi John, sorry to revive an old post of yours, but I'm dealing with the same issue. What route did you end up taking? Or did you at least find some ways to make the reverse engineering very difficult – Michael Jun 04 '13 at 21:45

2 Answers2

2

My group is having a similar discussion. Users can get the app and browse a catalog without having to sign-in. The catalog and other data is accessed via an API and we would like to force users to have an access_token for all calls.

Our current thinking is to

  • Always force the App to exchange a common clientId/secret for an access_token. So the app would get an access_token even for anonymous users. This would be via the client_credentials oAuth flow.
  • If the user signs in, use the oAuth password flow. They would pass in clientId, secret, username, and password. We would additionally allow them to pass in their anonymous token so that we could transfer any history from their anonymous session.

So for example...

access_token = api.oAuth.client_credentials(clientId, secret)
catalog = api.getCatalog(access_token)
authenticated_access_token = api.oAuth.password(clientId, secret, username, password, access_token)
Michael Connor
  • 4,182
  • 24
  • 21
2

Agree with the comments on the Q. Either:

1.) Use Client Credentials grant type in OAuth 2 - with an embedded secret in your App. Understand that this isn't super secure and someone will reverse engineer it eventually. Ideally each client would get a unique secret - so you could revoke a client if they're abusing its use.

2.) Live with that API being open - thereby not requiring an OAuth 2 access token at all. Maybe that API would be known only to your app - but again, it would only be a matter of time before someone reverse engineers it.

Scott T.
  • 6,152
  • 1
  • 26
  • 32
  • Seems like embedding an app access token would be marginally better than embedding the app secret? Leaving the API open without any authentication isn't an option. We need to know who is using the API. – John Clayton Dec 05 '11 at 22:44
  • Access tokens are typically short lived (based on time). Is your thought to only allow this API for X # of minutes/hours after the user installs it / before they properly login? If not - then you may mean a "refresh token" - which is longer lived (usually user revoked), and can be exchanged for access tokens. If I were you - and if you can - try to embed unique client_id / client_secret's in your app, and only permit these clients to call this particular API (i.e.: its OAuth scope only allows this operation). Ensure you have a means to monitor for abuse / revoke these clients server side. – Scott T. Dec 05 '11 at 22:51
  • We ended up going to option 1, even though a HTTPS-capable inspector was able to instantly reveal the client ID & secret. If the secret absolutely must be kept secret OAuth 2 is not the way to go. – John Clayton Jun 05 '13 at 23:59