verikloak-bff 0.2.3 → 0.2.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e2d5b0966fddd564dcd1b6e48fb871f3239542204176f0291f4249f5770b713
4
- data.tar.gz: c1f1c43a58c7428263757d2f051c3f988921d84b30fc5fbdc8995f0c5d55ef4c
3
+ metadata.gz: b024a1e87d9a4cd895b0e052ba276cbf418b50d4f51b3f642d3916e7b713253e
4
+ data.tar.gz: 82bab8741e03c8b1f57bea89856b8811440c34778470c18a82c87c279a36c4a4
5
5
  SHA512:
6
- metadata.gz: a4c8c80a0fccd793d93b2ef98374fd0bca253d5a36ff4d690dbd67de622bebd92ad27ef141d3c65c56ddd8c1934b9e9818a51eb3ef0a40b780ad0bc491263503
7
- data.tar.gz: 339f5c58833ebb8ef19b511725c3f540e7506f097032235852088e0594dc917702723f8084f1abbdfd050b41f738486665d1c8b93891fb9fc7293c31d6e0483d
6
+ metadata.gz: c2e1f2587d253acd2ac1f3a26b33d701adbe7cce48a6646f95658bd503e5238033bd855ab39fe23dc8ebb85af5bbb449b6170acba6e5bb840e8878afcd9e9d79
7
+ data.tar.gz: ecf08756e3af68c6d199ff54e40f10aee69a0a5c62d49cde1c5b1bd732dc319510490131e9a0ea357c82b67af7710ba7bd4a7303549b842b7a78fcddba86ad49
data/CHANGELOG.md CHANGED
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [0.2.5] - 2025-09-28
11
+
12
+ ### Changed
13
+ - Align the install generator under `Verikloak::Bff::Generators` while retaining the `Verikloak::BFF::Generators` alias to avoid constant redefinition warnings during reloads.
14
+
15
+
16
+ ## [0.2.4] - 2025-09-27
17
+
18
+ ### Changed
19
+ - Simplify BFF install generator by inlining configuration lookups and removing unnecessary helper methods.
20
+ - Streamline generated initializer to use `Rails.configuration.middleware` and `Rails.logger` directly.
21
+ - Extract JWT decoding logic into shared `JwtUtils` module to eliminate duplication between `HeaderGuard` and `ConsistencyChecks`.
22
+ - Refactor `HeaderGuard#call` into clear pipeline stages with improved documentation.
23
+ - Enhance middleware stack detection to handle wrapped entries, string names, and complex objects.
24
+ - Remove duplicate proxy trust logic in `ProxyTrust` module by unifying `from_trusted_proxy?` and `trusted?` methods.
25
+
26
+ ### Fixed
27
+ - Resolve RuboCop style violations including useless constant scoping and identical conditional branches.
28
+
10
29
  ## [0.2.3] - 2025-09-23
11
30
 
12
31
  ### Changed
@@ -1,57 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails/generators/base'
3
+ require 'rails/generators'
4
4
 
5
5
  module Verikloak
6
- module BFF
7
- # Namespace for Rails generators related to Verikloak BFF
6
+ module Bff
7
+ # Rails generators supporting verikloak-bff integration.
8
8
  module Generators
9
- # Rails generator for installing Verikloak BFF middleware integration.
10
- #
11
- # This generator creates a Rails initializer that safely inserts the
12
- # Verikloak::BFF::HeaderGuard middleware into the Rails middleware stack.
13
- # It replaces automatic middleware insertion to avoid boot failures when
14
- # core Verikloak middleware is not yet configured.
15
- #
16
- # @example Basic usage
17
- # rails g verikloak:bff:install
18
- #
19
- # @example Custom initializer path
20
- # rails g verikloak:bff:install --initializer=config/initializers/custom_bff.rb
9
+ # Generator to install the Verikloak BFF initializer into a Rails app.
21
10
  #
22
11
  # @see Verikloak::BFF::Rails::Middleware
12
+ # @example Default usage
13
+ # rails g verikloak:bff:install
23
14
  class InstallGenerator < ::Rails::Generators::Base
24
15
  source_root File.expand_path('templates', __dir__)
16
+ desc 'Creates the Verikloak BFF initializer for Rails applications.'
25
17
 
26
- # Configuration option for specifying the initializer file path.
27
- #
28
18
  # @option options [String] :initializer ('config/initializers/verikloak_bff.rb')
29
- # The path where the initializer file will be created
19
+ # Path for the generated initializer file.
30
20
  class_option :initializer, type: :string,
31
21
  default: 'config/initializers/verikloak_bff.rb',
32
22
  desc: 'Path for the generated initializer'
33
23
 
34
- # Creates the Rails initializer file from template.
35
- #
36
- # Generates a Rails initializer that safely inserts the HeaderGuard
37
- # middleware into the middleware stack with proper error handling.
38
- # The initializer uses Verikloak::BFF::Rails::Middleware.insert_after_core
39
- # to ensure graceful handling when core middleware is missing.
24
+ # Copies the initializer template to the desired location.
40
25
  #
41
26
  # @return [void]
42
27
  def create_initializer
43
- template 'initializer.rb.tt', initializer_path
44
- end
45
-
46
- private
47
-
48
- # Returns the path where the initializer should be created.
49
- #
50
- # @return [String] The initializer file path from options
51
- def initializer_path
52
- options[:initializer]
28
+ template 'initializer.rb.erb', options.fetch(:initializer)
53
29
  end
54
30
  end
55
31
  end
56
32
  end
57
33
  end
34
+
35
+ # Maintain legacy constant path for consumers referencing Verikloak::BFF::Generators.
36
+ module Verikloak
37
+ # Legacy namespace alias for backward compatibility.
38
+ module BFF
39
+ Generators = Bff::Generators unless defined?(Generators)
40
+ end
41
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Configure verikloak-bff to insert its HeaderGuard middleware only after the
4
+ # Verikloak core middleware is present. This avoids boot errors when the core
5
+ # gem has not yet been installed.
6
+ Rails.application.config.after_initialize do
7
+ Verikloak::BFF::Rails::Middleware.insert_after_core(
8
+ Rails.application.config.middleware,
9
+ logger: Rails.logger
10
+ )
11
+ end
@@ -6,8 +6,8 @@
6
6
  # @see .enforce!
7
7
 
8
8
  require 'json'
9
- require 'jwt' # used only to parse segments safely without verify
10
9
  require 'verikloak/bff/constants'
10
+ require 'verikloak/bff/jwt_utils'
11
11
 
12
12
  module Verikloak
13
13
  module BFF
@@ -21,12 +21,7 @@ module Verikloak
21
21
  # @param token [String, nil]
22
22
  # @return [Hash] claims or empty hash on error
23
23
  def decode_claims(token)
24
- return {} unless token
25
- return {} if token.bytesize > Constants::MAX_TOKEN_BYTES
26
-
27
- JWT.decode(token, nil, false).first
28
- rescue StandardError
29
- {}
24
+ Verikloak::BFF::JwtUtils.decode_claims(token)
30
25
  end
31
26
 
32
27
  # mapping: { email: :email, user: :sub, groups: :realm_roles }
@@ -13,7 +13,6 @@
13
13
  require 'rack'
14
14
  require 'rack/utils'
15
15
  require 'json'
16
- require 'jwt'
17
16
  require 'digest'
18
17
  require 'verikloak/header_sources'
19
18
  require 'verikloak/bff/configuration'
@@ -22,6 +21,7 @@ require 'verikloak/bff/proxy_trust'
22
21
  require 'verikloak/bff/forwarded_token'
23
22
  require 'verikloak/bff/consistency_checks'
24
23
  require 'verikloak/bff/constants'
24
+ require 'verikloak/bff/jwt_utils'
25
25
 
26
26
  module Verikloak
27
27
  module BFF
@@ -58,11 +58,7 @@ module Verikloak
58
58
  # @param token [String, nil]
59
59
  # @return [Array<Hash>] payload and header hashes
60
60
  def decode_unverified(token)
61
- return [{}, {}] if token.nil? || token.bytesize > Constants::MAX_TOKEN_BYTES
62
-
63
- JWT.decode(token, nil, false)
64
- rescue StandardError
65
- [{}, {}]
61
+ Verikloak::BFF::JwtUtils.decode_unverified(token)
66
62
  end
67
63
 
68
64
  # Remove unsafe characters from a structured logging payload.
@@ -104,6 +100,8 @@ module Verikloak
104
100
 
105
101
  # Rack middleware that enforces BFF boundary and header/claims consistency.
106
102
  class HeaderGuard
103
+ RequestTokens = Struct.new(:auth, :forwarded, :chosen)
104
+
107
105
  # Accept both Rack 2 and Rack 3 builder call styles:
108
106
  # - new(app, key: val)
109
107
  # - new(app, { key: val })
@@ -125,22 +123,29 @@ module Verikloak
125
123
  raise ArgumentError, 'trusted_proxies must be configured'
126
124
  end
127
125
 
128
- # Process a Rack request.
126
+ # Process a Rack request through the BFF header guard pipeline.
127
+ #
128
+ # Pipeline stages:
129
+ # 1. Proxy trust validation
130
+ # 2. Token extraction and state building
131
+ # 3. Policy enforcement (forwarded token requirements, consistency checks)
132
+ # 4. Request finalization (Authorization header normalization)
129
133
  #
130
134
  # @param env [Hash]
131
135
  # @return [Array(Integer, Hash, Array<#to_s>)] Rack response triple
132
136
  def call(env)
137
+ # Stage 1: Validate request comes from trusted proxy
133
138
  ensure_trusted_proxy!(env)
134
- auth_token, fwd_token = ForwardedToken.extract(env, @config.forwarded_header_name)
135
- ensure_forwarded_if_required!(fwd_token)
136
- chosen = choose_token(auth_token, fwd_token)
137
- chosen = seed_authorization_if_needed(env, chosen)
138
139
 
139
- enforce_header_consistency!(env, auth_token, fwd_token)
140
- enforce_claims_consistency!(env, chosen)
141
- ForwardedToken.strip_suspicious!(env, @config.auth_request_headers) if @config.strip_suspicious_headers
142
- normalize_authorization!(env, chosen, auth_token, fwd_token)
143
- expose_env_hints(env, chosen)
140
+ # Stage 2: Extract and validate tokens, build request state
141
+ tokens = build_token_state(env)
142
+
143
+ # Stage 3: Enforce configured policies (forwarded requirements, consistency)
144
+ enforce_token_policies!(env, tokens)
145
+
146
+ # Stage 4: Finalize request with normalized Authorization header
147
+ finalize_request!(env, tokens)
148
+
144
149
  @app.call(env)
145
150
  rescue Verikloak::BFF::Error => e
146
151
  respond_with_error(env, e)
@@ -148,6 +153,41 @@ module Verikloak
148
153
 
149
154
  private
150
155
 
156
+ # Build token state by extracting, validating, and selecting the active token.
157
+ #
158
+ # @param env [Hash]
159
+ # @return [RequestTokens]
160
+ def build_token_state(env)
161
+ auth_token, fwd_token = ForwardedToken.extract(env, @config.forwarded_header_name)
162
+ ensure_forwarded_if_required!(fwd_token)
163
+
164
+ chosen = choose_token(auth_token, fwd_token)
165
+ chosen = seed_authorization_if_needed(env, chosen)
166
+
167
+ RequestTokens.new(auth_token, fwd_token, chosen)
168
+ end
169
+
170
+ # Apply header and claim consistency policies for the current request.
171
+ #
172
+ # @param env [Hash]
173
+ # @param tokens [RequestTokens]
174
+ # @return [void]
175
+ def enforce_token_policies!(env, tokens)
176
+ enforce_header_consistency!(env, tokens.auth, tokens.forwarded)
177
+ enforce_claims_consistency!(env, tokens.chosen)
178
+ end
179
+
180
+ # Mutate the Rack env with normalized headers and logging hints.
181
+ #
182
+ # @param env [Hash]
183
+ # @param tokens [RequestTokens]
184
+ # @return [void]
185
+ def finalize_request!(env, tokens)
186
+ ForwardedToken.strip_suspicious!(env, @config.auth_request_headers) if @config.strip_suspicious_headers
187
+ normalize_authorization!(env, tokens.chosen, tokens.auth, tokens.forwarded)
188
+ expose_env_hints(env, tokens.chosen)
189
+ end
190
+
151
191
  # Apply per-instance configuration overrides.
152
192
  #
153
193
  # @param opts [Hash]
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'jwt'
4
+ require 'verikloak/bff/constants'
5
+
6
+ module Verikloak
7
+ module BFF
8
+ # Lightweight helpers around JWT decoding without verification.
9
+ module JwtUtils
10
+ module_function
11
+
12
+ # Decode JWT header and payload without verification, guarding against oversized input.
13
+ #
14
+ # @param token [String, nil]
15
+ # @return [Array<Hash>] [payload, header]
16
+ def decode_unverified(token)
17
+ return [{}, {}] if token.nil? || token.bytesize > Constants::MAX_TOKEN_BYTES
18
+
19
+ JWT.decode(token, nil, false)
20
+ rescue StandardError
21
+ [{}, {}]
22
+ end
23
+
24
+ # Return the decoded JWT payload without verification.
25
+ #
26
+ # @param token [String, nil]
27
+ # @return [Hash]
28
+ def decode_claims(token)
29
+ decode_unverified(token).first
30
+ end
31
+ end
32
+ end
33
+ end
@@ -23,17 +23,8 @@ module Verikloak
23
23
  # @example CIDR + Regex allowlist
24
24
  # ProxyTrust.trusted?(env, ["10.0.0.0/8", /^192\.168\./], :rightmost)
25
25
  def trusted?(env, trusted, strategy = :rightmost)
26
- return false if trusted.nil? || trusted.empty?
27
-
28
- # Rails-aligned: prefer REMOTE_ADDR; fallback to nearest XFF entry
29
- remote = (env['REMOTE_ADDR'] || '').to_s.strip
30
- remote = extract_peer_ip(env, strategy) if remote.empty?
31
- return false unless remote
32
-
33
- remote_ip = ip_or_nil(remote)
34
- trusted.any? { |rule| rule_trusts?(rule, remote, remote_ip, env) }
35
- rescue StandardError
36
- false
26
+ remote = resolve_peer(env, :remote_then_xff, strategy)
27
+ trusted_remote?(remote, trusted, env)
37
28
  end
38
29
 
39
30
  # Select the peer IP from X-Forwarded-For according to strategy or fall back to REMOTE_ADDR.
@@ -59,15 +50,7 @@ module Verikloak
59
50
  # @param strategy [Symbol] :rightmost or :leftmost
60
51
  # @return [String, nil]
61
52
  def selected_peer(env, preference, strategy)
62
- case preference.to_s.to_sym
63
- when :remote_then_xff
64
- ip = (env['REMOTE_ADDR'] || '').to_s.strip
65
- return ip unless ip.nil? || ip.empty?
66
-
67
- extract_peer_ip(env, :rightmost) # nearest by default
68
- else
69
- extract_peer_ip(env, strategy)
70
- end
53
+ resolve_peer(env, preference, strategy)
71
54
  end
72
55
 
73
56
  # Parse string to IPAddr or nil on failure.
@@ -112,16 +95,37 @@ module Verikloak
112
95
  # @param trusted [Array<String, Regexp, Proc>, nil]
113
96
  # @return [Boolean]
114
97
  def self.from_trusted_proxy?(env, trusted)
115
- return false if trusted.nil? || trusted.empty?
98
+ trusted?(env, trusted, :rightmost)
99
+ end
116
100
 
117
- ip = (env['REMOTE_ADDR'] || '').to_s.strip
118
- ip = env['HTTP_X_FORWARDED_FOR'].to_s.split(',').last.to_s.strip if ip.empty? && env['HTTP_X_FORWARDED_FOR']
119
- return false if ip.empty?
101
+ # Resolve the peer value based on preference and strategy.
102
+ #
103
+ # @param env [Hash]
104
+ # @param preference [Symbol]
105
+ # @param strategy [Symbol]
106
+ # @return [String, nil]
107
+ def resolve_peer(env, preference, strategy)
108
+ case preference.to_s.to_sym
109
+ when :remote_then_xff
110
+ remote = (env['REMOTE_ADDR'] || '').to_s.strip
111
+ return remote unless remote.empty?
112
+ # Fall back to X-Forwarded-For when REMOTE_ADDR is empty
113
+ end
114
+ extract_peer_ip(env, strategy)
115
+ end
120
116
 
121
- remote_ip = ip_or_nil(ip)
122
- return false unless remote_ip
117
+ # Determine whether a remote peer appears in the trusted list.
118
+ #
119
+ # @param remote [String, nil]
120
+ # @param trusted [Array<String, Regexp, Proc>, nil]
121
+ # @param env [Hash]
122
+ # @return [Boolean]
123
+ def trusted_remote?(remote, trusted, env)
124
+ return false if trusted.nil? || trusted.empty?
125
+ return false unless remote
123
126
 
124
- trusted.any? { |rule| rule_trusts?(rule, ip, remote_ip, env) }
127
+ remote_ip = ip_or_nil(remote)
128
+ trusted.any? { |rule| rule_trusts?(rule, remote, remote_ip, env) }
125
129
  rescue StandardError
126
130
  false
127
131
  end
@@ -4,14 +4,20 @@ module Verikloak
4
4
  module BFF
5
5
  # Rails-specific functionality for Verikloak BFF
6
6
  module Rails
7
- # Middleware management utilities for Rails applications
7
+ # Middleware management utilities for Rails applications.
8
8
  #
9
- # This module provides functionality to insert Verikloak BFF middleware
10
- # into Rails middleware stack, with proper error handling for cases where
11
- # the core Verikloak middleware is not present.
9
+ # This module focuses on inserting the HeaderGuard middleware right after
10
+ # the core Verikloak middleware while gracefully handling stacks that do
11
+ # not contain the core component.
12
12
  module Middleware
13
13
  module_function
14
14
 
15
+ CORE_NAME = 'Verikloak::Middleware'
16
+ HEADER_GUARD_NAME = 'Verikloak::BFF::HeaderGuard'
17
+ SKIP_MESSAGE = <<~MSG.chomp.freeze
18
+ [verikloak-bff] Skipping Verikloak::BFF::HeaderGuard insertion because Verikloak::Middleware is not present. Configure verikloak-rails discovery settings and restart once core verification is enabled.
19
+ MSG
20
+
15
21
  # Inserts Verikloak::BFF::HeaderGuard middleware after Verikloak::Middleware
16
22
  #
17
23
  # Attempts to insert the HeaderGuard middleware into the Rails middleware stack
@@ -31,12 +37,15 @@ module Verikloak
31
37
  def insert_after_core(stack, logger: nil)
32
38
  return false unless auto_insert_enabled?
33
39
 
34
- unless core_present?(stack)
40
+ core = core_middleware
41
+ header_guard = header_guard_middleware
42
+
43
+ unless stack && core && header_guard && core_present?(stack, core)
35
44
  log_skip(logger)
36
45
  return false
37
46
  end
38
47
 
39
- stack.insert_after(::Verikloak::Middleware, ::Verikloak::BFF::HeaderGuard)
48
+ stack.insert_after(core, header_guard)
40
49
  true
41
50
  rescue RuntimeError => e
42
51
  raise unless missing_core?(e)
@@ -54,11 +63,9 @@ module Verikloak
54
63
  #
55
64
  # @return [Boolean]
56
65
  def auto_insert_enabled?
57
- return true unless defined?(::Verikloak)
58
- return true unless ::Verikloak.respond_to?(:config)
59
-
60
- config = ::Verikloak.config
66
+ config = core_config
61
67
  return true unless config
68
+
62
69
  return config.auto_insert_bff_header_guard if config.respond_to?(:auto_insert_bff_header_guard)
63
70
 
64
71
  true
@@ -66,56 +73,60 @@ module Verikloak
66
73
  true
67
74
  end
68
75
 
76
+ # Returns the Verikloak configuration object when available.
77
+ #
78
+ # @return [Object, nil]
79
+ def core_config
80
+ return nil unless defined?(::Verikloak)
81
+ return nil unless ::Verikloak.respond_to?(:config)
82
+
83
+ ::Verikloak.config
84
+ rescue StandardError
85
+ nil
86
+ end
87
+
69
88
  # Detect whether the Verikloak core middleware is already present in the stack.
70
89
  #
71
90
  # @param stack [#include?, #each, nil]
72
91
  # @return [Boolean]
73
- def core_present?(stack)
92
+ def core_present?(stack, core = core_middleware)
74
93
  return false unless stack
75
94
 
76
- if stack.respond_to?(:include?)
77
- begin
78
- return true if stack.include?(::Verikloak::Middleware)
79
- rescue StandardError
80
- # Fall back to manual enumeration when include? is unsupported for this stack
81
- end
95
+ begin
96
+ return true if core && stack.respond_to?(:include?) && stack.include?(core)
97
+ rescue StandardError
98
+ # Fall back to manual enumeration when include? is unsupported for this stack.
82
99
  end
83
100
 
84
101
  return false unless stack.respond_to?(:each)
85
102
 
86
- stack.each do |middleware|
87
- return true if middleware_matches_core?(middleware)
103
+ stack.each do |entry|
104
+ candidate = unwrap_middleware(entry)
105
+ return true if core && candidate == core
106
+ return true if middleware_name(candidate) == CORE_NAME
88
107
  end
89
108
 
90
109
  false
91
110
  end
92
111
 
93
- # Check whether a middleware entry represents the Verikloak core middleware.
112
+ # Normalize raw stack entries to a comparable object.
94
113
  #
95
- # @param middleware [Object]
96
- # @return [Boolean]
97
- def middleware_matches_core?(middleware)
98
- candidate = middleware.is_a?(Array) ? middleware.first : middleware
99
-
100
- klass = extract_middleware_class(candidate)
101
-
102
- klass == ::Verikloak::Middleware ||
103
- (klass.is_a?(String) && klass == 'Verikloak::Middleware') ||
104
- (klass.respond_to?(:name) && klass.name == 'Verikloak::Middleware')
114
+ # @param entry [Object]
115
+ # @return [Object]
116
+ def unwrap_middleware(entry)
117
+ entry = entry.first if entry.is_a?(Array)
118
+ entry.respond_to?(:klass) ? entry.klass : entry
105
119
  end
106
120
 
107
- # Extracts the class or class-like identifier from a middleware candidate.
108
- #
109
- # @param candidate [Object]
110
- # @return [Class, String, Object]
111
- def extract_middleware_class(candidate)
112
- if candidate.respond_to?(:klass)
113
- candidate.klass
114
- elsif candidate.respond_to?(:name)
115
- candidate.name
116
- else
117
- candidate
118
- end
121
+ # Resolve a human-readable middleware name if possible.
122
+ #
123
+ # @param entry [Object]
124
+ # @return [String, nil]
125
+ def middleware_name(entry)
126
+ return entry if entry.is_a?(String)
127
+ return entry.to_s if entry.is_a?(Symbol)
128
+
129
+ entry.respond_to?(:name) ? entry.name : nil
119
130
  end
120
131
 
121
132
  # Checks if the error indicates missing core Verikloak middleware
@@ -134,7 +145,7 @@ module Verikloak
134
145
  # end
135
146
  def missing_core?(error)
136
147
  error.message.include?('No such middleware') &&
137
- error.message.include?('Verikloak::Middleware')
148
+ error.message.include?(CORE_NAME)
138
149
  end
139
150
 
140
151
  # Logs a warning message about skipping middleware insertion
@@ -151,11 +162,31 @@ module Verikloak
151
162
  # @example Logging without logger (uses warn)
152
163
  # log_skip(nil)
153
164
  def log_skip(logger)
154
- message = <<~MSG.chomp
155
- [verikloak-bff] Skipping Verikloak::BFF::HeaderGuard insertion because Verikloak::Middleware is not present. Configure verikloak-rails discovery settings and restart once core verification is enabled.
156
- MSG
165
+ logger ? logger.warn(SKIP_MESSAGE) : warn(SKIP_MESSAGE)
166
+ end
157
167
 
158
- logger ? logger.warn(message) : warn(message)
168
+ # Safely resolves the core middleware constant when available.
169
+ #
170
+ # @return [Class, nil]
171
+ def core_middleware
172
+ safe_const_get(CORE_NAME)
173
+ end
174
+
175
+ # Safely resolves the HeaderGuard middleware constant when available.
176
+ #
177
+ # @return [Class, nil]
178
+ def header_guard_middleware
179
+ safe_const_get(HEADER_GUARD_NAME)
180
+ end
181
+
182
+ # Attempts to constantize the provided class name, returning nil when undefined.
183
+ #
184
+ # @param name [String]
185
+ # @return [Module, Class, nil]
186
+ def safe_const_get(name)
187
+ Object.const_get(name)
188
+ rescue NameError
189
+ nil
159
190
  end
160
191
  end
161
192
  end
@@ -5,6 +5,6 @@
5
5
  # @return [String]
6
6
  module Verikloak
7
7
  module BFF
8
- VERSION = '0.2.3'
8
+ VERSION = '0.2.5'
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: verikloak-bff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - taiyaky
@@ -79,6 +79,7 @@ files:
79
79
  - LICENSE
80
80
  - README.md
81
81
  - lib/generators/verikloak/bff/install/install_generator.rb
82
+ - lib/generators/verikloak/bff/install/templates/initializer.rb.erb
82
83
  - lib/verikloak-bff.rb
83
84
  - lib/verikloak/bff.rb
84
85
  - lib/verikloak/bff/configuration.rb
@@ -87,6 +88,7 @@ files:
87
88
  - lib/verikloak/bff/errors.rb
88
89
  - lib/verikloak/bff/forwarded_token.rb
89
90
  - lib/verikloak/bff/header_guard.rb
91
+ - lib/verikloak/bff/jwt_utils.rb
90
92
  - lib/verikloak/bff/proxy_trust.rb
91
93
  - lib/verikloak/bff/rails.rb
92
94
  - lib/verikloak/bff/railtie.rb
@@ -99,7 +101,7 @@ metadata:
99
101
  source_code_uri: https://github.com/taiyaky/verikloak-bff
100
102
  changelog_uri: https://github.com/taiyaky/verikloak-bff/blob/main/CHANGELOG.md
101
103
  bug_tracker_uri: https://github.com/taiyaky/verikloak-bff/issues
102
- documentation_uri: https://rubydoc.info/gems/verikloak-bff/0.2.3
104
+ documentation_uri: https://rubydoc.info/gems/verikloak-bff/0.2.5
103
105
  rubygems_mfa_required: 'true'
104
106
  rdoc_options: []
105
107
  require_paths: