Protect my public oauth API from abuse, but allow

2019-05-26 18:51发布

问题:

I have a website and an API. The website allows anonymous people to browse the catalogue, but you must be logged in to post stuff.

I have built an API that exposes the same functionality. The API is used by a mobile app we are developing, but we are also going to allow other developers to use the API (i.e. it's publicly documented). The entire API is currently requires OAuth (2.0) authentication. To prevent abuse we use rate-limiting per OAuth client-id/user-id combination.

Now a new requirement for the mobile app has come down: The app should allow anonymous users to browse our catalogue. I am not sure how to implement this, without opening up our API to abuse.

Anonymous OAuth access

The first problem is allowing anonymous access. If we still want the entire API protected by OAuth then our mobile app will have to use the client-credentials grant type (posting a client-id and secret key). But we would have to store the client-id and secret in the app itself. This is not secure since it can easily be reverse engineered.

Alternatively, we could use dynamic client registration. As soon as an app is installed, it registers with an (undocumented) API to create an OAuth client for itself. Problem here is, how do I protect the client registration endpoint? A secret key again? Plus, this leads to a large amount of OAuth clients registered.

Remove OAuth from public endpoints

Alternatively, we could remove OAuth from the public endpoints all together (i.e. browsing the catalogue) and only require OAuth for posting stuff or managing an account. But how would I protect the API from abuse then? Without OAuth I cannot rate-limit based on client-id.

I am not sure that rate-limiting based on IP address would work. We expect many mobile app users and I fear that crappy (Moroccan) mobile telecom providers are NAT-ing a large amount of phone users behind just a few IP addresses. This would quickly exhaust any rate-limit that we set.

Is this correct? Or can I safely rate-limit on IP address for mobile users?

Alternative security mechanism

I could also implement a different authentication mechanism alongside OAuth. Something that allows our mobile phone app access to the API, which can distinguish (and rate-limit) different phones/users but which is safe from people just extracting a shared secret key from our mobile app binary.

Any suggestions on how to allow anonymous access to my API but still rate-limit effectively?

回答1:

Since, the mobile app is installed on a device, if you configure a secret, then that secret will be common for all installations of the mobile app. Thus, derailing the purpose of a secret.

You should do dynamic registration. Here are the steps

  1. Developer preconfigures the the following information with a trusted authority.

 {
 "software_id":"COMMON_VALUE_HERE",
    "software_version": "OPTIONAL_BUILD_VERSION",
    "client_name":"HUMAN_READABLE_CLIENT_NAME",
    "client_uri":"OPTIONAL_FOR_CLIENT_CREDENTIALS",
    "logo_uri":"OPTIONAL_FOR_CLIENT_CREDENTIALS",
    "tos_uri":"OPTIONAL_TERMS_OF_USE"
}

  1. The trusted authority generates a "software_statement" in exchange of the information that the developer provided. This contains the information that is constant for all installations of the native app.

  2. After the app is installed on the user device, the app contacts the Authorization server for dynamic registration. The app posts the following to Authorization server

{
"redirect_uri" : "OPTIONAL_FOR_CLIENT_CREDENTIALS",
"scope": "SPACE SEPARATED SCOPES",
"software_statement": "MANDATORY"
}

  1. The Authorization server verifies the information present in the "software_statement", generates and returns back a "client_id" and "client_secret" that are specific to the particular installation of software.

  2. The client calls "POST" method on token endpoint with the newly received "client_id" and "client_secret", and receives an "access_token".

  3. The client uses the "access_token" for accessing the "protected_resource".

The source of my answer is "oauth 2 in action" by Manning publication.