简体   繁体   中英

Designing an API with designated client keys

I'm designing a JSON web API and want to distinguish clients by unique IDs, in order to monitor usage and block malicious/misbehaving clients. The API is NOT encapsulated in a JavaScript library and NOT exclusive to web apps, any client type can use it (desktop, phone, etc.).

The problem is, that the web app (official website) is also a client of the API itself , thus would have to expose its API key. As a result, some user could just extract the key from the JavaScript on the page and use it, instead of generating his own key.

Is it possible to mitigate this problem somehow with some better/smarter design choices, or do I have to live with the fact that anyone using the API in bad faith can exploit this?

I have 100% control over the frontend app (EmberJS) and backend servers (Go), so any alternation can be suggested.

  • I'm using rate limiting per session/ip to add an extra protection layer for that case
  • The twitter.com page was once also a client of its own API. How did they solve that?

Note: The question is not about authentication or security itself, but how to require 3rd party users to use an API key in addition (!) to authentication!

You should distinguish between web and non-web clients. An access key for web cannot be used in non-web and vice-versa. For web clients, you can do referer checking etc. You could also dynamically create access keys for your application and automatically change them daily (or every session). You can also add some special verification for your app only, eg some additional key that is calculted by obfuscated JS.

Nothing can prevent a malicious user to emulate a browser, execute the JS, manipulate that, and then do bad things - but you can make it annoying enough that they decide it's not worth their effort. Really important things like permissions etc. obviously need to be checked server-side, so abusing your API should not be much of a problem. You will have to treat API abuse via your site's API key the same as you do with regular web app abuse - IP blocks etc.

You still need to keep API keys for non-web clients secret. This can only be done unreliably by obfuscation, which you can leave at the hands of the client developer. If their key gets leaked and abused, you revoke it, and they will be motivated to fix it.

Have a look at OAuth 2.0 , they impelement many features that could be useful for you. Even if you don't want to use it, you can take some inspiration from it. OpenStreetMap uses OAuth (not sure if 1 or 2) for their flash-based editor; as long as it is called from the same origin by a logged-in user, the OAuth permission granting is done automatically. For third-party apps, the user needs to do it manually. You may want to check that out.

You will not be able to make your API secure just using a single API key. The API key you are describing is basically a public key and you will need some type of private key for secure identification/authentication and a mechanism to deliver it.

You asked how Twitter got around this issue. They use Oath 1.0a. Here is brief description of how it is tied to the API key from a Twitter Developer FAQ .

Most integrations with the API will require you to identify your application to Twitter by way of an API key. On the Twitter platform, the term "API key" usually refers to what's called an OAuth consumer key. This string identifies your application when making requests to the API. In OAuth 1.0a, your "API keys" might refer to the combination of this consumer key and the "consumer secret," a string that used to securely "sign" your requests to Twitter. Most requests to Twitter require a user context in addition to the application context. User context is presented through the use of another kind of token/key called the "access token." See Obtaining access tokens for more information.

You can find a lot of great resources on designing API's at Apigee.com . They recommend using OAuth 2.0 for authentication/authorization.

Here is a description on how to use HMAC authentication to secure a Web API .

I have used a workaround for my web application when I have had to use API's that only used an API Key. I do not access the API directly from the client-side portion of the web application (ie JavaScript in the web browser). Instead I access the API server-side and store the API Key encrypted in a secure configuration file. I provide a Facade to the original API and use my own security methods to secure the Facade API that are dependent on the type of application.

General API workflow:

  1. client sends a request
  2. request is authenticated and authorized
  3. data is sent back

Web Site - log in

  1. user logs in providing a username and password
  2. A secret is created and stored into a coockie

Web site - API access

  1. client sends a request
  2. request is authenticated and authorized based on coockie's secret (coockies are sent with the request)
  3. data is sent back

Non WEB client - obtaining an API KEY (long random alpha numeric string)

  1. Option 1 - User registers a client on the website, gets an API KEY and stores it into the client
  2. Option 2 - User enters username and password into the client, the client requests an API KEY with usenamer and password, the key is returned and stored into the client. Username and Password are not stored on the client.

Non WEB client - API comunication

  1. client sends a request with API KEY
  2. request is authenticated and authorized based on API-KEY
  3. data is sent back

When the key is generated with option 2 you can get some additional data since it originates from the client (operating system, browser). In this case when checking the API-KEY you can force a user to generate a new one if, he changed OS or Browser

The key point is that your API authenticates requests in two ways. Using coockie's secret or an API KEY. Therefore there is no need to expose the API-KEY on the website.

Note that for clients using an API-KEY there is no session involved. Each request is authenticated only by the API-KEY. So those clients are considered non WEB app.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM