Skip to content

Conversation

@smallinsky
Copy link
Contributor

@smallinsky smallinsky commented Nov 25, 2025

What

Fix rate limiting logic in WithUnauthenticatedLimiter and WithAccessDeniedLimiter middleware to check rate limits before performing authentication or executing the handler.

Problem

Previously, these middleware functions would:

  1. Execute authentication checks (allow to guessing the token without rate limiting)
  2. Only apply rate limiting after the auth operations completed

Requires #61776

Address #61510

Contributes to #61511

@smallinsky smallinsky marked this pull request as ready for review November 25, 2025 19:11
Copy link
Contributor

@juliaogris juliaogris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a few question.

Generic testing / compatibility question: For new test code should we favor synctest over clockwork.FakeClock?

}

// IsRateLimited checks if consuming the specified number of tokens would be rate-limited
// without actually consuming any tokens. Returns true if rate-limited, false otherwise.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says "consuming the specified number of tokens" but the method takes no parameters and always checks if there's at least 1 token available.

Maybe update to:

 // IsRateLimited checks if the bucket is currently rate-limited (no tokens available)
  // without actually consuming any tokens. Returns true if rate-limited, false otherwise.

}

func rateLimitRequest(r *http.Request, limiter *limiter.RateLimiter) error {
remote, _, err := net.SplitHostPort(r.RemoteAddr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be updated to:

remote, err := getRemoteAddressFromRequest(r)

func isRequestRateLimited(r *http.Request, limiter *limiter.RateLimiter) bool {
remote, err := getRemoteAddressFromRequest(r)
if err != nil {
return false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silently swallows error - does this deserve a comment?

conditionalLimiterFunc returns an error if getRemoteAddressFromRequest fails
unauthenticatedLimiterFunc does not, should they be consistent?

callCount := 0
handle := h.WithUnauthenticatedLimiter(func(w http.ResponseWriter, r *http.Request, p httprouter.Params) (any, error) {
callCount++
return nil, trace.BadParameter("invalid request")
Copy link
Contributor

@tcsc tcsc Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason for not returning 200 here?

I mean, is the specific status code important, other than

  1. being preserved by the WithUnauthenticatedLimiter adapter, and
  2. not being StatusBadRequest so you can tell when the rate limiter kicks in?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants