* Do not use passwords as API authentication. The user of an API is a computer program, not a human. Issue single-purpose random credentials for API access.]
* Make sure that your API is accessible only over HTTPS; test the API endpoint to ensure requests aren't honored over unencrypted HTTP.
* Use the simplest API authentication mechanism that (a) works and (b) you understand. You should probably degrade the capabilities of your API before you try to adopt an authentication system that you don't completely, fully, absolutely grok.
This means, if you don't need delegation right away (for instance, if you don't have 3rd party applications making calls to your API on behalf of your users), don't bother with anything like OAuth.
Contrary to the implications in this article, HTTP Basic Auth is not less secure than OAuth if your endpoints all require HTTPS. If you allow HTTP calls to an API, you have bigger problems than your auth token scheme.
Semantic mismatches between API endpoints and web UI endpoints (ie, semantic differences between API auth and cookie-based authentication) are a classic, pervasive, hard- to- eradicate source of serious security flaws. Don't make things any more complicated than they need to be.
[Late edit: I didn't think I needed to make the first point, but I clearly did need to. Sorry.]
Once they're authenticated, I generate a token and send it to them. They store it, and use that token from here on out (HTTPS only).
Perhaps I expire it after some time (hours or days, if I don't want my user to have to login all the time).
That's it? :D Seems like I'm missing something...
Could you explain that one in more detail? I don't think I understand it.
You have another code path that authenticates API callers.
You have code scattered through your whole application that makes authorization checks based on which user you're authenticated on.
Inconsistencies between the first two code paths often break that code.
One neat variant on this is how GitHub uses HTTP Basic auth to give you an OAuth token... http://developer.github.com/v3/#authentication
What simple but secure methods are there where delegation is required? Is there something simpler than OAuth or AWS style signed HMAC?
We don't need some perfect universally recognized root trust system to get started. Why doesn't the sign up process for authenticated API access routinely include the issuance of a certificate signed by the API owner?
Unlike for interactive users there's no expectation that a customer will be accessing an API from some random computer where he might not have access to his certificate store.
The API support in client SSL libraries for managing multiple certificates, for applications with multiple API affiliations, is shaky.
I like TLS client authentication a lot, but it's hard to make it work.
It's one of those areas where the underlying tool (either a library like openssl or NSS, or an OS feature like SSPI) could do the hard work in one place and make it simple for downstream libraries to wrap the functionality.
In other, somewhat analogous, domains that happened, but for whatever reason not in this case.
If I use https://username:email@example.com/, doesn't that URL show up in server logs all over the internet?
I didn't think this was something I had to point out about API authentication, but apparently it is.
Obviously, you're still using a password if you use HTTP Basic Auth.
This is one of many benefits of using multiple (revokable) API Keys.
% curl --trace-ascii /dev/stdout http://jimktrains:firstname.lastname@example.org
== Info: About to connect() to news.ycombinator.com port 80 (#0)
== Info: Trying 126.96.36.199... == Info: connected
== Info: Server auth using Basic with user 'jimktrains'
=> Send header, 223 bytes (0xdf)
0000: GET / HTTP/1.1
0010: Authorization: Basic amlta3RyYWluczpwYXNzd29yZA==
The username and password are sent in the "Authorization" HTTP header, which will be encrypted.