Follow-ups: flow-serving bridge (gateway verification gate + review findings from #12-#20) #30
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lab/authz-bridge#30
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent
#11 — Spec: The flow-serving bridge (gRPC ext_authz Check + OIDC/Exchange flows + callback/logout listener)
What this is
The single tracking ticket for the work that spec #11's implementation surfaced but did not include: one spec verification gate that was never performed, plus the code-review follow-ups from the nine build tickets (#12–#20, all merged). Broken down into individual tickets when scheduled.
Status (updated 21 Sep 2026)
Verified against the current tree:
tokenExchange(exchange.go), the refresh grant (oidc.go), andauthorizationCodeExchange(callback.go) remain three separate form-POST skeletons; no shared helper.TokenEndpointnot gated): still open.App.OIDCAvailable()(snapshot.go) checks the authorization endpoint, callback set, and JWKS, but notShared.TokenEndpoint— the OIDC gate still misclassifies a never-resolved token endpoint as a failed refresh (302 loop) rather than the ADR 0011 503 unavailable class.defaultTokenTTLis still a fixed 60s with no subject-expcap (overlaps #61 item 3).matchCallbackPathstill comparesu.Path == reqPath, so a callback registered at the hostname root (https://host, empty path) never matches/(403); the multi-URLredirect_uri = CallbackURLs[0]vs match-by-path note still has no test/comment.Items
1. Gateway verification gate (spec #11 — the only unperformed spec item)
The spec's verified gate: the lab gateway must honor
denied_response(302+Location+Set-Cookie) andresponse_headers_to_add(Set-Cookie), and the OIDC rule'sallowedHeadersmust listcookie(ADR 0003). If unmet, the OIDC Flow does not work on that gateway (the Exchange Flow still does — it needs no302). Verify against the lab gateway; this is the difference between "the flows are built" and "the flows work end-to-end behind the gateway".2. Shared token-endpoint POST helper (cross-cutting, from the #16/#17 reviews)
tokenExchange(internal/serve/exchange.go),tokenRefresh(internal/serve/oidc.go), andauthorizationCodeExchange(internal/serve/callback.go) are three copies of the same form-POST skeleton: build form →NewRequestWithContext→Content-Type→Do→ReadAll→Unmarshal→ status/error/missing-token checks. Extract a sharedpostFormToTokenEndpoint-style helper; each grant fills the form and defines its own success check. Related (optional): the unavailable-reason gates (unavailableReason/exchangeUnavailableReason/callbackUnavailableReason) share the same cascade shape but check different fields — a shared helper is possible but would need care to keep behavior identical.3. Availability gate:
TokenEndpointnot gated (from the #17 review)unavailableReason(the OIDC Check's 5xx gate) checks the client secret, the OIDC section, the authorization endpoint, the callback URLs, and the JWKS — but notShared.TokenEndpoint. An App whose token endpoint never resolved surfaces as a failed refresh (a 302 re-login loop) instead of the ADR 0011503"unavailable" class for broken config. Fail-closed, but misclassified. Fix: includeTokenEndpoint == ""in the gate (the callback and exchange gates already check it).4. Token cache TTL fallback bound (from the #18 review)
When the token endpoint omits
expires_in, the per-replica cache falls back to a fixed 60s TTL, which can exceed the token's actual exp (the backend then 401s — not a mis-authorization, but it breaks the ADR 0009 "TTL-bounded ≤ the access token's exp" guarantee). Kanidm always sendsexpires_in, so this is an edge case; consider a smaller fallback or documenting the assumption.5. Callback edge cases (from the #16 review — low priority)
https://host) never matches the request path/(always 403).redirect_uriisCallbackURLs[0]while the callback matches by path. Safe in the real IdP flow (the IdP only redirects to the requestedredirect_uri; direct navigation to another registered path is 403'd — fail-closed), but worth a test or a comment.6. Gateway CRDs are test-only (from the #20 review — decision needed)
The gateway-api CRDs are committed only under
test/crds/gateway-api/for envtest; the install bundle assumes a Gateway implementation (which ships the CRDs) is present in-cluster. Decide whether the bundle should be self-contained (ship the CRDs) or document the assumption.Out of scope
Anything that changes the merged behavior of #12–#20 beyond the fixes above; new Flow kinds (ADR 0004's future work); the state model (spec #1).