api_keys 0.2.1 → 0.4.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/CHANGELOG.md +60 -0
- data/README.md +851 -25
- data/SECURITY.md +33 -0
- data/app/controllers/api_keys/application_controller.rb +58 -10
- data/app/controllers/api_keys/keys_controller.rb +77 -23
- 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 +33 -4
- 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 +3 -11
- 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 +10 -47
- 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/keys/show.html.erb +2 -2
- data/app/views/api_keys/security/best_practices.html.erb +73 -47
- data/app/views/layouts/api_keys/application.html.erb +267 -14
- data/lib/api_keys/authentication.rb +39 -11
- data/lib/api_keys/configuration.rb +444 -17
- data/lib/api_keys/engine.rb +5 -20
- data/lib/api_keys/errors.rb +73 -0
- data/lib/api_keys/form_builder_extensions.rb +168 -0
- data/lib/api_keys/helpers/expiration_options.rb +139 -0
- data/lib/api_keys/helpers/token_session.rb +203 -0
- data/lib/api_keys/helpers/view_helpers.rb +220 -0
- data/lib/api_keys/jobs/callbacks_job.rb +10 -17
- data/lib/api_keys/jobs/update_stats_job.rb +27 -12
- data/lib/api_keys/models/api_key.rb +452 -21
- data/lib/api_keys/models/concerns/has_api_keys.rb +269 -26
- data/lib/api_keys/services/authenticator.rb +300 -112
- data/lib/api_keys/services/digestor.rb +81 -14
- data/lib/api_keys/services/token_generator.rb +41 -1
- data/lib/api_keys/tenant_resolution.rb +4 -4
- data/lib/api_keys/version.rb +1 -1
- data/lib/api_keys.rb +12 -0
- data/lib/generators/api_keys/add_authentication_index_generator.rb +36 -0
- data/lib/generators/api_keys/add_key_types_generator.rb +68 -0
- data/lib/generators/api_keys/templates/add_authentication_index_to_api_keys.rb.erb +32 -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 +11 -3
- data/lib/generators/api_keys/templates/initializer.rb +261 -120
- metadata +29 -63
- data/Rakefile +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3183ee0be98a005fd2fc318937f9f8aeb6d8a6c0528a0b75d7234e55cde80480
|
|
4
|
+
data.tar.gz: 67080c1cddf08ee647657c8845a9332c61279249d8c9765ea0ad6fda4e4961a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff1adbe9b462443d7f278013030780bfc99ec2ef5acb6a814966a3530950147069bf33cc79d3d35ae8f6af8f76bf43b3a9a42d9692e22f9757df3c172b186535
|
|
7
|
+
data.tar.gz: 6f3f9febcd26069d345739d6268c8bcd4acce174ccdd2c24f915c8cfabf5404c2aa708e3538219ad8be30c8392d633101a6f1e52d7b099e123bf01474511859e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,63 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [0.4.0] - 2026-08-09
|
|
4
|
+
|
|
5
|
+
This security-focused release hardens authentication, authorization, credential handling, the self-serve dashboard, background jobs, configuration, dependencies, CI, and the release supply chain. Upgrading is strongly recommended. Existing installations must apply the authentication lookup migration before deploying this version.
|
|
6
|
+
|
|
7
|
+
### Security
|
|
8
|
+
|
|
9
|
+
- Make token caching a non-authoritative ID lookup hint: every hit reloads current database state and cryptographically re-verifies the presented token, so revocation, expiration, scope changes, and cache poisoning fail closed.
|
|
10
|
+
- Replace token-derived SHA1 cache identifiers with SHA256 and prevent plaintext tokens, digests, stored public tokens, request objects, and authentication result objects from leaking through gem logs, inspection, serialization, errors, or async callback arguments.
|
|
11
|
+
- Bound token sizes, bcrypt input length, bcrypt cost, and bcrypt candidate work; add an indexed prefix/last-four/algorithm lookup for existing installations.
|
|
12
|
+
- Bound historical-prefix discovery and fall back to an indexed last-four lookup so cache poisoning or unusually many retired prefixes cannot create unbounded request work or strand valid bcrypt keys.
|
|
13
|
+
- Serialize all quota checks and inserts by locking the owner row, including direct Active Record creation paths.
|
|
14
|
+
- Enforce immutable authentication identity fields, supported digest formats, bounded scopes/metadata/identifiers/session payloads, runtime permission ceilings, configured key types, and fail-closed environment isolation.
|
|
15
|
+
- Require every newly created key to have a configured type once key-types mode is enabled; existing untyped legacy keys remain compatible.
|
|
16
|
+
- Require explicit finite permissions and `revocable: false` for intentionally stored public tokens.
|
|
17
|
+
- Fail closed when dashboard owner authentication is missing or ineffective; bind one-time session tokens to their created key; reject malformed create/update payloads; scope every dashboard lookup to the current owner; and add no-store, anti-framing, referrer, MIME-sniffing, and permissions headers.
|
|
18
|
+
- Apply an enforcing nonce-based dashboard Content Security Policy and remove inline handlers, un-nonced scripts, third-party assets, and inline style attributes from credential-bearing views.
|
|
19
|
+
- Enforce HTTPS authentication by default in production, disable query-string credentials in the demo, and remove third-party code from pages that handle tokens.
|
|
20
|
+
- Pin GitHub Actions to immutable commits and add dependency auditing, Brakeman, CodeQL, dependency review, and Dependabot configuration.
|
|
21
|
+
- Remove the unused Claude Code workflow and its third-party CI/OIDC surface.
|
|
22
|
+
- Encrypt one-time secret-token handoffs inside the Rails session with an application-derived AES-256-GCM key, bind them to the created key, expire them after ten minutes, and delete them on first retrieval. Legacy in-flight plaintext handoffs remain readable for upgrade continuity but are never newly written.
|
|
23
|
+
|
|
24
|
+
### Reliability
|
|
25
|
+
|
|
26
|
+
- Execute authentication callbacks exactly once with serializable, credential-free context hashes.
|
|
27
|
+
- Resolve job queues dynamically, prevent out-of-order/future jobs from corrupting usage timestamps, and keep request counters atomic.
|
|
28
|
+
- Validate security-sensitive global and per-owner configuration early and store permission policy as defensive frozen copies.
|
|
29
|
+
- Ensure each appraisal excludes the next Rails line's prereleases; Rails 7.2 uses its upstream-compatible Minitest 5 while Rails 8/default suites remain on Minitest 6.
|
|
30
|
+
- Return `403 Forbidden` when a valid key lacks a required scope while retaining `401 Unauthorized` for missing or invalid credentials.
|
|
31
|
+
- Honor the public `parent_controller` configuration (with a backward-compatible internal Engine fallback), cascade owner deletion across non-revocable keys, and debounce `last_used_at` jobs for one minute by default when exact request counting is disabled.
|
|
32
|
+
- Remove redundant single-column polymorphic-owner indexes from new-install migrations and exclude development-only metadata from built gems.
|
|
33
|
+
- Resolve every finding recorded in [issue #12](https://github.com/rameerez/api_keys/issues/12) through a code fix, test, explicit bounded design, or superseding hardening control.
|
|
34
|
+
|
|
35
|
+
### Upgrade notes
|
|
36
|
+
|
|
37
|
+
- Existing installations should run `rails generate api_keys:add_authentication_index` and `rails db:migrate` before deploying this version.
|
|
38
|
+
- Invalid expiration presets now raise `ArgumentError` instead of silently creating a key without expiration.
|
|
39
|
+
- Authentication identity fields (`token_digest`, algorithm, prefix, last four, owner, key type, and environment) can no longer be changed through normal Active Record updates after creation.
|
|
40
|
+
- Typed keys with blank or retired environments now fail closed. Repair any such legacy rows before deployment; untyped legacy keys are unaffected.
|
|
41
|
+
- When `key_types` is configured, new keys must pass `key_type:` or use a configured `default_key_type`; this does not invalidate existing untyped keys.
|
|
42
|
+
- Authentication callbacks now execute asynchronously exactly once with small, credential-free context hashes instead of request, result, or model objects. Update callback consumers and ensure the application has a durable Active Job backend where delivery matters.
|
|
43
|
+
- Production authentication now requires HTTPS by default and fails closed when a request appears insecure. Verify TLS termination and trusted proxy forwarding before deployment.
|
|
44
|
+
- Scope and permission policy is enforced at creation, update, and authentication time. Malformed scopes and scopes above a configured ceiling are rejected; blank scopes deny access whenever a scope policy is enabled.
|
|
45
|
+
- Reassess every permission ceiling configured with `public: true`. The gem validates that public tokens are non-revocable and finitely scoped, but only the host application can determine whether each named permission is safe for an untrusted client.
|
|
46
|
+
- The actively security-tested matrix is Ruby 3.3, 3.4, and 4.0 with Rails 7.2, 8.0, and 8.1. The gemspec continues to permit Ruby 3.1+ for compatibility, but older runtimes are outside the documented security-support matrix.
|
|
47
|
+
- Missing-scope responses now use HTTP 403 instead of 401. Clients that branch on the previous status should update.
|
|
48
|
+
- New one-time token handoffs are encrypted and expire after ten minutes. Custom integrations must use `ApiKeys::TokenSession` rather than reading its internal session payload directly.
|
|
49
|
+
- `last_used_at` updates are debounced for one minute by default when `track_requests_count` is false. Set `stats_update_interval = 0` for per-request timestamps; enabling exact request counting necessarily enqueues a stats job for every successful authentication.
|
|
50
|
+
- Deleting an owner now removes all associated API-key rows, including non-revocable types. Direct user-level `revoke!`, `destroy`, and `destroy!` protections remain unchanged.
|
|
51
|
+
|
|
52
|
+
## [0.3.0] - 2026-02-09
|
|
53
|
+
|
|
54
|
+
- Add Stripe-style key types and environments (publishable/secret keys with test/live isolation)
|
|
55
|
+
- Add public key token storage for non-revocable publishable keys
|
|
56
|
+
- Add headless helpers for custom dashboard integrations
|
|
57
|
+
- Add usage analytics scopes for admin dashboards
|
|
58
|
+
- Fix PostgreSQL FOR UPDATE with COUNT aggregate error
|
|
59
|
+
- Fix blank scopes bypass in key_types mode: empty scopes no longer grant unrestricted access when permission ceilings are configured
|
|
60
|
+
|
|
1
61
|
## [0.2.1] - 2025-08-04
|
|
2
62
|
|
|
3
63
|
- Fix SecurityController callback reference from :authenticate_api_keys_user! to :authenticate_api_keys_owner!
|