feat: log and meter rate-limited external auth token validation by jscottmiller · Pull Request #26754 · coder/coder · GitHub
Skip to content

feat: log and meter rate-limited external auth token validation#26754

Draft
jscottmiller wants to merge 3 commits into
mainfrom
scott/plat-153-rate-limited-token-validation-is-invisible-to-operators
Draft

feat: log and meter rate-limited external auth token validation#26754
jscottmiller wants to merge 3 commits into
mainfrom
scott/plat-153-rate-limited-token-validation-is-invisible-to-operators

Conversation

@jscottmiller

@jscottmiller jscottmiller commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

When ValidateToken keeps a token because the validation endpoint returned a rate-limited response (a 403 with rate-limit headers or a 429), it previously returned valid=true silently. Operators had no way to tell a provider-confirmed token apart from one kept optimistically during a rate limit.

This change is observability-only. The valid/invalid decision is unchanged.

Approach

The existing coderd_oauth2_external_requests_total{name, source="ValidateToken", status_code} metric already distinguishes the unambiguous outcomes: 200 (confirmed), 429 (rate-limited), and 401 (invalid). The only gap is that a 403 is ambiguous (genuine revocation vs. rate limit). This PR closes that gap with a structured Warn log on the optimistic paths, rather than adding a new metric, keeping externalauth concerns out of the generic OAuth2 instrumentation.

Changes

  • coderd/externalauth: Add a Logger to Config (zero value is a no-op). On both rate-limit branches (403 with rate-limit headers, 429), emit a Warn with provider_id, provider_type, status_code, and reason. ConvertConfig now takes a logger.
  • cli/server.go: Pass the existing logger into ConvertConfig.

Tests

TestValidateToken asserts the structured Warn log fields across the rate-limited (403 + headers, 403 + Retry-After, 429) cases, and asserts no warning is logged for genuine revocations, 401, and confirmed (200) responses.

Verified: affected packages build, go test ./coderd/externalauth/... passes, gofmt clean, golangci-lint clean.

Design notes

Earlier revisions added a dedicated coderd_oauth2_external_requests_token_validation_total{name, result} counter. Reaching it from ValidateToken required either bolting a RecordTokenValidation method onto the generic InstrumentedOAuth2Config interface or threading a recorder callback through ConvertConfig, both of which leaked an externalauth-specific concern into the OAuth2 abstraction. Since the existing request metric plus the new log already cover the operator need, the dedicated counter was dropped.


🤖 Generated with the help of Coder Agents on behalf of @jscottmiller.

When ValidateToken keeps a token because the validation endpoint
returned a rate-limited response (403 with rate-limit headers or 429),
emit a Warn log and increment a new counter
coderd_oauth2_external_requests_token_validation_total{name,result} so
operators can distinguish a provider-confirmed token from one kept
optimistically during a rate limit. The valid/invalid decision is
unchanged.
@linear-code

linear-code Bot commented Jun 26, 2026

Copy link
Copy Markdown

Replace the RecordTokenValidation method on InstrumentedOAuth2Config with
a Factory.TokenValidationRecorder that returns a per-provider recorder
function. externalauth.Config holds the recorder as a private field set
by ConvertConfig, so the metric stays in promoauth without bolting an
externalauth-specific concern onto the generic oauth2 abstraction. The
test fake no longer needs to implement an unrelated method.
Remove the dedicated token validation counter and all of its wiring
(the promoauth counter, the Factory recorder, and the Config field).
The existing coderd_oauth2_external_requests_total{source="ValidateToken",
status_code} metric already distinguishes confirmed (200), rate-limited
(429), and invalid (401) outcomes, and the new Warn log captures the
ambiguous rate-limited 403 case. This keeps externalauth concerns out of
the generic oauth2 instrumentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant