Class: StandardId::Engine
- Inherits:
-
Rails::Engine
- Object
- Rails::Engine
- StandardId::Engine
- Defined in:
- lib/standard_id/engine.rb
Class Method Summary collapse
-
.verify_host_cookie_encryption!(app) ⇒ Object
Defensive check: StandardId’s Web::SessionManager stores session tokens in ‘cookies.encrypted` in addition to `session`.
-
.warn_if_allowed_audiences_empty_in_production! ⇒ Object
Logs a production-only warning when no global audience allow-list is configured.
Class Method Details
.verify_host_cookie_encryption!(app) ⇒ Object
Defensive check: StandardId’s Web::SessionManager stores session tokens in ‘cookies.encrypted` in addition to `session`. If the host app is somehow missing a secret_key_base, encrypted cookies fall back to plaintext and session tokens leak to the client. Rails 8 apps always have a secret_key_base, but this check catches misconfigured test harnesses, custom boot sequences, and host apps that blank it out.
We warn (not raise) to avoid breaking apps that intentionally short- circuit boot (e.g., ‘assets:precompile` rake tasks with no secrets available). A hard failure would be hostile to those workflows.
IMPORTANT: we must NOT call ‘app.secret_key_base` directly. Rails 8.1’s getter runs the “generate + persist” path on first read, which in turn invokes the setter — and the setter raises when the resolved value is blank (which is exactly the case this check is meant to warn about). So calling the getter here would turn a soft warning into a hard boot failure under parallel workers (e.g. parallel_rspec’s ‘parallel:create`) that don’t share a generated key between processes. Instead we read the same underlying sources Rails resolves from (ENV, then credentials) without triggering the write path.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/standard_id/engine.rb', line 72 def self.(app) secret = host_secret_key_base(app) if secret.blank? Rails.logger.warn( "[StandardId] Host application has no secret_key_base configured. " \ "Encrypted cookies will not be available and session tokens stored in " \ "cookies.encrypted will be persisted in plaintext. Configure " \ "Rails.application.credentials.secret_key_base (or ENV['SECRET_KEY_BASE']) " \ "before running in production." ) end end |
.warn_if_allowed_audiences_empty_in_production! ⇒ Object
Logs a production-only warning when no global audience allow-list is configured. With ‘allowed_audiences` empty, the API token manager skips decode-time aud enforcement, leaving cross-audience JWT replay mitigation dependent on per-controller `AudienceVerification` inclusion. Extracted to a module method so specs can exercise it directly without booting a second Rails app.
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/standard_id/engine.rb', line 113 def self.warn_if_allowed_audiences_empty_in_production! return unless Rails.env.production? return if StandardId.config.oauth.allowed_audiences.present? Rails.logger.warn( "StandardId: config.oauth.allowed_audiences is empty in production — " \ "JWT audience is not enforced globally. Set this to your expected " \ "audiences (e.g., ['web', 'api']) to close cross-audience replay vectors." ) end |