Module: Verikloak::BFF::Rails::Middleware

Defined in:
lib/verikloak/bff/rails.rb

Overview

Middleware management utilities for Rails applications.

This module focuses on inserting the HeaderGuard middleware right before the core Verikloak middleware (so tokens are normalized before core verification) while gracefully handling stacks that do not contain the core component.

NOTE: When verikloak-rails is installed, middleware insertion happens automatically via its railtie — these helpers are only needed for manual (non verikloak-rails) setups.

Constant Summary collapse

CORE_NAME =
'Verikloak::Middleware'
HEADER_GUARD_NAME =
'Verikloak::BFF::HeaderGuard'
SKIP_MESSAGE =
<<~MSG.chomp.freeze
  [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.
MSG
DEPRECATION_MESSAGE =
<<~MSG.chomp.freeze
  [verikloak-bff] Verikloak::BFF::Rails::Middleware.insert_after_core is deprecated and will be removed in a future release. Use insert_before_core instead — HeaderGuard must run before Verikloak::Middleware so that tokens are normalized prior to verification. insert_after_core now delegates to insert_before_core.
MSG

Class Method Summary collapse

Class Method Details

.core_middlewareClass?

Safely resolves the core middleware constant when available.

Returns:

  • (Class, nil)


149
150
151
# File 'lib/verikloak/bff/rails.rb', line 149

def core_middleware
  safe_const_get(CORE_NAME)
end

.core_present?(stack, core = core_middleware) ⇒ Boolean

Detect whether the Verikloak core middleware is already present in the stack.

Parameters:

  • stack (#include?, #each, nil)

Returns:

  • (Boolean)


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/verikloak/bff/rails.rb', line 83

def core_present?(stack, core = core_middleware)
  return false unless stack

  begin
    return true if core && stack.respond_to?(:include?) && stack.include?(core)
  rescue StandardError
    # Fall back to manual enumeration when include? is unsupported for this stack.
  end

  return false unless stack.respond_to?(:each)

  stack.each do |entry|
    candidate = unwrap_middleware(entry)
    return true if core && candidate == core
    return true if middleware_name(candidate) == CORE_NAME
  end

  false
end

.header_guard_middlewareClass?

Safely resolves the HeaderGuard middleware constant when available.

Returns:

  • (Class, nil)


156
157
158
# File 'lib/verikloak/bff/rails.rb', line 156

def header_guard_middleware
  safe_const_get(HEADER_GUARD_NAME)
end

.insert_after_core(stack, logger: nil) ⇒ Boolean

Deprecated.

Use insert_before_core instead. The previous behavior (inserting HeaderGuard after the core middleware) contradicted the documented stack order and let core verification see un-normalized tokens. This method now delegates to insert_before_core and emits a deprecation warning.

Returns true if insertion succeeded, false if skipped.

Parameters:

  • stack (ActionDispatch::MiddlewareStack)

    Rails middleware stack

  • logger (Logger, nil) (defaults to: nil)

    Optional logger for warning messages

Returns:

  • (Boolean)

    true if insertion succeeded, false if skipped



74
75
76
77
# File 'lib/verikloak/bff/rails.rb', line 74

def insert_after_core(stack, logger: nil)
  logger ? logger.warn(DEPRECATION_MESSAGE) : warn(DEPRECATION_MESSAGE)
  insert_before_core(stack, logger: logger)
end

.insert_before_core(stack, logger: nil) ⇒ Boolean

Inserts Verikloak::BFF::HeaderGuard middleware before Verikloak::Middleware

Attempts to insert the HeaderGuard middleware into the Rails middleware stack before the core Verikloak::Middleware, matching the documented stack order:

[Verikloak::BFF::HeaderGuard] → [Verikloak::Middleware] → [Your App]

If the core middleware is not present, logs a warning and gracefully skips the insertion.

Examples:

Inserting middleware in Rails configuration

Verikloak::BFF::Rails::Middleware.insert_before_core(
  Rails.application.config.middleware,
  logger: Rails.logger
)

Parameters:

  • stack (ActionDispatch::MiddlewareStack)

    Rails middleware stack

  • logger (Logger, nil) (defaults to: nil)

    Optional logger for warning messages

Returns:

  • (Boolean)

    true if insertion succeeded, false if skipped due to missing core

Raises:

  • (RuntimeError)

    Re-raises non-middleware-related runtime errors



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/verikloak/bff/rails.rb', line 47

def insert_before_core(stack, logger: nil)
  core = core_middleware
  header_guard = header_guard_middleware

  unless stack && core && header_guard && core_present?(stack, core)
    log_skip(logger)
    return false
  end

  stack.insert_before(core, header_guard)
  true
rescue RuntimeError => e
  raise unless missing_core?(e)

  log_skip(logger)
  false
end

.log_skip(logger) ⇒ Object

Logs a warning message about skipping middleware insertion

Outputs a descriptive warning message explaining why the HeaderGuard middleware insertion was skipped and provides guidance for resolution. Uses the provided logger if available, otherwise falls back to warn().

Parameters:

  • logger (Logger, nil)

    Optional logger instance for structured logging



142
143
144
# File 'lib/verikloak/bff/rails.rb', line 142

def log_skip(logger)
  logger ? logger.warn(SKIP_MESSAGE) : warn(SKIP_MESSAGE)
end

.middleware_name(entry) ⇒ String?

Resolve a human-readable middleware name if possible.

Parameters:

  • entry (Object)

Returns:

  • (String, nil)


116
117
118
119
120
121
# File 'lib/verikloak/bff/rails.rb', line 116

def middleware_name(entry)
  return entry if entry.is_a?(String)
  return entry.to_s if entry.is_a?(Symbol)

  entry.respond_to?(:name) ? entry.name : nil
end

.missing_core?(error) ⇒ Boolean

Checks if the error indicates missing core Verikloak middleware

Examines a RuntimeError to determine if it was caused by attempting to insert middleware relative to a non-existent Verikloak::Middleware.

Parameters:

  • error (RuntimeError)

    The error to examine

Returns:

  • (Boolean)

    true if error indicates missing Verikloak::Middleware



130
131
132
133
# File 'lib/verikloak/bff/rails.rb', line 130

def missing_core?(error)
  error.message.include?('No such middleware') &&
    error.message.include?(CORE_NAME)
end

.safe_const_get(name) ⇒ Module, ...

Attempts to constantize the provided class name, returning nil when undefined.

Parameters:

  • name (String)

Returns:

  • (Module, Class, nil)


164
165
166
167
168
# File 'lib/verikloak/bff/rails.rb', line 164

def safe_const_get(name)
  Object.const_get(name)
rescue NameError
  nil
end

.unwrap_middleware(entry) ⇒ Object

Normalize raw stack entries to a comparable object.

Parameters:

  • entry (Object)

Returns:

  • (Object)


107
108
109
110
# File 'lib/verikloak/bff/rails.rb', line 107

def unwrap_middleware(entry)
  entry = entry.first if entry.is_a?(Array)
  entry.respond_to?(:klass) ? entry.klass : entry
end