api_keys 0.2.1 ā 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.simplecov +36 -0
- data/AGENTS.md +5 -0
- data/Appraisals +17 -0
- data/CHANGELOG.md +9 -0
- data/CLAUDE.md +5 -0
- data/README.md +767 -3
- data/Rakefile +9 -4
- data/app/controllers/api_keys/keys_controller.rb +43 -11
- data/app/controllers/api_keys/security_controller.rb +8 -0
- data/app/views/api_keys/keys/_empty_state.html.erb +9 -0
- data/app/views/api_keys/keys/_form.html.erb +31 -2
- data/app/views/api_keys/keys/_key_actions.html.erb +20 -0
- data/app/views/api_keys/keys/_key_badges.html.erb +17 -0
- data/app/views/api_keys/keys/_key_row.html.erb +21 -35
- data/app/views/api_keys/keys/_key_status.html.erb +10 -0
- data/app/views/api_keys/keys/_keys_table.html.erb +2 -7
- data/app/views/api_keys/keys/_publishable_keys.html.erb +40 -0
- data/app/views/api_keys/keys/_secret_keys.html.erb +39 -0
- data/app/views/api_keys/keys/_show_token.html.erb +5 -1
- data/app/views/api_keys/keys/_token_display.html.erb +11 -0
- data/app/views/api_keys/keys/index.html.erb +40 -8
- data/app/views/api_keys/security/best_practices.html.erb +73 -47
- data/app/views/layouts/api_keys/application.html.erb +113 -7
- data/context7.json +4 -0
- data/gemfiles/rails_7.2.gemfile +21 -0
- data/gemfiles/rails_8.0.gemfile +21 -0
- data/gemfiles/rails_8.1.gemfile +21 -0
- data/lib/api_keys/configuration.rb +77 -0
- data/lib/api_keys/errors.rb +73 -0
- data/lib/api_keys/form_builder_extensions.rb +158 -0
- data/lib/api_keys/helpers/expiration_options.rb +131 -0
- data/lib/api_keys/helpers/token_session.rb +68 -0
- data/lib/api_keys/helpers/view_helpers.rb +216 -0
- data/lib/api_keys/models/api_key.rb +229 -17
- data/lib/api_keys/models/concerns/has_api_keys.rb +183 -3
- data/lib/api_keys/services/authenticator.rb +45 -2
- data/lib/api_keys/services/digestor.rb +6 -2
- data/lib/api_keys/tenant_resolution.rb +3 -1
- data/lib/api_keys/version.rb +1 -1
- data/lib/api_keys.rb +12 -0
- data/lib/generators/api_keys/add_key_types_generator.rb +68 -0
- data/lib/generators/api_keys/templates/add_key_types_to_api_keys.rb.erb +18 -0
- data/lib/generators/api_keys/templates/create_api_keys_table.rb.erb +9 -0
- data/lib/generators/api_keys/templates/initializer.rb +242 -120
- metadata +24 -58
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators/base"
|
|
4
|
+
require "rails/generators/active_record"
|
|
5
|
+
|
|
6
|
+
module ApiKeys
|
|
7
|
+
module Generators
|
|
8
|
+
# Rails generator for adding key_type and environment columns to the api_keys table.
|
|
9
|
+
# This generator is for existing installations that want to enable the key types feature.
|
|
10
|
+
class AddKeyTypesGenerator < Rails::Generators::Base
|
|
11
|
+
include ActiveRecord::Generators::Migration
|
|
12
|
+
|
|
13
|
+
source_root File.expand_path("templates", __dir__)
|
|
14
|
+
|
|
15
|
+
# Implement the required interface for Rails::Generators::Migration.
|
|
16
|
+
def self.next_migration_number(dirname)
|
|
17
|
+
next_migration_number = current_migration_number(dirname) + 1
|
|
18
|
+
ActiveRecord::Migration.next_migration_number(next_migration_number)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Creates the migration file using the template.
|
|
22
|
+
def create_migration_file
|
|
23
|
+
migration_template "add_key_types_to_api_keys.rb.erb",
|
|
24
|
+
File.join(db_migrate_path, "add_key_types_to_api_keys.rb")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Displays helpful information to the user after installation.
|
|
28
|
+
def display_post_install_message
|
|
29
|
+
say "\nš Key types migration created!", :green
|
|
30
|
+
say "\nNext steps:"
|
|
31
|
+
say " 1. Run `rails db:migrate` to add the key_type and environment columns."
|
|
32
|
+
say "\n 2. Configure key types in `config/initializers/api_keys.rb`:"
|
|
33
|
+
say " ApiKeys.configure do |config|"
|
|
34
|
+
say " config.key_types = {"
|
|
35
|
+
say " publishable: {"
|
|
36
|
+
say " prefix: 'pk',"
|
|
37
|
+
say " permissions: %w[read validate],"
|
|
38
|
+
say " revocable: false,"
|
|
39
|
+
say " limit: 1"
|
|
40
|
+
say " },"
|
|
41
|
+
say " secret: {"
|
|
42
|
+
say " prefix: 'sk',"
|
|
43
|
+
say " permissions: :all"
|
|
44
|
+
say " }"
|
|
45
|
+
say " }"
|
|
46
|
+
say ""
|
|
47
|
+
say " config.environments = {"
|
|
48
|
+
say " test: { prefix_segment: 'test' },"
|
|
49
|
+
say " live: { prefix_segment: 'live' }"
|
|
50
|
+
say " }"
|
|
51
|
+
say ""
|
|
52
|
+
say " config.current_environment = -> { Rails.env.production? ? :live : :test }"
|
|
53
|
+
say " config.strict_environment_isolation = true"
|
|
54
|
+
say " end"
|
|
55
|
+
say "\n 3. Create typed API keys:"
|
|
56
|
+
say " user.create_api_key!(name: 'My Key', key_type: :publishable)"
|
|
57
|
+
say " user.create_api_key!(name: 'Admin Key', key_type: :secret)"
|
|
58
|
+
say "\nSee the api_keys README for detailed usage and examples.", :cyan
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def migration_version
|
|
64
|
+
"[#{ActiveRecord::VERSION::STRING.to_f}]"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Migration to add key_type and environment columns to the api_keys table.
|
|
4
|
+
# This enables the Stripe-style publishable/secret key types feature.
|
|
5
|
+
#
|
|
6
|
+
# Run this migration if you're upgrading from a version of api_keys that
|
|
7
|
+
# didn't have key types support.
|
|
8
|
+
class AddKeyTypesToApiKeys < ActiveRecord::Migration<%= migration_version %>
|
|
9
|
+
def change
|
|
10
|
+
add_column :api_keys, :key_type, :string
|
|
11
|
+
add_column :api_keys, :environment, :string
|
|
12
|
+
|
|
13
|
+
add_index :api_keys, :key_type
|
|
14
|
+
add_index :api_keys, :environment
|
|
15
|
+
add_index :api_keys, [:owner_type, :owner_id, :key_type, :environment],
|
|
16
|
+
name: "index_api_keys_owner_type_env"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -42,6 +42,12 @@ class CreateApiKeysTable < ActiveRecord::Migration<%= migration_version %>
|
|
|
42
42
|
# Timestamp when the key was revoked (null means active)
|
|
43
43
|
t.datetime :revoked_at
|
|
44
44
|
|
|
45
|
+
# Key type identifier (e.g., "publishable", "secret") for Stripe-style key types
|
|
46
|
+
t.string :key_type
|
|
47
|
+
|
|
48
|
+
# Environment identifier (e.g., "test", "live") for environment isolation
|
|
49
|
+
t.string :environment
|
|
50
|
+
|
|
45
51
|
t.timestamps
|
|
46
52
|
|
|
47
53
|
# Critical index for authentication performance
|
|
@@ -58,6 +64,9 @@ class CreateApiKeysTable < ActiveRecord::Migration<%= migration_version %>
|
|
|
58
64
|
t.index :expires_at
|
|
59
65
|
t.index :revoked_at
|
|
60
66
|
t.index :last_used_at
|
|
67
|
+
t.index :key_type
|
|
68
|
+
t.index :environment
|
|
69
|
+
t.index [:owner_type, :owner_id, :key_type, :environment], name: "index_api_keys_owner_type_env"
|
|
61
70
|
end
|
|
62
71
|
end
|
|
63
72
|
|
|
@@ -1,77 +1,188 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
ApiKeys.configure do |config|
|
|
4
|
-
#
|
|
4
|
+
# ============================================================================
|
|
5
|
+
# CORE AUTHENTICATION
|
|
6
|
+
# ============================================================================
|
|
5
7
|
|
|
6
8
|
# The HTTP header name where the API key is expected.
|
|
7
9
|
# Default: "Authorization" (expects "Bearer <token>")
|
|
8
10
|
# config.header = "Authorization"
|
|
9
11
|
|
|
10
12
|
# The query parameter name to check as a fallback if the header is missing.
|
|
11
|
-
#
|
|
13
|
+
# WARNING: Query parameters appear in logs, browser history, and Referer headers.
|
|
14
|
+
# Only enable for development/testing. Set to nil to disable (recommended).
|
|
12
15
|
# Default: nil
|
|
13
16
|
# config.query_param = "api_key"
|
|
14
17
|
|
|
15
|
-
#
|
|
18
|
+
# ============================================================================
|
|
19
|
+
# DASHBOARD CONFIGURATION
|
|
20
|
+
# ============================================================================
|
|
21
|
+
#
|
|
22
|
+
# The api_keys engine provides a web UI for users to manage their API keys.
|
|
23
|
+
# Configure how the dashboard integrates with your application's auth system.
|
|
24
|
+
# ============================================================================
|
|
16
25
|
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
26
|
+
# The method that returns the current API key owner in your controllers.
|
|
27
|
+
# This should return the model instance that has_api_keys.
|
|
28
|
+
# Default: :current_user (works with Devise out of the box)
|
|
29
|
+
#
|
|
30
|
+
# Example for Organization-owned keys:
|
|
31
|
+
# config.current_owner_method = :current_organization
|
|
21
32
|
|
|
22
|
-
# The
|
|
23
|
-
#
|
|
24
|
-
# Default:
|
|
25
|
-
#
|
|
33
|
+
# The method that authenticates/requires login for the dashboard.
|
|
34
|
+
# This should be a before_action-style method that ensures the owner is logged in.
|
|
35
|
+
# Default: :authenticate_user! (works with Devise out of the box)
|
|
36
|
+
#
|
|
37
|
+
# Example for Organization-owned keys:
|
|
38
|
+
# config.authenticate_owner_method = :authenticate_organization!
|
|
26
39
|
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
# Default:
|
|
31
|
-
#
|
|
40
|
+
# Dashboard environment filtering (only applies when key_types is configured).
|
|
41
|
+
# When false (default), dashboard only shows keys matching current_environment.
|
|
42
|
+
# When true, dashboard shows keys from all environments.
|
|
43
|
+
# Default: false
|
|
44
|
+
#
|
|
45
|
+
# config.dashboard_allow_cross_environment = false
|
|
32
46
|
|
|
33
|
-
#
|
|
47
|
+
# URL for the "back" link in the dashboard UI.
|
|
48
|
+
# Default: "/"
|
|
49
|
+
# config.return_url = "/settings"
|
|
34
50
|
|
|
35
|
-
#
|
|
36
|
-
# :
|
|
37
|
-
#
|
|
38
|
-
# Default: :sha256
|
|
39
|
-
# config.hash_strategy = :bcrypt
|
|
51
|
+
# Text for the "back" link.
|
|
52
|
+
# Default: "ā¹ Home"
|
|
53
|
+
# config.return_text = "ā¹ Back to Settings"
|
|
40
54
|
|
|
41
|
-
#
|
|
55
|
+
# ============================================================================
|
|
56
|
+
# TOKEN PREFIXES
|
|
57
|
+
# ============================================================================
|
|
58
|
+
#
|
|
59
|
+
# API keys are generated with a prefix followed by random characters:
|
|
60
|
+
# "ak_7Hq2mJvK9pRs3xYz..."
|
|
61
|
+
# prefix = ak_
|
|
62
|
+
# random part = 7Hq2mJvK9pRs3xYz...
|
|
63
|
+
#
|
|
64
|
+
# The prefix system has two modes:
|
|
65
|
+
#
|
|
66
|
+
# 1. SIMPLE MODE (default): All keys use the same prefix from `token_prefix`
|
|
67
|
+
# Example: ak_7Hq2mJvK9pRs3xYz...
|
|
68
|
+
#
|
|
69
|
+
# 2. KEY TYPES MODE: Different key types get different prefixes based on
|
|
70
|
+
# their type and environment (Stripe-style)
|
|
71
|
+
# Example: pk_test_7Hq2mJvK..., sk_live_9xYz3pRs...
|
|
72
|
+
#
|
|
73
|
+
# See "KEY TYPES & ENVIRONMENTS" section below to enable key types mode.
|
|
42
74
|
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
# a User model with current_user/authenticate_user! methods (Devise-style).
|
|
75
|
+
# ----------------------------------------------------------------------------
|
|
76
|
+
# Simple Prefix (when NOT using KEY TYPES)
|
|
77
|
+
# ----------------------------------------------------------------------------
|
|
47
78
|
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
79
|
+
# A lambda/proc that returns the prefix for newly generated tokens.
|
|
80
|
+
# This is ONLY used when:
|
|
81
|
+
# - key_types is not configured (empty hash), OR
|
|
82
|
+
# - Creating a key without specifying a key_type
|
|
83
|
+
#
|
|
84
|
+
# When key_types IS configured and you specify a key_type, this setting
|
|
85
|
+
# is IGNORED - the prefix comes from the key type's configuration instead.
|
|
86
|
+
#
|
|
87
|
+
# WARNING: Once set, do NOT change or existing keys will fail authentication!
|
|
88
|
+
# Default: -> { "ak_" }
|
|
89
|
+
# config.token_prefix = -> { "myapp_" }
|
|
50
90
|
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
91
|
+
# ============================================================================
|
|
92
|
+
# KEY TYPES & ENVIRONMENTS (Stripe-style Publishable/Secret Keys)
|
|
93
|
+
# ============================================================================
|
|
94
|
+
#
|
|
95
|
+
# For applications that distribute software with embedded API keys (desktop
|
|
96
|
+
# apps, mobile apps, CLI tools), you can create different key types with
|
|
97
|
+
# different permission levels - similar to Stripe's publishable/secret pattern.
|
|
98
|
+
#
|
|
99
|
+
# When enabled:
|
|
100
|
+
# - Keys get type+environment prefixes: pk_test_, pk_live_, sk_test_, sk_live_
|
|
101
|
+
# - Each type can have different permissions, revocability, and limits
|
|
102
|
+
# - The `token_prefix` setting above is IGNORED for typed keys
|
|
103
|
+
#
|
|
104
|
+
# By default, this feature is DISABLED (empty hash) for backwards compatibility.
|
|
105
|
+
# Existing keys without key_type/environment continue to work normally.
|
|
106
|
+
# ============================================================================
|
|
55
107
|
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
108
|
+
# Define your key types with their properties:
|
|
109
|
+
#
|
|
110
|
+
# - prefix: The token prefix for this type (e.g., "pk" becomes pk_test_)
|
|
111
|
+
# - permissions: Scope ceiling - array of allowed scopes, or :all for unrestricted
|
|
112
|
+
# - revocable: Whether keys of this type can be revoked/deleted (default: true)
|
|
113
|
+
# - limit: Max keys of this type per owner per environment (nil = unlimited)
|
|
114
|
+
# - public: If true AND revocable: false, stores plaintext token in metadata
|
|
115
|
+
# so it can be viewed again in the dashboard. Use ONLY for publishable
|
|
116
|
+
# keys designed to be embedded in distributed apps. (default: false)
|
|
117
|
+
# SECURITY: NEVER set public: true on secret keys!
|
|
118
|
+
#
|
|
119
|
+
# config.key_types = {
|
|
120
|
+
# publishable: {
|
|
121
|
+
# prefix: "pk", # ā pk_test_, pk_live_
|
|
122
|
+
# permissions: %w[read validate], # Can ONLY have these scopes
|
|
123
|
+
# revocable: false, # Cannot be revoked - protects deployed apps!
|
|
124
|
+
# public: true, # Store token for later viewing in dashboard
|
|
125
|
+
# limit: 1 # Only 1 publishable key per environment
|
|
126
|
+
# },
|
|
127
|
+
# secret: {
|
|
128
|
+
# prefix: "sk", # ā sk_test_, sk_live_
|
|
129
|
+
# permissions: :all # No scope restrictions
|
|
130
|
+
# # revocable: true (default)
|
|
131
|
+
# # public: false (default) - NEVER store secret keys!
|
|
132
|
+
# # limit: nil (default = unlimited)
|
|
133
|
+
# }
|
|
134
|
+
# }
|
|
135
|
+
|
|
136
|
+
# Define your environments with their prefix segments:
|
|
137
|
+
#
|
|
138
|
+
# - prefix_segment: The middle part of the prefix (e.g., "test" ā pk_test_)
|
|
139
|
+
# Set to nil for single-environment setups (prefix becomes just "pk_")
|
|
140
|
+
#
|
|
141
|
+
# config.environments = {
|
|
142
|
+
# test: { prefix_segment: "test" }, # Development/staging ā pk_test_, sk_test_
|
|
143
|
+
# live: { prefix_segment: "live" } # Production ā pk_live_, sk_live_
|
|
144
|
+
# }
|
|
145
|
+
#
|
|
146
|
+
# Alternative naming (Stripe's newer convention):
|
|
147
|
+
# config.environments = {
|
|
148
|
+
# sandbox: { prefix_segment: "test" },
|
|
149
|
+
# live: { prefix_segment: "live" }
|
|
150
|
+
# }
|
|
151
|
+
|
|
152
|
+
# Lambda that returns the current environment.
|
|
153
|
+
# Used to auto-select environment when creating keys and for isolation checks.
|
|
154
|
+
# Default: -> { :default }
|
|
155
|
+
#
|
|
156
|
+
# config.current_environment = -> { Rails.env.production? ? :live : :test }
|
|
60
157
|
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
158
|
+
# Enable strict environment isolation.
|
|
159
|
+
# When true, keys can ONLY authenticate in their matching environment:
|
|
160
|
+
# - test keys return :environment_mismatch error in production
|
|
161
|
+
# - live keys return :environment_mismatch error in development/test
|
|
162
|
+
# Default: false
|
|
163
|
+
#
|
|
164
|
+
# config.strict_environment_isolation = true
|
|
165
|
+
|
|
166
|
+
# Default key type when not specified in create_api_key!
|
|
167
|
+
# When set and key_types is configured, keys created without explicit
|
|
168
|
+
# key_type will use this default.
|
|
169
|
+
# Default: nil (must specify key_type explicitly when key_types is configured)
|
|
170
|
+
#
|
|
171
|
+
# config.default_key_type = :secret
|
|
64
172
|
|
|
65
|
-
#
|
|
173
|
+
# ============================================================================
|
|
174
|
+
# KEY LIMITS & BEHAVIORS
|
|
175
|
+
# ============================================================================
|
|
66
176
|
|
|
67
177
|
# Global limit on the number of *active* keys an owner can have.
|
|
68
|
-
# Can be overridden
|
|
178
|
+
# Can be overridden per-model with `max_keys` in the `has_api_keys` block, like:
|
|
179
|
+
# has_api_keys max_keys: 5
|
|
69
180
|
# Set to nil for no global limit.
|
|
70
181
|
# Default: nil
|
|
71
182
|
# config.default_max_keys_per_owner = 10
|
|
72
183
|
|
|
73
|
-
#
|
|
74
|
-
# Can be overridden
|
|
184
|
+
# Require a name when creating keys.
|
|
185
|
+
# Can be overridden per-model with `require_name` in the `has_api_keys` block.
|
|
75
186
|
# Default: false
|
|
76
187
|
# config.require_key_name = true
|
|
77
188
|
|
|
@@ -81,104 +192,115 @@ ApiKeys.configure do |config|
|
|
|
81
192
|
# config.expire_after = 90.days
|
|
82
193
|
|
|
83
194
|
# Default scopes to assign to newly created keys if none are specified.
|
|
84
|
-
#
|
|
195
|
+
# Can be overridden per-model with `default_scopes` in the `has_api_keys` block.
|
|
85
196
|
# Default: []
|
|
86
197
|
# config.default_scopes = ["read"]
|
|
87
198
|
|
|
88
|
-
#
|
|
89
|
-
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
# config.cache_ttl = 30.seconds # Higher TTL = higher risk of "revoked-but-still-valid" edge cases
|
|
98
|
-
|
|
99
|
-
# === Security ===
|
|
199
|
+
# ============================================================================
|
|
200
|
+
# TOKEN GENERATION
|
|
201
|
+
# ============================================================================
|
|
202
|
+
#
|
|
203
|
+
# The number of random bytes to generate for the token (before encoding).
|
|
204
|
+
# More bytes = more entropy = harder to guess.
|
|
205
|
+
# SECURITY: Minimum recommended is 16 bytes (128 bits). Default provides 192 bits.
|
|
206
|
+
# Default: 24 (generates ~32 Base58 chars or 48 hex chars)
|
|
207
|
+
# config.token_length = 24
|
|
100
208
|
|
|
101
|
-
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
209
|
+
# The encoding alphabet for the random part of the token.
|
|
210
|
+
# :base58 - shorter tokens, avoids ambiguous chars (0, O, I, l) - RECOMMENDED
|
|
211
|
+
# :hex - standard hexadecimal encoding, longer tokens
|
|
212
|
+
# Default: :base58
|
|
213
|
+
# config.token_alphabet = :base58
|
|
104
214
|
|
|
105
|
-
#
|
|
106
|
-
#
|
|
107
|
-
#
|
|
108
|
-
# config.https_strict_mode = true
|
|
215
|
+
# ============================================================================
|
|
216
|
+
# STORAGE & VERIFICATION
|
|
217
|
+
# ============================================================================
|
|
109
218
|
|
|
110
|
-
#
|
|
111
|
-
# ---------------------------------------------
|
|
112
|
-
# The api_keys gem executes callbacks and updates the `last_used_at` timestamp on every successful authentication
|
|
113
|
-
# and optionally increments `requests_count` if `track_requests_count` is true.
|
|
114
|
-
# To avoid blocking the request cycle, these calls and updates are performed asynchronously
|
|
115
|
-
# using ActiveJob (`ApiKeys::Jobs::UpdateStatsJob` and `ApiKeys::Jobs::CallbacksJob`)
|
|
219
|
+
# The hashing strategy used to store token digests in the database.
|
|
116
220
|
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
221
|
+
# :sha256 (RECOMMENDED for API keys)
|
|
222
|
+
# - Fast, performant, O(1) database lookups
|
|
223
|
+
# - Secure for high-entropy tokens (192+ bits from SecureRandom)
|
|
224
|
+
# - Industry standard for API keys (used by Stripe, GitHub, AWS)
|
|
119
225
|
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
# -
|
|
123
|
-
#
|
|
226
|
+
# :bcrypt (for extra security at cost of performance)
|
|
227
|
+
# - Includes salt, computationally expensive by design
|
|
228
|
+
# - 10x-50x slower than SHA256 - impacts every API request
|
|
229
|
+
# - Better for low-entropy secrets (passwords), overkill for random API keys
|
|
124
230
|
#
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
# if you cannot use a persistent backend and performance is critical.
|
|
231
|
+
# Default: :sha256
|
|
232
|
+
# config.hash_strategy = :sha256
|
|
128
233
|
|
|
129
|
-
#
|
|
234
|
+
# ============================================================================
|
|
235
|
+
# SECURITY
|
|
236
|
+
# ============================================================================
|
|
130
237
|
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
238
|
+
# Log a warning if API authentication is attempted over HTTP in production.
|
|
239
|
+
# API keys should always be transmitted over HTTPS.
|
|
240
|
+
# Default: true
|
|
241
|
+
# config.https_only_production = true
|
|
134
242
|
|
|
135
|
-
#
|
|
136
|
-
#
|
|
137
|
-
#
|
|
243
|
+
# Raise an error (instead of just warning) for HTTP in production.
|
|
244
|
+
# Only applies when https_only_production is true.
|
|
245
|
+
# Default: false
|
|
246
|
+
# config.https_strict_mode = false
|
|
138
247
|
|
|
139
|
-
#
|
|
248
|
+
# ============================================================================
|
|
249
|
+
# BACKGROUND JOBS & CALLBACKS
|
|
250
|
+
# ============================================================================
|
|
251
|
+
#
|
|
252
|
+
# The gem can update usage statistics and execute callbacks asynchronously
|
|
253
|
+
# using ActiveJob. For reliable operation, configure a persistent job backend
|
|
254
|
+
# (Sidekiq, GoodJob, SolidQueue, etc.).
|
|
255
|
+
#
|
|
256
|
+
# WARNING: The default :async adapter may lose jobs on app restart.
|
|
257
|
+
# The :inline adapter runs synchronously, impacting request performance.
|
|
258
|
+
# ============================================================================
|
|
140
259
|
|
|
141
|
-
#
|
|
142
|
-
#
|
|
143
|
-
# `requests_count`, and configured callbacks will NOT be processed.
|
|
144
|
-
# Useful if you handle these concerns externally or cannot use ActiveJob.
|
|
260
|
+
# Master toggle for all background job operations.
|
|
261
|
+
# When false, last_used_at, requests_count, and callbacks are NOT processed.
|
|
145
262
|
# Default: true
|
|
146
|
-
# config.enable_async_operations =
|
|
147
|
-
|
|
148
|
-
# === Usage Statistics ===
|
|
263
|
+
# config.enable_async_operations = true
|
|
149
264
|
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
# Note: Incrementing counters frequently can impact DB performance.
|
|
265
|
+
# Track request counts (increments requests_count on each authentication).
|
|
266
|
+
# Note: High-frequency counter updates can impact database performance.
|
|
153
267
|
# Default: false
|
|
154
|
-
# config.track_requests_count =
|
|
268
|
+
# config.track_requests_count = false
|
|
155
269
|
|
|
156
|
-
#
|
|
157
|
-
|
|
158
|
-
#
|
|
159
|
-
#
|
|
160
|
-
# Default: ->(request) { }
|
|
161
|
-
# config.before_authentication = ->(request) { Rails.logger.info "Authenticating request: #{request.uuid}" }
|
|
162
|
-
|
|
163
|
-
# A lambda/proc to run *after* authentication attempt (success or failure).
|
|
164
|
-
# Receives the ApiKeys::Services::Authenticator::Result object.
|
|
165
|
-
# Default: ->(result) { }
|
|
166
|
-
# config.after_authentication = ->(result) { MyAnalytics.track_auth(result) }
|
|
270
|
+
# Queue names for background jobs.
|
|
271
|
+
# Default: :default
|
|
272
|
+
# config.stats_job_queue = :default
|
|
273
|
+
# config.callbacks_job_queue = :default
|
|
167
274
|
|
|
168
|
-
#
|
|
275
|
+
# Callbacks executed on authentication attempts.
|
|
276
|
+
# before_authentication: receives the request object
|
|
277
|
+
# after_authentication: receives the Result object (success/failure info)
|
|
278
|
+
#
|
|
279
|
+
# Default: empty procs (no-op)
|
|
280
|
+
# config.before_authentication = ->(request) { Rails.logger.info "Auth: #{request.uuid}" }
|
|
281
|
+
# config.after_authentication = ->(result) { Analytics.track(result) }
|
|
169
282
|
|
|
170
|
-
#
|
|
171
|
-
#
|
|
172
|
-
#
|
|
173
|
-
# config.return_url = "/app/settings"
|
|
283
|
+
# ============================================================================
|
|
284
|
+
# PERFORMANCE
|
|
285
|
+
# ============================================================================
|
|
174
286
|
|
|
175
|
-
#
|
|
176
|
-
#
|
|
177
|
-
#
|
|
287
|
+
# Time-to-live (TTL) for caching API key lookups in Rails.cache.
|
|
288
|
+
#
|
|
289
|
+
# Higher values = better performance (fewer DB queries)
|
|
290
|
+
# Lower values = faster propagation of revocations/changes
|
|
291
|
+
#
|
|
292
|
+
# Trade-off: A revoked key may still work for up to `cache_ttl` seconds
|
|
293
|
+
# until the cache expires.
|
|
294
|
+
#
|
|
295
|
+
# Set to 0 or nil to disable caching entirely.
|
|
296
|
+
# Default: 5.seconds
|
|
297
|
+
# config.cache_ttl = 5.seconds
|
|
178
298
|
|
|
179
|
-
#
|
|
299
|
+
# ============================================================================
|
|
300
|
+
# DEBUGGING
|
|
301
|
+
# ============================================================================
|
|
180
302
|
|
|
181
|
-
# Enable verbose logging
|
|
303
|
+
# Enable verbose debug logging.
|
|
182
304
|
# Default: false
|
|
183
|
-
# config.debug_logging =
|
|
305
|
+
# config.debug_logging = false
|
|
184
306
|
end
|