AK4R = API Keys for Rails

AK4R is a Rack middleware which adds to Ruby on Rails the ability to protect APi calls whit an API key passed in the request headers.

The implementation is very similar to the description here: https://www.freecodecamp.org/news/best-practices-for-building-api-keys-97c26eabfea9/ , using some pieces of the rack-api-key gem.

API keys are stored in an Active Record model and validated at every request.

API keys are scoped, so you have the ability to fine tune permissions.

API keys can optionally expire.

Installation

Add this line to your Rails application's Gemfile:

gem 'ak4r'

And then execute:

$ bundle

Finally you should generate the db migration:

rails generate ak4r_migration
rake db:migrate

Usage

Gem auto loads into the Rails application. The default is to protect all urls starting with "/api". Since initially no key is present every request throws an exception:

Ak4r::ApiException

you should rescue this in your application, e.g. you can add this line to application_controller.rb :

rescue_from Ak4r::ApiException, with: :handle_api_authorization

How to generate API keys

There is a rake task for this:

rake ak4r:create["name","scope1;scope2"]

Scopes are defined as [HTTP_VERB]:path, e.g. GET:/api/books.json .

This task outputs the key to put in X-API-KEY header. Please note that the key itself is not stored so you must immediatelly copy it in a secure place.

Configuration

You can customize its behaviour in your config/application.rb :

config.ak4r.[option] = '...'

If options depend on your environment, you can define it in the according file: config/environments/<env>.rb

:salt

The salt used to generate keys.

:header_key

It's important to note that internally Rack actually mutates any given headers and prefixes them with HTTP and subsequently underscores them. For example if an API client passed "X-API-KEY" in the header, Rack would interpret that header as "HTTP_X_API_KEY". "HTTP_X_API_KEY" is the default header. If you want to use a different header you can specify it with this option.

:url_restriction

This is an option that can restrict the middleware to specific URLs. This works well when you have a mixture of API endpoints that require authentication and some that might not. Or a combination of API endpoints and publicly facing webpages. Perhaps you've scoped all of your API endpoints to "/api", and the rest of the URL mappings or routes are supposed to be wide open.

:url_exclusion

This is an option to allow specific URLs to bypass middleware authentication. This works well when you require a single or few endpoints to not require authentication. Perhaps you've scoped all of your API endpoints to "/api" but wish to leave "/api/status" publicly facing.