Class: Legion::Identity::Middleware
- Inherits:
-
Object
- Object
- Legion::Identity::Middleware
- Defined in:
- lib/legion/identity/middleware.rb
Constant Summary collapse
- SKIP_PATHS =
%w[/api/health /api/ready /api/openapi.json /metrics].freeze
- LOOPBACK_BINDS =
%w[127.0.0.1 ::1 localhost].freeze
Class Method Summary collapse
-
.require_auth?(bind:, mode:) ⇒ Boolean
Returns whether the API should require authentication.
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, require_auth: false) ⇒ Middleware
constructor
A new instance of Middleware.
Constructor Details
#initialize(app, require_auth: false) ⇒ Middleware
Returns a new instance of Middleware.
9 10 11 12 |
# File 'lib/legion/identity/middleware.rb', line 9 def initialize(app, require_auth: false) @app = app @require_auth = require_auth end |
Class Method Details
.require_auth?(bind:, mode:) ⇒ Boolean
Returns whether the API should require authentication. Skips auth for lite mode and loopback binds (local dev / CI).
60 61 62 63 64 65 |
# File 'lib/legion/identity/middleware.rb', line 60 def self.require_auth?(bind:, mode:) return false if mode == :lite return false if LOOPBACK_BINDS.include?(bind) true end |
Instance Method Details
#call(env) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/legion/identity/middleware.rb', line 14 def call(env) return @app.call(env) if skip_path?(env['PATH_INFO']) # Bridge from existing auth middleware auth_claims = env['legion.auth'] auth_method = env['legion.auth_method'] request = if auth_claims build_request(auth_claims, auth_method) elsif @require_auth # Auth middleware already handled 401 for protected paths; # this is a safety net for any path that slipped through. nil else # No auth required (loopback bind, lite mode, etc.). # Set a system-level principal so audit trails always have an identity. system_principal end env['legion.principal'] = request # Bridge to RBAC principal if legion-rbac is loaded. # This is a data bridge — set regardless of enforce/audit mode so # the RBAC middleware always has a typed principal to evaluate. # Guard: require Legion::Rbac.enabled? to confirm the real gem is loaded # (not a minimal test stub), and rescue construction errors defensively. if request && defined?(Legion::Rbac::Principal) && defined?(Legion::Rbac) && Legion::Rbac.respond_to?(:enabled?) && Legion::Rbac.enabled? begin env['legion.rbac_principal'] = Legion::Rbac::Principal.new( id: request.principal_id, type: request.kind == :service ? :worker : request.kind, roles: request.roles, team: request.&.dig(:team) ) rescue StandardError # Best-effort bridge: leave legion.rbac_principal unset on construction errors. end end @app.call(env) end |