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 +4 -4
- data/CHANGELOG.md +19 -0
- data/lib/generators/verikloak/bff/install/install_generator.rb +18 -34
- data/lib/generators/verikloak/bff/install/templates/initializer.rb.erb +11 -0
- data/lib/verikloak/bff/consistency_checks.rb +2 -7
- data/lib/verikloak/bff/header_guard.rb +56 -16
- data/lib/verikloak/bff/jwt_utils.rb +33 -0
- data/lib/verikloak/bff/proxy_trust.rb +31 -27
- data/lib/verikloak/bff/rails.rb +78 -47
- data/lib/verikloak/bff/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b024a1e87d9a4cd895b0e052ba276cbf418b50d4f51b3f642d3916e7b713253e
|
|
4
|
+
data.tar.gz: 82bab8741e03c8b1f57bea89856b8811440c34778470c18a82c87c279a36c4a4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
3
|
+
require 'rails/generators'
|
|
4
4
|
|
|
5
5
|
module Verikloak
|
|
6
|
-
module
|
|
7
|
-
#
|
|
6
|
+
module Bff
|
|
7
|
+
# Rails generators supporting verikloak-bff integration.
|
|
8
8
|
module Generators
|
|
9
|
-
#
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
98
|
+
trusted?(env, trusted, :rightmost)
|
|
99
|
+
end
|
|
116
100
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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
|
data/lib/verikloak/bff/rails.rb
CHANGED
|
@@ -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
|
|
10
|
-
#
|
|
11
|
-
# the core
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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 |
|
|
87
|
-
|
|
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
|
-
#
|
|
112
|
+
# Normalize raw stack entries to a comparable object.
|
|
94
113
|
#
|
|
95
|
-
# @param
|
|
96
|
-
# @return [
|
|
97
|
-
def
|
|
98
|
-
|
|
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
|
-
#
|
|
108
|
-
#
|
|
109
|
-
# @param
|
|
110
|
-
# @return [
|
|
111
|
-
def
|
|
112
|
-
if
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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?(
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
MSG
|
|
165
|
+
logger ? logger.warn(SKIP_MESSAGE) : warn(SKIP_MESSAGE)
|
|
166
|
+
end
|
|
157
167
|
|
|
158
|
-
|
|
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
|
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.
|
|
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.
|
|
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:
|