Advice for Operating a Public-Facing API

best-practices csharp aspnetcore

Host the API on its own hostname

  • Serve your API at api.example.com, never at example.com/api.

  • It means that it can have its own TLS certificate and TLS restrictions.

  • When it comes to blocking bots and poorly-written clients, a user should still be able to reach your main website for support even if their IP is blocked from reaching your API server.

Don’t be too liberal in what you accept

  • Don’t accept any non-conforming request.

  • Keep a message size limitation.

  • If you allow a non-conforming request once, you will have to allow it forever.

  • Validate hard.

Avoid OAuth if you can

  • With OAuth your API can’t be used from a simple curl request but has to be a custom multi-step process pulling in a whole OAuth library.

  • Use static API tokens if you can, but make it easy to rotate them.

  • If possible, avoid using an authentication mechanism that requires custom HTTP headers (including basic auth) because some esoteric devices and plugins don’t support them.

  • Remember, not everyone is going to be sending HTTP requests from the ideal code you would have written, they’re using what they have available.

Log a unique id with every request

  • Generate a unique ID or UUID with every request, return it to the user in the message body.

  • Log it, and ask for it on your support form.

  • Easier to track down requests in log files and correlate them to a user’s support request.

Be descriptive in your error responses

  • Assume a human will read them.

  • Have your API errors include URLs to documentation to avoid support requests.

Use prefixed tokens

  • Use a short prefix for each type of random ID you create.

  • Instead of generating an API token of Mk7vuCg9eptiV8qid4mn, make it appMk7vuCg9eptiV8qid4mn. Instead of a user key of zo2iD3x3J9, use userzo2iD3x3J9.

  • Makes it easier for users to keep multiple keys/tokens straight.

  • Makes it possible to automate helpful API error responses like "your token parameter has a user key instead of an API token".

Stay on top of failures

  • Instant alerts of 5xx errors from your API when your database falls over.

  • generated in response to missing required parameters, expired tokens, and other conditions that you don’t normally need to worry about.

  • Block IPs if a certain 4.xx request error threshold is reached like say 1.5 million per hour. And send an email to the client who is causing this with a reason for blocking the IP.

References