Implementing flexible, Stripe-style API authentication in Ruby on Rails

Having dealt with many uncomfortable API authentication schemes in the last decade, I wanted to share the scheme that we’ve found most sustainable for our Ruby on Rails applications. This scheme aligns with that used by services like Stripe. It allows clients to authenticate either via HTTP Basic Auth or an X-AUTH-TOKEN custom header.

What it will look like

API interactions with the Authentication scheme we are implementing will look as follows:

In using the -u flag, curl is authenticating via HTTP Basic Auth. The client’s API key can also be passed via an X-AUTH-TOKEN header, which you may find more convenient for implementing clients depending on the features and conventions of the underlying HTTP library you are using.

The basics of Basic Auth

HTTP Basic Auth works via the Authorization header. This header takes the following form:

In the case of HTTP Basic Auth, the type component of the header value will be set to Basic. The credentials component is a Base64-encoded string containing the username and the password, separated by a colon character. In our case, we are actually disregarding the password portion and assuming that the user portion is the API key. By placing a colon at the end of the credentials we passed with the -u flag, we are telling curl to pass the key as the user portion of the Authentication payload and an empty string as the password portion.

When we make the request:

The server will see the following:

If we Base64-decode the credentials part, this expands to:

Controller-level authentication

With these building blocks, we can implement a controller-level API authentication scheme. We will assume an ApiKey model with a value column containing the actual key (sk_test_8d7cd4bc9a8cdfe635d3881d4fc1439d in our example).

We will support passing of the key via HTTP Basic auth and also an X-AUTH-TOKEN header. We can therefore implement an ApiController that performs an authorization based upon these headers:

For every action in this controller or any inheriting controller, you can now be assured of the existence of a valid @api_key in scope. You can use this @api_key to perform further authorization (such as by tying it to a company or user and implementing a current_ability method in the case of CanCanCan) and for scoping of resources.

Wrap up

I hope that this article gave some high-level guidance to how to approach Header-based authentication for APIs in Ruby on Rails. This approach is an excellent fit for most authenticated APIs (APIs where you can expect that client credentials will live on a secured host).

For circumstances where credentials cannot be kept private (such as when calls must be made directly from the browser, possibly in a different domain than your application, or when you are providing resource access on behalf of your users to third parties), you may require something like an OAuth scheme instead. In a future post we will be taking a look at this approach as well.

Nicholas

Hi! I'm Nicholas. I am a software developer and the founder of Superset Inc. I keep a personal homepage at nicholas.zaillian.com and I can be reached by email at nzaillian@supersetinc.com (public key here if you want to encrypt your message).

No Comments

Leave a Comment

Please be polite. We appreciate that.
Your email address will not be published and required fields are marked