API Design: HTTP Basic Authentication vs API Token

I'm currently creating an authentication system on front of a public web API for a web application. Given that each user account has an API key and each request must be authenticated, I have two alternatives:

  1. Using an HTTP Basic Authentication, like GitHub does.

    Requests must be sent to the URL

    http://api.example.com/resource/id
    with basic authentication
    username: token
    password: the api key
    
  2. Passing the API Token as querystring parameter.

    Requests must be sent to the URL

    http://api.example.com/resource/id?token=api_key
    

There's also a third option which is passing the token within the URI, but I honestly don't like that solution.

Which solution would you adopt and why?


Solution 1:

Best bet might be using an API key in the header (e.g. 'Authorization: Token MY_API_KEY') instead of as a url param:

Advantages over HTTP Basic Auth:

  • More convenient, as you can easily expire or regenerate tokens without affecting the user's account password.
  • If compromised, vulnerability limited to API, not the user's master account
  • You can have multiple keys per account (e.g. users can have "test" and "production" keys side by side.)

Advantages over API key in URL:

  • Provides extra measure of security by preventing users from inadvertently sharing URLs with their credentials embedded in them. (Also, URL can wind up in things like server logs)

Solution 2:

Many times I had to think about how to authenticate users/requests onto APIs and after comparing more solutions I ended up with using the Amazon's solution where I don't need or I can't use OAuth. This solution is based on signatures that prevents from "man in the middle" problems as Basic Auth and passing a simple token are sending plain text data. Yes you can add ssl but this will add complexity to the system...

Solution 3:

I think that HTTP Basic Auth should be OK but just for really simple needs.

The complete (and final) solution IMHO is to implement an OAuth provider. It's not complex, it's a simple protocol and gives you lots of flexibility. In addition it seems to be the current trend as many big players implement it and it's supported from many many libraries.