verikloak-rails 0.3.2 → 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 +24 -0
- data/README.md +7 -5
- data/lib/generators/verikloak/install/install_generator.rb +1 -1
- data/lib/verikloak/rails/bff_configurator.rb +6 -1
- data/lib/verikloak/rails/configuration.rb +5 -2
- data/lib/verikloak/rails/controller.rb +7 -7
- data/lib/verikloak/rails/error_renderer.rb +10 -14
- data/lib/verikloak/rails/railtie.rb +16 -2
- data/lib/verikloak/rails/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2cf09e4cda410ff55efd34d8e2fb24fa78241de47f3c5cd8942deaca6e83db4
|
|
4
|
+
data.tar.gz: 8f8ee287a51d3a39e7807b70b4d11c42090de231b898e9eea07b221b518b8f63
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dbb93e90c1408dce20360f186a6a59bb4f47a62db569656279c311c01d1623e6f894709d5ccd73b0df32e3a4e3351bb90a598074ae6ec3a8b9d31c2187a1b937
|
|
7
|
+
data.tar.gz: b51e2a247c8ca1a145b768e5d59762675669d5ab1b6556ac738197a611fd0c8e925d193d7308c8522f4b072c8645aa93f947a61993b1045f57d803a8903e6c78
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.4.0] - 2026-02-15
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
- **Header sanitization**: `ErrorRenderer` now delegates to `Verikloak::ErrorResponse.sanitize_header_value` — strips all control characters (`[[:cntrl:]]`), not just CR/LF, consistent with core gem
|
|
14
|
+
- **Request-ID sanitization**: Log tag builder strengthened from `/[\r\n]+/` to `/[[:cntrl:]]+/` to block all control characters in tagged logging
|
|
15
|
+
- **BFF configurator hardening**: `public_send` in `BffConfigurator` is now guarded with a whitelist — rejects keys starting with `_` or containing `!` to prevent accidental invocation of non-accessor methods
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **`with_required_audience!`**: Was passing two positional arguments to `Error.new` (`'forbidden', 'message'`), which raises `ArgumentError` with core gem 0.4.0's keyword-arg signature. Now uses `Error.new('Required audience not satisfied', code: 'forbidden')`
|
|
19
|
+
- **`authenticate_user!`**: Was passing `Error.new('unauthorized')` which set `code` to `nil` (message became `'unauthorized'` but code was unset). Now uses `Error.new('Unauthorized', code: 'unauthorized')` for correct error rendering
|
|
20
|
+
- Test stubs updated to match core gem's keyword-arg `Error.new(message, code:, http_status:)` signature
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- `allow_http` configuration option — forwarded to core `Verikloak::Middleware` for development/test environments where HTTPS is unavailable
|
|
24
|
+
- Logger cycle detection using `Set` guard in `_verikloak_base_logger` to prevent infinite loops with circular logger chains
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- **BREAKING**: Minimum `verikloak` dependency raised to `>= 0.4.0` (keyword-arg `Error.new` signature)
|
|
28
|
+
- Dev dependency `rspec` pinned to `~> 3.13`, `rubocop-rspec` pinned to `~> 3.9`
|
|
29
|
+
- Extracted `auto_disable_rescue_pundit` method from `apply_configuration` in Railtie for clarity and testability
|
|
30
|
+
- Removed `sanitize_quoted` private method from `ErrorRenderer` in favor of shared `Verikloak::ErrorResponse.sanitize_header_value`
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
10
34
|
## [0.3.2] - 2026-01-01
|
|
11
35
|
|
|
12
36
|
### Changed
|
data/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Provide drop-in, token-based authentication for Rails APIs via Verikloak (OIDC d
|
|
|
21
21
|
## Compatibility
|
|
22
22
|
- Ruby: >= 3.1
|
|
23
23
|
- Rails: 6.1 – 8.x
|
|
24
|
-
- verikloak: >= 0.
|
|
24
|
+
- verikloak: >= 0.4.0, < 1.0.0
|
|
25
25
|
|
|
26
26
|
## Quick Start
|
|
27
27
|
```bash
|
|
@@ -168,6 +168,7 @@ Keys under `config.verikloak`:
|
|
|
168
168
|
| `token_env_key` | String | Custom Rack env key that stores the Bearer token | `nil` (middleware default `verikloak.token`) |
|
|
169
169
|
| `user_env_key` | String | Custom Rack env key that stores decoded claims | `nil` (middleware default `verikloak.user`) |
|
|
170
170
|
| `bff_header_guard_options` | Hash or Proc | Forwarded to `Verikloak::BFF.configure` prior to middleware insertion | `{}` |
|
|
171
|
+
| `allow_http` | Boolean | Allow `http://` discovery URLs (forwarded to core middleware). **Only for development/test.** | `false` |
|
|
171
172
|
|
|
172
173
|
Environment variable examples are in the generated initializer.
|
|
173
174
|
|
|
@@ -266,14 +267,15 @@ Rails.application.configure do
|
|
|
266
267
|
end
|
|
267
268
|
```
|
|
268
269
|
|
|
269
|
-
Note: Always sanitize values placed into `WWW-Authenticate` header parameters to avoid header injection.
|
|
270
|
+
Note: Always sanitize values placed into `WWW-Authenticate` header parameters to avoid header injection. You can use the shared helper from the core gem:
|
|
270
271
|
|
|
271
272
|
```ruby
|
|
272
273
|
class CompactErrorRenderer
|
|
273
274
|
private
|
|
274
|
-
def
|
|
275
|
-
#
|
|
276
|
-
|
|
275
|
+
def sanitize(val)
|
|
276
|
+
# Delegates to core gem's sanitizer — escapes quotes/backslashes,
|
|
277
|
+
# truncates at CRLF, and strips all control characters.
|
|
278
|
+
Verikloak::ErrorResponse.sanitize_header_value(val)
|
|
277
279
|
end
|
|
278
280
|
end
|
|
279
281
|
```
|
|
@@ -26,7 +26,7 @@ module Verikloak
|
|
|
26
26
|
✅ verikloak: initializer created.
|
|
27
27
|
|
|
28
28
|
Next steps:
|
|
29
|
-
1) Ensure the base gem is installed: gem 'verikloak', '>= 0.
|
|
29
|
+
1) Ensure the base gem is installed: gem 'verikloak', '>= 0.4.0', '< 1.0.0'
|
|
30
30
|
2) Set discovery_url / audience in config/initializers/verikloak.rb
|
|
31
31
|
3) (Optional) If you disable auto-include, add this line to ApplicationController:
|
|
32
32
|
include Verikloak::Rails::Controller
|
|
@@ -103,7 +103,12 @@ module Verikloak
|
|
|
103
103
|
target.configure do |config|
|
|
104
104
|
entries.each do |key, value|
|
|
105
105
|
writer = "#{key}="
|
|
106
|
-
|
|
106
|
+
# Guard: only call known attr_accessor writers to prevent
|
|
107
|
+
# accidental invocation of arbitrary public methods.
|
|
108
|
+
next unless config.respond_to?(writer)
|
|
109
|
+
next if key.to_s.start_with?('_') || key.to_s.include?('!')
|
|
110
|
+
|
|
111
|
+
config.public_send(writer, value)
|
|
107
112
|
end
|
|
108
113
|
end
|
|
109
114
|
end
|
|
@@ -61,7 +61,8 @@ module Verikloak
|
|
|
61
61
|
:auto_insert_bff_header_guard,
|
|
62
62
|
:bff_header_guard_insert_before, :bff_header_guard_insert_after,
|
|
63
63
|
:token_verify_options, :decoder_cache_limit,
|
|
64
|
-
:token_env_key, :user_env_key, :bff_header_guard_options
|
|
64
|
+
:token_env_key, :user_env_key, :bff_header_guard_options,
|
|
65
|
+
:allow_http
|
|
65
66
|
|
|
66
67
|
# Initialize configuration with sensible defaults for Rails apps.
|
|
67
68
|
# @return [void]
|
|
@@ -86,6 +87,7 @@ module Verikloak
|
|
|
86
87
|
@token_env_key = nil
|
|
87
88
|
@user_env_key = nil
|
|
88
89
|
@bff_header_guard_options = {}
|
|
90
|
+
@allow_http = false
|
|
89
91
|
end
|
|
90
92
|
|
|
91
93
|
# Options forwarded to the base Verikloak Rack middleware.
|
|
@@ -103,7 +105,8 @@ module Verikloak
|
|
|
103
105
|
token_verify_options: token_verify_options,
|
|
104
106
|
decoder_cache_limit: decoder_cache_limit,
|
|
105
107
|
token_env_key: token_env_key,
|
|
106
|
-
user_env_key: user_env_key
|
|
108
|
+
user_env_key: user_env_key,
|
|
109
|
+
allow_http: allow_http
|
|
107
110
|
}.compact
|
|
108
111
|
end
|
|
109
112
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'active_support/concern'
|
|
4
|
+
require 'set'
|
|
4
5
|
|
|
5
6
|
module Verikloak
|
|
6
7
|
module Rails
|
|
@@ -43,11 +44,7 @@ module Verikloak
|
|
|
43
44
|
def authenticate_user!
|
|
44
45
|
return if authenticated?
|
|
45
46
|
|
|
46
|
-
e =
|
|
47
|
-
::Verikloak::Error.new('unauthorized')
|
|
48
|
-
rescue StandardError
|
|
49
|
-
StandardError.new('Unauthorized')
|
|
50
|
-
end
|
|
47
|
+
e = ::Verikloak::Error.new('Unauthorized', code: 'unauthorized')
|
|
51
48
|
Verikloak::Rails.config.error_renderer.render(self, e)
|
|
52
49
|
end
|
|
53
50
|
|
|
@@ -84,7 +81,7 @@ module Verikloak
|
|
|
84
81
|
aud = Array(current_user_claims&.dig('aud'))
|
|
85
82
|
return if required.flatten.all? { |r| aud.include?(r) }
|
|
86
83
|
|
|
87
|
-
raise ::Verikloak::Error.new('
|
|
84
|
+
raise ::Verikloak::Error.new('Required audience not satisfied', code: 'forbidden')
|
|
88
85
|
end
|
|
89
86
|
|
|
90
87
|
private
|
|
@@ -108,7 +105,7 @@ module Verikloak
|
|
|
108
105
|
tags = []
|
|
109
106
|
if config.logger_tags.include?(:request_id)
|
|
110
107
|
rid = request.request_id || request.headers['X-Request-Id']
|
|
111
|
-
rid = rid.to_s.gsub(/[
|
|
108
|
+
rid = rid.to_s.gsub(/[[:cntrl:]]+/, ' ').strip
|
|
112
109
|
tags << "req:#{rid}" unless rid.empty?
|
|
113
110
|
end
|
|
114
111
|
if config.logger_tags.include?(:sub)
|
|
@@ -164,7 +161,10 @@ module Verikloak
|
|
|
164
161
|
logger
|
|
165
162
|
end
|
|
166
163
|
current = root_logger
|
|
164
|
+
seen = Set.new
|
|
167
165
|
while current.respond_to?(:logger)
|
|
166
|
+
break unless seen.add?(current.object_id)
|
|
167
|
+
|
|
168
168
|
next_logger = current.logger
|
|
169
169
|
break if next_logger.nil? || next_logger.equal?(current)
|
|
170
170
|
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'verikloak/error_response'
|
|
4
|
+
|
|
3
5
|
module Verikloak
|
|
4
6
|
module Rails
|
|
5
7
|
# Renders JSON errors for authentication/authorization failures.
|
|
6
8
|
#
|
|
7
9
|
# When status is 401, adds a `WWW-Authenticate: Bearer` header including
|
|
8
10
|
# `error` and `error_description` fields when available.
|
|
11
|
+
#
|
|
12
|
+
# Header sanitization is delegated to {Verikloak::ErrorResponse} to ensure
|
|
13
|
+
# consistent control-character stripping across all Verikloak gems.
|
|
9
14
|
class ErrorRenderer
|
|
10
15
|
DEFAULT_STATUS_MAP = {
|
|
11
16
|
'invalid_token' => 401,
|
|
@@ -67,6 +72,8 @@ module Verikloak
|
|
|
67
72
|
end
|
|
68
73
|
|
|
69
74
|
# Build WWW-Authenticate headers when returning 401 responses.
|
|
75
|
+
# Delegates sanitization to {Verikloak::ErrorResponse.sanitize_header_value}
|
|
76
|
+
# to ensure control-character stripping is consistent with the core gem.
|
|
70
77
|
# @param status [Integer]
|
|
71
78
|
# @param code [String, nil]
|
|
72
79
|
# @param message [String]
|
|
@@ -74,23 +81,12 @@ module Verikloak
|
|
|
74
81
|
def auth_headers(status, code, message)
|
|
75
82
|
return {} unless status == 401
|
|
76
83
|
|
|
84
|
+
sanitize = ->(v) { Verikloak::ErrorResponse.sanitize_header_value(v) }
|
|
77
85
|
header = +'Bearer'
|
|
78
|
-
header << %( error="#{
|
|
79
|
-
header << %( error_description="#{
|
|
86
|
+
header << %( error="#{sanitize.call(code)}") if code
|
|
87
|
+
header << %( error_description="#{sanitize.call(message)}") if message
|
|
80
88
|
{ 'WWW-Authenticate' => header }
|
|
81
89
|
end
|
|
82
|
-
|
|
83
|
-
# Sanitize a value for inclusion inside a quoted HTTP header parameter.
|
|
84
|
-
# Escapes quotes and backslashes, and strips CR/LF to prevent header injection.
|
|
85
|
-
# Why block replacement? String replacements like '\\1' are parsed as
|
|
86
|
-
# backreferences/escapes in Ruby, making precise escaping error‑prone.
|
|
87
|
-
# The block receives the literal match and we return it prefixed with a
|
|
88
|
-
# backslash, guaranteeing predictable escaping for both " and \\.
|
|
89
|
-
# @param val [String]
|
|
90
|
-
# @return [String]
|
|
91
|
-
def sanitize_quoted(val)
|
|
92
|
-
val.to_s.gsub(/(["\\])/) { |m| "\\#{m}" }.gsub(/[\r\n]+/, ' ')
|
|
93
|
-
end
|
|
94
90
|
end
|
|
95
91
|
end
|
|
96
92
|
end
|
|
@@ -20,7 +20,7 @@ module Verikloak
|
|
|
20
20
|
middleware_insert_after auto_insert_bff_header_guard
|
|
21
21
|
bff_header_guard_insert_before bff_header_guard_insert_after
|
|
22
22
|
token_verify_options decoder_cache_limit token_env_key user_env_key
|
|
23
|
-
bff_header_guard_options
|
|
23
|
+
bff_header_guard_options allow_http
|
|
24
24
|
].freeze
|
|
25
25
|
|
|
26
26
|
config.verikloak = ActiveSupport::OrderedOptions.new
|
|
@@ -100,10 +100,24 @@ module Verikloak
|
|
|
100
100
|
CONFIG_KEYS.each do |key|
|
|
101
101
|
c.send("#{key}=", rails_cfg[key]) if rails_cfg.key?(key)
|
|
102
102
|
end
|
|
103
|
-
c
|
|
103
|
+
auto_disable_rescue_pundit(c, rails_cfg)
|
|
104
104
|
end
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
+
# When verikloak-pundit is loaded and the user has not explicitly set
|
|
108
|
+
# rescue_pundit, disable the built-in Pundit rescue to avoid
|
|
109
|
+
# double-handling errors.
|
|
110
|
+
#
|
|
111
|
+
# @param config [Verikloak::Rails::Configuration]
|
|
112
|
+
# @param rails_cfg [ActiveSupport::OrderedOptions]
|
|
113
|
+
# @return [void]
|
|
114
|
+
def auto_disable_rescue_pundit(config, rails_cfg)
|
|
115
|
+
return if rails_cfg.key?(:rescue_pundit)
|
|
116
|
+
return unless defined?(::Verikloak::Pundit)
|
|
117
|
+
|
|
118
|
+
config.rescue_pundit = false
|
|
119
|
+
end
|
|
120
|
+
|
|
107
121
|
# Insert the base Verikloak::Middleware into the application middleware stack.
|
|
108
122
|
# Respects the configured insertion point (before or after specified middleware).
|
|
109
123
|
#
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: verikloak-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- taiyaky
|
|
@@ -55,7 +55,7 @@ dependencies:
|
|
|
55
55
|
requirements:
|
|
56
56
|
- - ">="
|
|
57
57
|
- !ruby/object:Gem::Version
|
|
58
|
-
version: 0.
|
|
58
|
+
version: 0.4.0
|
|
59
59
|
- - "<"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
61
|
version: 1.0.0
|
|
@@ -65,7 +65,7 @@ dependencies:
|
|
|
65
65
|
requirements:
|
|
66
66
|
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 0.
|
|
68
|
+
version: 0.4.0
|
|
69
69
|
- - "<"
|
|
70
70
|
- !ruby/object:Gem::Version
|
|
71
71
|
version: 1.0.0
|
|
@@ -96,7 +96,7 @@ metadata:
|
|
|
96
96
|
source_code_uri: https://github.com/taiyaky/verikloak-rails
|
|
97
97
|
changelog_uri: https://github.com/taiyaky/verikloak-rails/blob/main/CHANGELOG.md
|
|
98
98
|
bug_tracker_uri: https://github.com/taiyaky/verikloak-rails/issues
|
|
99
|
-
documentation_uri: https://rubydoc.info/gems/verikloak-rails/0.
|
|
99
|
+
documentation_uri: https://rubydoc.info/gems/verikloak-rails/0.4.0
|
|
100
100
|
rubygems_mfa_required: 'true'
|
|
101
101
|
rdoc_options: []
|
|
102
102
|
require_paths:
|