Where I work, where we supply a software platform that is providing a service to users. Like thousands of others of these services, people can log into our web interface using their username and password and can perform some actions within the tool (wordpress is a good example of such a system).
When this type of service is transitioned into an API, we generally are no longer dealing with username and passwords, we are now dealing with API keys, signatures, HMAC, and a whole raft of other jargon to do essentially the same thing.
When I was thinking about how I was going to set up Authorisation to our API, I thought about the types of API users who would be using the service. I could identify two kinds of people building applications that use my API:
1. The Service Provider
This is the guy that is building a new application, and wants to utilise the functionality provided by the API. He is going to have is own users database, and he’ll authenticate to the API using his own credentials.
2. The Service Extender
This is the guy that is building an application that extends the functionality of the existing service using the API. He may or may not have his own users database, but the likelihood is that he’ll allow his users to authenticate to the API using their own credentials within the service (e.g. OAuth).
As I follow the YAGNI principle as much as possible, the only users that I had in the first instance fit into the first category. Based on this, there wasn’t much point in supporting an OAuth style framework until we had some users that were jumping up and down for it.
Keep the authorisation simple and your users will thank you.
HTTP already has support built-in for authorising users, so I deemed the easiest way was to use the out of the box Authorization header.
Take the existing username and password to access the service that users already know, turn it into Base64 and use Basic HTTP to access the API.
So a username and password of john.smith / Password123 becomes:
HTTPS 1.1 GET /messages Authorization: Basic am9obi5zbWl0aDpQYXNzd29yZDEyMw==
Every programming language comes with a Base64 encoder built-in, so it’s simple for the users to set up.
There are no timestamps, signatures, HMAC or any of the other cumbersome approaches. However, there is one caveat; you must use HTTPS.
As long as you force HTTPS, this is method secure.
I have no doubt the day will come where we need to build this out to support services like OAuth or perhaps generation of signatures using timestamps and shared secrets, but in 3 years of running this service, we haven’t had any complaints from users about this methodology.
Perhaps when you are thinking of authorising your API, check with your users about this methodology before jumping straight to OAuth or similar.