api_keys 0.1.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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +393 -0
  5. data/Rakefile +32 -0
  6. data/api_keys_dashboard.webp +0 -0
  7. data/api_keys_permissions.webp +0 -0
  8. data/api_keys_token.webp +0 -0
  9. data/app/controllers/api_keys/application_controller.rb +62 -0
  10. data/app/controllers/api_keys/keys_controller.rb +129 -0
  11. data/app/controllers/api_keys/security_controller.rb +16 -0
  12. data/app/views/api_keys/keys/_form.html.erb +106 -0
  13. data/app/views/api_keys/keys/_key_row.html.erb +72 -0
  14. data/app/views/api_keys/keys/_keys_table.html.erb +52 -0
  15. data/app/views/api_keys/keys/_show_token.html.erb +88 -0
  16. data/app/views/api_keys/keys/edit.html.erb +5 -0
  17. data/app/views/api_keys/keys/index.html.erb +26 -0
  18. data/app/views/api_keys/keys/new.html.erb +5 -0
  19. data/app/views/api_keys/keys/show.html.erb +12 -0
  20. data/app/views/api_keys/security/best_practices.html.erb +70 -0
  21. data/app/views/layouts/api_keys/application.html.erb +115 -0
  22. data/config/routes.rb +18 -0
  23. data/lib/api_keys/authentication.rb +160 -0
  24. data/lib/api_keys/configuration.rb +125 -0
  25. data/lib/api_keys/controller.rb +47 -0
  26. data/lib/api_keys/engine.rb +76 -0
  27. data/lib/api_keys/jobs/callbacks_job.rb +69 -0
  28. data/lib/api_keys/jobs/update_stats_job.rb +58 -0
  29. data/lib/api_keys/logging.rb +42 -0
  30. data/lib/api_keys/models/api_key.rb +209 -0
  31. data/lib/api_keys/models/concerns/has_api_keys.rb +144 -0
  32. data/lib/api_keys/services/authenticator.rb +255 -0
  33. data/lib/api_keys/services/digestor.rb +68 -0
  34. data/lib/api_keys/services/token_generator.rb +32 -0
  35. data/lib/api_keys/tenant_resolution.rb +40 -0
  36. data/lib/api_keys/version.rb +5 -0
  37. data/lib/api_keys.rb +49 -0
  38. data/lib/generators/api_keys/install_generator.rb +70 -0
  39. data/lib/generators/api_keys/templates/create_api_keys_table.rb.erb +100 -0
  40. data/lib/generators/api_keys/templates/initializer.rb +160 -0
  41. metadata +184 -0
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+ require "base58"
5
+
6
+ module ApiKeys
7
+ module Services
8
+ # Generates secure, random API tokens according to configured settings.
9
+ class TokenGenerator
10
+ # Generates a new token string.
11
+ #
12
+ # @param length [Integer] The desired byte length of the random part (before encoding).
13
+ # @param prefix [String] The prefix to prepend to the token.
14
+ # @param alphabet [Symbol] The encoding alphabet (:base58 or :hex).
15
+ # @return [String] The generated token including the prefix.
16
+ def self.call(length: ApiKeys.configuration.token_length, prefix: ApiKeys.configuration.token_prefix.call, alphabet: ApiKeys.configuration.token_alphabet)
17
+ random_bytes = SecureRandom.bytes(length)
18
+
19
+ random_part = case alphabet
20
+ when :base58
21
+ Base58.binary_to_base58(random_bytes, :bitcoin)
22
+ when :hex
23
+ random_bytes.unpack1("H*") # Equivalent to SecureRandom.hex
24
+ else
25
+ raise ArgumentError, "Unsupported token alphabet: #{alphabet}. Use :base58 or :hex."
26
+ end
27
+
28
+ "#{prefix}#{random_part}"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ApiKeys
6
+ # Controller concern to resolve and provide access to the tenant
7
+ # associated with the currently authenticated API key.
8
+ module TenantResolution
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ helper_method :current_api_tenant
13
+
14
+ # Alias for convenience and explicitness
15
+ alias_method :current_api_key_tenant, :current_api_tenant
16
+ alias_method :current_api_account, :current_api_tenant
17
+ alias_method :current_api_key_account, :current_api_tenant
18
+ alias_method :current_api_owner, :current_api_tenant
19
+ alias_method :current_api_key_owner, :current_api_tenant
20
+ end
21
+
22
+ # Returns the tenant associated with the current API key.
23
+ # Uses the configured `tenant_resolver` lambda.
24
+ # Returns nil if no key is authenticated, no owner exists,
25
+ # or the resolver returns nil.
26
+ #
27
+ # @return [Object, nil] The resolved tenant object, or nil.
28
+ def current_api_tenant
29
+ return @current_api_tenant if defined?(@current_api_tenant)
30
+ return nil unless current_api_key # Requires Authentication concern to be included first
31
+
32
+ resolver = ApiKeys.configuration.tenant_resolver
33
+ @current_api_tenant = resolver&.call(current_api_key)
34
+ rescue StandardError => e
35
+ # Log error but don't break the request if resolver fails
36
+ Rails.logger.error "[ApiKeys] Tenant resolution failed: #{e.message}" if defined?(Rails.logger)
37
+ @current_api_tenant = nil
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ApiKeys
4
+ VERSION = "0.1.0"
5
+ end
data/lib/api_keys.rb ADDED
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is the entry point to the gem.
4
+
5
+ require "rails"
6
+ require "active_record"
7
+ require "active_support/all"
8
+
9
+ require "api_keys/version"
10
+ require "api_keys/configuration"
11
+
12
+ require "api_keys/models/concerns/has_api_keys"
13
+
14
+ require "api_keys/models/api_key"
15
+
16
+ # Rails integration
17
+ require "api_keys/engine" if defined?(Rails)
18
+
19
+ # Main module that serves as the primary interface to the gem.
20
+ # Most methods here delegate to Configuration, which is the single source of truth for all config in the initializer
21
+ module ApiKeys
22
+ # Custom error classes
23
+ class Error < StandardError; end
24
+
25
+ class << self
26
+ attr_writer :configuration
27
+
28
+ def configuration
29
+ @configuration ||= Configuration.new
30
+ end
31
+
32
+ # Configure the gem with a block (main entry point)
33
+ def configure
34
+ yield(configuration)
35
+ end
36
+
37
+ # Resets the configuration to its default values.
38
+ # Useful for testing.
39
+ def reset_configuration!
40
+ @configuration = Configuration.new
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ # TODO: Require other necessary files like configuration, engine, etc.
47
+ # require_relative "api_keys/configuration"
48
+ # require_relative "api_keys/engine"
49
+ # require_relative "api_keys/railtie" if defined?(Rails::Railtie)
@@ -0,0 +1,70 @@
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 installing the ApiKeys gem.
9
+ # Creates the necessary migration and initializer file.
10
+ class InstallGenerator < 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
+ # Borrowed from ActiveRecord::Generators::Base
17
+ # https://github.com/rails/rails/blob/main/activerecord/lib/rails/generators/active_record/base.rb#L31
18
+ def self.next_migration_number(dirname)
19
+ next_migration_number = current_migration_number(dirname) + 1
20
+ ActiveRecord::Migration.next_migration_number(next_migration_number)
21
+ end
22
+
23
+ # Creates the migration file using the template.
24
+ def create_migration_file
25
+ migration_template "create_api_keys_table.rb.erb",
26
+ File.join(db_migrate_path, "create_api_keys_table.rb")
27
+ end
28
+
29
+ # Creates the initializer file using the template.
30
+ def create_initializer
31
+ template "initializer.rb", "config/initializers/api_keys.rb"
32
+ end
33
+
34
+ # Displays helpful information to the user after installation.
35
+ def display_post_install_message
36
+ say "\n🎉 api_keys gem successfully installed!", :green
37
+ say "\nNext steps:"
38
+ say " 1. Run `rails db:migrate` to create the `api_keys` table."
39
+ say " ☢️ Run migrations before starting your application!", :yellow
40
+ say "\n 2. Add `has_api_keys` to any models that need to have API keys, with an optional block for configuration:"
41
+ say " # Example for app/models/user.rb"
42
+ say " class User < ApplicationRecord"
43
+ say " has_api_keys do"
44
+ say " # Optional settings:"
45
+ say " # max_keys 10"
46
+ say " end"
47
+ say " # ..."
48
+ say " end"
49
+ say "\n 3. Optionally, configure the gem behavior in `config/initializers/api_keys.rb` if needed."
50
+ say "\n 4. In your app's API controllers, verify API keys by including `ApiKeys::Controller`, and adding the before_action to the desired endpoints:"
51
+ say " # Example for app/controllers/api/base_controller.rb"
52
+ say " class Api::BaseController < ActionController::API"
53
+ say " include ApiKeys::Controller"
54
+ say " before_action :authenticate_api_key! # Enforce authentication"
55
+ say " # ..."
56
+ say " end"
57
+ say "\nSee the api_keys README for detailed usage and examples.
58
+ ", :cyan
59
+ say "Happy coding! 🚀", :green
60
+ end
61
+
62
+ private
63
+
64
+ def migration_version
65
+ "[#{ActiveRecord::VERSION::STRING.to_f}]"
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Migration responsible for creating the core api_keys table.
4
+ class CreateApiKeysTable < ActiveRecord::Migration<%= migration_version %>
5
+ def change
6
+ primary_key_type, foreign_key_type = primary_and_foreign_key_types
7
+
8
+ create_table :api_keys, id: primary_key_type do |t|
9
+ # Identifiable prefix (e.g., "ak_live_", "ak_test_") for env/debugging
10
+ t.string :prefix, null: false
11
+
12
+ # Secure digest of the token (e.g., sha256 or bcrypt hash)
13
+ t.string :token_digest, null: false
14
+
15
+ # Algorithm used for the digest (e.g., "bcrypt", "sha256")
16
+ t.string :digest_algorithm, null: false
17
+
18
+ # Last 4 characters of the random part of the token for display
19
+ t.string :last4, null: false, limit: 4
20
+
21
+ # Optional, user-provided name for the key
22
+ t.string :name
23
+
24
+ # Who owns this key? Can be null for ownerless keys.
25
+ t.references :owner, polymorphic: true, null: true, type: foreign_key_type
26
+
27
+ # Optional list of permissions granted to this key (array of strings)
28
+ t.send(json_column_type, :scopes, default: [], null: false)
29
+
30
+ # Optional freeform metadata for tagging
31
+ t.send(json_column_type, :metadata, default: {}, null: false)
32
+
33
+ # Optional auto-expiration timestamp
34
+ t.datetime :expires_at
35
+
36
+ # Timestamp of the last successful authentication using this key
37
+ t.datetime :last_used_at
38
+
39
+ # Optional counter cache for total requests made with this key.
40
+ t.bigint :requests_count, default: 0, null: false
41
+
42
+ # Timestamp when the key was revoked (null means active)
43
+ t.datetime :revoked_at
44
+
45
+ t.timestamps
46
+
47
+ # Critical index for authentication performance
48
+ t.index :token_digest, unique: true
49
+
50
+ # Index to optimize prefix-based lookups (especially for bcrypt)
51
+ t.index [:prefix, :digest_algorithm], name: "index_api_keys_on_prefix_and_digest_algorithm"
52
+
53
+ # Optional indexes
54
+ t.index :prefix
55
+ t.index :last4 # Index potentially useful for UI lookups/filtering by masked token
56
+ t.index :owner_id if foreign_key_type # Index owner_id only if it's a separate column
57
+ t.index :owner_type if foreign_key_type # Index owner_type only if it's a separate column
58
+ t.index :expires_at
59
+ t.index :revoked_at
60
+ t.index :last_used_at
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ # Helper method to determine the appropriate primary and foreign key types
67
+ # based on the Rails application's configuration.
68
+ def primary_and_foreign_key_types
69
+ config = Rails.configuration.generators
70
+ setting = config.options[config.orm][:primary_key_type]
71
+ primary_key_type = setting || :primary_key
72
+ foreign_key_type = setting || :bigint # Assuming bigint is a safe default for foreign keys
73
+ [primary_key_type, foreign_key_type]
74
+ end
75
+
76
+ # Helper method to determine the appropriate JSON column type based on the database adapter.
77
+ # Uses :jsonb for PostgreSQL for better performance and indexing, :json otherwise.
78
+ def json_column_type
79
+ # Check connection availability for adapter name inspection
80
+ if ActiveRecord::Base.connection.adapter_name.downcase.include?('postgresql')
81
+ :jsonb
82
+ else
83
+ :json
84
+ end
85
+ rescue ActiveRecord::ConnectionNotEstablished
86
+ # Fallback during initial setup or if connection isn't available
87
+ :text
88
+ end
89
+
90
+ # Provides the appropriate migration version syntax for the current Rails version.
91
+ def migration_version
92
+ major = ActiveRecord::VERSION::MAJOR
93
+ minor = ActiveRecord::VERSION::MINOR
94
+ if major >= 5
95
+ "[#{major}.#{minor}]"
96
+ else
97
+ ""
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ ApiKeys.configure do |config|
4
+ # === Core Authentication ===
5
+
6
+ # The HTTP header name where the API key is expected.
7
+ # Default: "Authorization" (expects "Bearer <token>")
8
+ # config.header = "Authorization"
9
+
10
+ # The query parameter name to check as a fallback if the header is missing.
11
+ # Set to nil to disable query parameter lookup (recommended for security).
12
+ # Default: nil
13
+ # config.query_param = "api_key"
14
+
15
+ # === Token Generation ===
16
+
17
+ # A lambda/proc that returns the prefix for newly generated tokens.
18
+ # Defaults to "ak_".
19
+ # Once set, do NOT change or all previously generated keys may become invalid!
20
+ # config.token_prefix = -> { "ak_" }
21
+
22
+ # The number of random bytes to generate for the token (before encoding).
23
+ # More bytes = more entropy = harder to guess.
24
+ # Default: 24 (generates ~32 Base58 chars or 48 hex chars)
25
+ # config.token_length = 32
26
+
27
+ # The encoding alphabet for the random part of the token.
28
+ # :base58 (recommended) - shorter, avoids ambiguous chars (0, O, I, l)
29
+ # :hex - standard hexadecimal encoding
30
+ # Default: :base58
31
+ # config.token_alphabet = :hex
32
+
33
+ # === Storage & Verification ===
34
+
35
+ # The hashing strategy used to store token digests in the database.
36
+ # :sha256 (recommended) - fast, performant, O(1) lookups, but less secure if database is compromised (salted with prefix only)
37
+ # :bcrypt - for security-critical tokens: includes salt, computationally expensive, can cause lags, 10x-50x slower than sha256
38
+ # Default: :sha256
39
+ # config.hash_strategy = :bcrypt
40
+
41
+ # === Optional Behaviors ===
42
+
43
+ # Global limit on the number of *active* keys an owner can have.
44
+ # Can be overridden by `max_keys` in the `has_api_keys` block.
45
+ # Set to nil for no global limit.
46
+ # Default: nil
47
+ # config.default_max_keys_per_owner = 10
48
+
49
+ # If true, requires a `name` when creating keys.
50
+ # Can be overridden by `require_name` in the `has_api_keys` block.
51
+ # Default: false
52
+ # config.require_key_name = true
53
+
54
+ # Automatically expire keys after a certain period from creation.
55
+ # Set to nil for no automatic expiration.
56
+ # Default: nil
57
+ # config.expire_after = 90.days
58
+
59
+ # Default scopes to assign to newly created keys if none are specified.
60
+ # Applies globally unless overridden by `has_api_keys` in the owner model.
61
+ # Default: []
62
+ # config.default_scopes = ["read"]
63
+
64
+ # === Performance ===
65
+
66
+ # Time-to-live (TTL) for caching ApiKey lookups.
67
+ # Higher values improve performance by reducing database lookups and
68
+ # expensive comparisons (like bcrypt), but increase the delay for changes
69
+ # (like revocation or expiration) to take effect for already cached keys.
70
+ # Set to 0 or nil to disable caching.
71
+ # Uses Rails.cache.
72
+ # Default: 5.seconds
73
+ # config.cache_ttl = 30.seconds # Higher TTL = higher risk of “revoked-but-still-valid” edge cases
74
+
75
+ # === Security ===
76
+
77
+ # If true, logs a warning if the gem is used over HTTP in production.
78
+ # Default: true
79
+ # config.https_only_production = true
80
+
81
+ # If true (and https_only_production is true), raises an error instead of
82
+ # just logging a warning when used over HTTP in production.
83
+ # Default: false
84
+ # config.https_strict_mode = true
85
+
86
+ # IMPORTANT: Usage Statistics & Background Jobs
87
+ # ---------------------------------------------
88
+ # The api_keys gem executes callbacks and updates the `last_used_at` timestamp on every successful authentication
89
+ # and optionally increments `requests_count` if `track_requests_count` is true.
90
+ # To avoid blocking the request cycle, these calls and updates are performed asynchronously
91
+ # using ActiveJob (`ApiKeys::Jobs::UpdateStatsJob` and `ApiKeys::Jobs::CallbacksJob`)
92
+ #
93
+ # *** For callbacks to be executed, and for reliable and performant usage statistics, you MUST configure a persistent
94
+ # ActiveJob backend adapter in your Rails app! (e.g., Sidekiq, GoodJob, SolidQueue, Resque, Delayed::Job). ***
95
+ #
96
+ # - Using the default :async adapter is NOT recommended for production as updates
97
+ # run in-process and may be lost if the application restarts unexpectedly.
98
+ # - Using the :inline adapter will perform updates synchronously within the request,
99
+ # negating the performance benefits and potentially slowing down responses.
100
+ #
101
+ # If you do not have a persistent background job system configured, callbacks won't fire and stats updates
102
+ # might be unreliable or impact performance. Consider disabling `track_requests_count` and avoid using callbacks
103
+ # if you cannot use a persistent backend and performance is critical.
104
+
105
+ # === Background Job Queues ===
106
+
107
+ # Configure the ActiveJob queue name for processing API key usage statistics.
108
+ # Default: :default
109
+ # config.stats_job_queue = :api_keys_stats
110
+
111
+ # Configure the ActiveJob queue name for processing asynchronous callbacks.
112
+ # Default: :default
113
+ # config.callbacks_job_queue = :api_keys_callbacks
114
+
115
+ # === Global Async Toggle ===
116
+
117
+ # Set to false to completely disable all background job enqueueing performed
118
+ # by this gem (stats updates and callbacks). If false, `last_used_at`,
119
+ # `requests_count`, and configured callbacks will NOT be processed.
120
+ # Useful if you handle these concerns externally or cannot use ActiveJob.
121
+ # Default: true
122
+ # config.enable_async_operations = false
123
+
124
+ # === Usage Statistics ===
125
+
126
+ # If true, automatically update `last_used_at` and increment `requests_count`
127
+ # on the ApiKey record upon successful authentication.
128
+ # Note: Incrementing counters frequently can impact DB performance.
129
+ # Default: false
130
+ # config.track_requests_count = true
131
+
132
+ # === Callbacks ===
133
+
134
+ # A lambda/proc to run *before* token extraction and verification.
135
+ # Receives the request object.
136
+ # Default: ->(request) { }
137
+ # config.before_authentication = ->(request) { Rails.logger.info "Authenticating request: #{request.uuid}" }
138
+
139
+ # A lambda/proc to run *after* authentication attempt (success or failure).
140
+ # Receives the ApiKeys::Services::Authenticator::Result object.
141
+ # Default: ->(result) { }
142
+ # config.after_authentication = ->(result) { MyAnalytics.track_auth(result) }
143
+
144
+ # === Engine UI Configuration ===
145
+
146
+ # The URL or path helper method (as a string) to link back to from the engine's UI.
147
+ # Useful when embedding the engine within a larger application context.
148
+ # Default: "/" (Root path)
149
+ # config.return_url = "/app/settings"
150
+
151
+ # The text displayed for the return link.
152
+ # Default: "‹ Home"
153
+ # config.return_text = "‹ Back to Settings"
154
+
155
+ # === Debugging ===
156
+
157
+ # Enable verbose logging for debugging purposes.
158
+ # Default: false
159
+ # config.debug_logging = true
160
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: api_keys
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - rameerez
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 2025-04-30 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rails
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '6.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '6.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: activerecord
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '6.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '6.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: activesupport
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '6.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '6.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: base58
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.2'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.2'
68
+ - !ruby/object:Gem::Dependency
69
+ name: bcrypt
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.1'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.1'
82
+ - !ruby/object:Gem::Dependency
83
+ name: bundler
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '2.0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '2.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rake
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '13.0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '13.0'
110
+ description: Add secure, production-ready API key authentication to your Rails app
111
+ in minutes. Handles key generation, hashing, expiration, revocation, per-key scopes;
112
+ plus a drop-in dashboard for your users to self-issue and manage their own API keys.
113
+ email:
114
+ - rubygems@rameerez.com
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - CHANGELOG.md
120
+ - LICENSE.txt
121
+ - README.md
122
+ - Rakefile
123
+ - api_keys_dashboard.webp
124
+ - api_keys_permissions.webp
125
+ - api_keys_token.webp
126
+ - app/controllers/api_keys/application_controller.rb
127
+ - app/controllers/api_keys/keys_controller.rb
128
+ - app/controllers/api_keys/security_controller.rb
129
+ - app/views/api_keys/keys/_form.html.erb
130
+ - app/views/api_keys/keys/_key_row.html.erb
131
+ - app/views/api_keys/keys/_keys_table.html.erb
132
+ - app/views/api_keys/keys/_show_token.html.erb
133
+ - app/views/api_keys/keys/edit.html.erb
134
+ - app/views/api_keys/keys/index.html.erb
135
+ - app/views/api_keys/keys/new.html.erb
136
+ - app/views/api_keys/keys/show.html.erb
137
+ - app/views/api_keys/security/best_practices.html.erb
138
+ - app/views/layouts/api_keys/application.html.erb
139
+ - config/routes.rb
140
+ - lib/api_keys.rb
141
+ - lib/api_keys/authentication.rb
142
+ - lib/api_keys/configuration.rb
143
+ - lib/api_keys/controller.rb
144
+ - lib/api_keys/engine.rb
145
+ - lib/api_keys/jobs/callbacks_job.rb
146
+ - lib/api_keys/jobs/update_stats_job.rb
147
+ - lib/api_keys/logging.rb
148
+ - lib/api_keys/models/api_key.rb
149
+ - lib/api_keys/models/concerns/has_api_keys.rb
150
+ - lib/api_keys/services/authenticator.rb
151
+ - lib/api_keys/services/digestor.rb
152
+ - lib/api_keys/services/token_generator.rb
153
+ - lib/api_keys/tenant_resolution.rb
154
+ - lib/api_keys/version.rb
155
+ - lib/generators/api_keys/install_generator.rb
156
+ - lib/generators/api_keys/templates/create_api_keys_table.rb.erb
157
+ - lib/generators/api_keys/templates/initializer.rb
158
+ homepage: https://github.com/rameerez/api_keys
159
+ licenses:
160
+ - MIT
161
+ metadata:
162
+ allowed_push_host: https://rubygems.org
163
+ homepage_uri: https://apikeys.rameerez.com
164
+ source_code_uri: https://github.com/rameerez/api_keys
165
+ changelog_uri: https://github.com/rameerez/api_keys/blob/main/CHANGELOG.md
166
+ rubygems_mfa_required: 'true'
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: 3.1.0
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubygems_version: 3.6.2
182
+ specification_version: 4
183
+ summary: Gate your Rails API with secure, self-serve API keys in minutes
184
+ test_files: []