rails_api_keys
Reusable Rails engine for personal API keys: create (reveal once), hash at rest, revoke, and authenticate via Authorization: Bearer <token>.
Host apps own UI, routes, and domain APIs. This gem stays thin on purpose.
What this gem includes
RailsApiKeys::ApiKey— issue, authenticate, revokehas_api_keys— opt-in owner macro withcreate_api_key!(supports multiple models)RailsApiKeys::Authentication— controller concern for Bearer tokens- Install generator (migration + initializer)
No mailers, jobs, views, assets, or mounted domain routes.
Installation
Add the gem and install:
# Gemfile
gem "rails_api_keys"
bundle install
bin/rails generate rails_api_keys:install
bin/rails db:migrate
Host setup
Opt in on each owner model with has_api_keys (any number of models):
class User < ApplicationRecord
has_api_keys
end
class Company < ApplicationRecord
has_api_keys
end
That declares has_many :api_keys and allows the model to own keys. Build your own controllers/UI to create keys (show the raw token once), list them, and revoke.
Configuration
Defaults suit a typical Devise User host; multiple owners are supported via has_api_keys:
| Option | Default | Purpose |
|---|---|---|
token_prefix |
"#{AppName.downcase}_ak_" |
Prefix on generated raw tokens |
owner_active |
active_for_authentication? when present |
Reject keys whose owner is inactive |
Override only what you need:
# config/initializers/rails_api_keys.rb
RailsApiKeys.configure do |config|
# config.token_prefix = "myapp_ak_"
# config.owner_active = ->(owner) { owner.active? }
end
Usage
key, raw = current_user.create_api_key!(name: "Zapier", permission: :read)
# Show `raw` once — it cannot be recovered later.
RailsApiKeys::ApiKey.authenticate(raw) # => key or nil
key.revoke!
class Api::V1::BaseController < ActionController::API
include RailsApiKeys::Authentication
before_action :authenticate_api_key!
# current_api_key / current_api_owner are available after authenticate
end
Clients send:
Authorization: Bearer <raw_token>
authenticate_api_key! rejects missing/invalid tokens with 401, then enforces permission from the HTTP method: GET/HEAD require read; other methods require write (403 if the key lacks it).
Permissions
| Permission | GET/HEAD | Other methods |
|---|---|---|
read |
allowed | forbidden |
read_write |
allowed | allowed |
Permissions are immutable after create. Revoke with revoke! (sets revoked_at).
Security notes
- Raw tokens are returned only from
create_api_key!/generate_for!and never stored - Digests use SHA-256 (
token_digest); UI can showtoken_display_prefix - Soft revoke via
revoked_at; authentication ignores revoked keys
Development
bundle install
bundle exec rspec
bin/rubocop
See CHANGELOG.md for release notes. Agent-oriented notes live in AGENTS.md.
License
This project is licensed under the MIT License.
Rubyroid Labs — full-cycle software development company for businesses delivering scalable web and mobile apps, dedicated developers, and full-cycle teams in Ruby on Rails, React Native, and UX/UI. 98% on-time delivery.
- Website: rubyroidlabs.com
- Email: hi@rubyroidlabs.com
- References: Clutch