Documentation
¶
Overview ¶
Package iammiddleware is the gateway-trust shim for legacy call sites. It used to do JWKS fetch + JWT validation in-binary (293 LOC). That trust boundary is now hanzoai/gateway: gateway validates the JWT, populates X-Org-Id / X-User-Id / X-User-Email, and only gateway-routed traffic reaches commerced.
This file preserves the public API the rest of commerce depends on (Init, InitKV, Client, IAMTokenRequired, IsIAMAuthenticated, GetIAMClaims, GetIAMTier) so the 13 call sites compile, but every function reads identity from the gateway-supplied headers via pkg/auth.
Deletion target: once all call sites migrate to pkg/auth + pkg/org, this file can be removed wholesale.
Index ¶
Constants ¶
const HeaderRoles = "X-Roles"
HeaderRoles is the canonical comma-joined role-name header set by the gateway from the JWT roles claim. Empty value -> no roles.
const HeaderTest = "X-Hanzo-Test"
HeaderTest is the gateway-propagated test-mode signal. When the gateway forwards "true" (only for test orgs), the request runs in TEST mode: org.Live=false, charges hit sandbox processors, ledger rows are flagged Test. Absent/any-other value ⇒ live. Mirrors the X-Hanzo-Test semantics in middleware/accesstoken.go. The gateway is the trust boundary; commerced trusts the bit it forwards.
const HeaderUserIsAdmin = "X-User-IsAdmin"
HeaderUserIsAdmin is the gateway-minted "true"/"" ORG-level admin flag (set for an org owner). Only "true" (case-insensitive) is treated as admin; any other value (including absent) fails closed to false. It is org-scoped only — NEVER gate cross-org/superadmin actions on it; use GlobalAdmin().
const HeaderUserIsGlobalAdmin = "X-User-IsGlobalAdmin"
HeaderUserIsGlobalAdmin is the gateway-minted "true"/"" PLATFORM superadmin flag, minted only for a real global admin (owner==AdminOrg or the explicit isGlobalAdmin claim). Fails closed to false when absent.
const HeaderUserPermissions = "X-User-Permissions"
HeaderUserPermissions is the canonical gateway-minted permission header. It carries the bit.Field value as a base-10 int64 string (e.g. "3" for Live|Test). The gateway MUST set it from the validated JWT roles/claims; commerced reads it as-is. Missing or malformed values fail closed (zero permissions). Documented in HEADERS.md.
Variables ¶
This section is empty.
Functions ¶
func Client ¶ added in v1.39.1
Client returns the initialized IAM client, or nil if IAM is disabled or Init() has not been called. Consumers outside the middleware chain (e.g. SPA handlers with their own auth gate) use this to validate bearer tokens against the same JWKS the /v1 middleware uses. Fail-closed: a nil return means "treat every request as unauthenticated".
Returns the client built by Init from the IAM config, or nil when IAM is disabled / misconfigured (fail-closed at the call site). This is the non-gateway entry point hook: commerce-api.hanzo.ai is exposed directly (not behind hanzoai/gateway), so its edge surfaces verify the JWT here.
func GetIAMClaims ¶
GetIAMClaims returns a non-nil *auth.IAMClaims populated from the gateway-minted identity headers. The gateway validated the JWT and stamped X-Org-Id, X-User-Id, X-User-Email, X-User-IsAdmin, X-Roles (see hanzoai/gateway/auth_middleware.go). commerced trusts those bits and reflects them into a claims struct so call sites can read IsAdmin / Owner / Subject / Roles uniformly.
Fail-closed contract: missing headers map to zero-valued fields. In particular, missing X-User-IsAdmin yields IsAdmin=false (not "unknown"). Call sites MUST NOT nil-guard the return — it is always non-nil.
The legacy in-test path stores a *auth.IAMClaims under the "iam_claims" gin key; that wins when present so tests can inject arbitrary claim shapes without going through HTTP.
func GetIAMTier ¶ added in v1.36.4
GetIAMTier returns "" — tier is no longer derived in-binary. The gateway can attach an X-Tier header in a future iteration if needed.
func IAMTokenRequired ¶
func IAMTokenRequired() gin.HandlerFunc
IAMTokenRequired returns a Gin middleware that:
- Reads the gateway-supplied X-Org-Id / X-User-Id / X-User-Email headers (already JWT-validated upstream).
- Resolves the Organization via pkg/org.Resolve (KV-cached).
- Sets the legacy gin context keys downstream handlers expect: iam_authenticated, iam_org, iam_user_id, iam_email, organization, active-organization, permissions.
Missing headers: falls through (handler chain may use a legacy org-token instead). The gateway is the trust boundary; commerced is only reachable via the gateway in production, where COMMERCED_REQUIRE_IDENTITY rejects header-less requests at the edge of the binary.
func Init ¶
Init builds the IAM client used by the directly-exposed commerce-api edge — the surfaces that face a raw user Bearer JWT instead of gateway-minted headers: EdgeAuth (middleware/edgeauth.go) and the /admin/billing UI gate (billing/handler.go). It verifies tokens against the IAM JWKS. The gateway-trust middleware chain (IAMTokenRequired) is unchanged — it still reads validated headers.
A nil config or a build error leaves the client nil, so those edge surfaces fail closed (every request treated as unauthorized).
func InitKV ¶ added in v1.36.4
func InitKV(kv KVCache)
InitKV wires the KV cache used by org-id resolution.
func IsIAMAuthenticated ¶
IsIAMAuthenticated reports whether the request was identity-attached by either pkg/auth.Gin (preferred) or legacy IAMTokenRequired.