Problem
When auth is disabled, Authorize returns c.Next() with zero checks
(auth/middleware/middleware.go:222-224):
if !auth.Enabled || auth.Address == "" {
return c.Next()
}
The gRPC interceptor does the same (middlewareGRPC.go:49, :235). A blank or
missing Address, or Enabled=false, silently turns the middleware into a
pass-through — the service serves every route unauthenticated.
Impact
One missing/typo'd env var (empty Address) downgrades a protected service to
fully open with no error, no log gate, no boot failure. Fail-open is the default
posture, exactly inverted from what a security-sensitive deployment wants.
Proposal
Add an opt-in fail-closed switch (e.g. AUTH_REQUIRED=true / AuthClient.Required):
- When set and auth is disabled/misconfigured (
!Enabled || Address == ""),
refuse to mount: return an error from the constructor / a hard 503 from the
handler instead of c.Next().
- Default
false preserves current behavior (backward-compatible).
Downstream context
midaz now compensates per-service with boot gates (tracer:
components/tracer/internal/bootstrap/auth_presence.go fails boot when no auth
mechanism is enabled outside local mode; ledger:
components/ledger/internal/bootstrap/config.go fails boot in production when
auth is disabled). That is N hand-rolled gates, one per service, drifting
independently. The fail-closed posture belongs upstream in one place.
Problem
When auth is disabled,
Authorizereturnsc.Next()with zero checks(
auth/middleware/middleware.go:222-224):The gRPC interceptor does the same (
middlewareGRPC.go:49,:235). A blank ormissing
Address, orEnabled=false, silently turns the middleware into apass-through — the service serves every route unauthenticated.
Impact
One missing/typo'd env var (empty
Address) downgrades a protected service tofully open with no error, no log gate, no boot failure. Fail-open is the default
posture, exactly inverted from what a security-sensitive deployment wants.
Proposal
Add an opt-in fail-closed switch (e.g.
AUTH_REQUIRED=true/AuthClient.Required):!Enabled || Address == ""),refuse to mount: return an error from the constructor / a hard 503 from the
handler instead of
c.Next().falsepreserves current behavior (backward-compatible).Downstream context
midaz now compensates per-service with boot gates (tracer:
components/tracer/internal/bootstrap/auth_presence.gofails boot when no authmechanism is enabled outside local mode; ledger:
components/ledger/internal/bootstrap/config.gofails boot in production whenauth is disabled). That is N hand-rolled gates, one per service, drifting
independently. The fail-closed posture belongs upstream in one place.