Module: Insika::Server::TenantAuth
- Defined in:
- lib/insika/server/tenant_auth.rb
Overview
Edge resolution for WS1 (multi-tenant): Authorization: Bearer <token> ->
a principal { role:, tenant_id: }, resolved BEFORE the routes. Two modes,
one gate:
single_tenant (default) — no token store: the classic single operator
credential (config[:gateway_token]) is the only thing that resolves.
multi_tenant — tokens live in the TokenStore (per-tenant + operator).
A configured gateway_token STILL resolves as operator (an existing
deployment switching modes keeps its credential — additive, never
a second-class path).
Fail-closed BY CONSTRUCTION: no store and no configured token -> :disabled (503, never open). A revoked or unknown token -> :unauthorized. Pure module, testable without a Rack env.
Class Method Summary collapse
-
.check(gateway_token, token_store, header) ⇒ Object
gateway_token: config | nil.
Class Method Details
.check(gateway_token, token_store, header) ⇒ Object
gateway_token: config | nil. token_store: TokenStore | nil. header: raw Authorization value. -> :disabled | :unauthorized | { role: "operator"|"tenant", tenant_id: }
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 57 58 |
# File 'lib/insika/server/tenant_auth.rb', line 28 def check(gateway_token, token_store, header) # Fail-closed FIRST (the construction rule): with no store AND no # configured token the gateway is DISABLED (503) however the request # looks — never "401: who are you facing a door that does not exist". # A token_store present means the gateway IS configured (multi_tenant), # with or without the legacy gateway token. return :disabled if token_store.nil? && (gateway_token.nil? || gateway_token.empty?) provided = header.to_s[/\ABearer (.+)\z/, 1] return :unauthorized if provided.nil? if token_store record = token_store.resolve(provided) unless record # store miss -> the legacy gateway token still resolves as operator # (an existing deployment switching modes keeps its credential). return :unauthorized if gateway_token.nil? || gateway_token.empty? return :unauthorized unless Rack::Utils.secure_compare(gateway_token, provided) return { role: "operator", tenant_id: nil } end return { role: record.role.to_s, tenant_id: record.tenant_id } end # classic mode (no store): the gateway token is the only credential. # Constant-time comparison: the operator token doesn't leak via timing. return :unauthorized unless Rack::Utils.secure_compare(gateway_token, provided) { role: "operator", tenant_id: nil } end |