Repository navigation
grpc: refresh trusted headers from continuous auth responses - #19
Merged
maoueh merged 3 commits intoOct 9, 2026
Merged
Conversation
continuousAuth discarded every response after the first, so the trusted headers of a stream were fixed by its first Authenticate call. When that call returned an empty success (e.g. an authenticator answering without its own upstream), the stream ran without x-user-id/x-meta for its whole lifetime even though later continuous calls returned them. Each continuous response is now merged into the stream's trusted headers: keys are added or updated, never removed. The headers live in an atomic holder on the context, and the new ReplaceTrustedHeaders swaps them; FromContext returns the current snapshot. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
matthewdarwin
force-pushed
the
continuous-auth-refresh-headers
branch
from
October 7, 2026 12:49
50f2ca2 to
5b7df03
Compare
matthewdarwin
marked this pull request as ready for review
October 7, 2026 12:54
…auth tests Document that FromContext's map must not be modified, that a nested WithTrustedHeaders shadows refreshes, and that removal is not handled by continuous auth refresh. Bump to Go 1.25 so continuous auth tests run under testing/synctest instead of real-time sleeps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
maoueh
approved these changes
Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With
continuous=true, the grpc plugin callsAuthenticateagain on every interval, but it only looks at the error. The response is discarded, so a stream's trusted headers are whatever the first call returned.If that first call returns an empty success, the stream keeps no
x-user-id/x-metafor its whole lifetime, even after later continuous calls return the full headers. An authenticator answers with an empty success when it chooses to fail open, for example a local sidecar that cannot reach its own upstream within its deadline. Metering then emits events without identity until the client disconnects. On long-lived Substreams/Firehose streams that can be hours of usage.Change
continuousAuthmerges each response's headers into the stream's trusted headers. Keys are added or updated, never removed. An empty response is a no-op, and an unchanged one skips the swap.atomic.Pointerholder on the context. The newReplaceTrustedHeaders(ctx, h)swaps them, andFromContextreturns the current snapshot. Metering reads the headers concurrently with the refresh, so the map is not mutated in place.FromContext's signature and return type are unchanged. Callers that copy values once at stream start keep the old values; to pick up refreshed headers they need to read them per event. Firehose already does this (firehose/server/server.go); Substreams tier1 does not, see the linked PR.No extra calls: the continuous requests already happen; only their responses are now used.
Tests
TestReplaceTrustedHeaders: derived contexts see the replacement, and earlier snapshots are unchanged.TestAuthenticatorPlugin_ContinuousAuthenticate_RefreshesHeaders: the first call returns empty and the second returns headers, which then appear on the context. Later empty responses do not remove them. The test reads concurrently with the refresh.go test -race -count=50 ./ ./grpc/passes.middleware/connect'sTest_validAuthis flaky ondevelopwithout this change (it fails intermittently with"987" != "123").🤖 Generated with Claude Code