Authority Rate Limit Guidance

Audience: Authority operators, SOC, Security Guild. Scope: Fixed-window rate limiting on the /token, /authorize, and /internal/* routes — recommended defaults, override scenarios, partitioning behaviour, and monitoring practices.

Stella Ops Authority applies fixed-window rate limiting to critical endpoints so that brute-force and burst traffic are throttled before they can exhaust downstream resources. This guide complements the Standard-plugin credential lockout controls (see etc/authority.plugins/standard.yamllockout, and the Authority plugin developer guide) and the password-hashing guidance.

The limiter is wired in Program.cs via AddRateLimiter(... AuthorityRateLimiter.Configure(...)) and runs as a single ASP.NET Core GlobalLimiter (AuthorityRateLimiter.CreateGlobalLimiter). Inside that global limiter each of the three endpoint groups gets its own fixed-window partition; the three groups are identified internally by the partition-key prefixes authority-token, authority-authorize, and authority-internal (AuthorityRateLimiter.TokenLimiterName/AuthorizeLimiterName/InternalLimiterName). They are not registered as named ASP.NET Core rate-limit policies, so the built-in limiter metric dimension is not populated from a policy name (see Monitoring and Alerts). Rejected requests return HTTP 429 Too Many Requests (RejectionStatusCode).

Configuration Overview

Rate limits live under security.rateLimiting in authority.yaml (bound to AuthorityRateLimitingOptionsAuthorityEndpointRateLimitOptions). Each endpoint exposes:

security:
  rateLimiting:
    token:
      enabled: true
      permitLimit: 30
      window: 00:01:00
      queueLimit: 0
    authorize:
      enabled: true
      permitLimit: 60
      window: 00:01:00
      queueLimit: 10
    internal:
      enabled: false
      permitLimit: 5
      window: 00:01:00
      queueLimit: 0

The shipped etc/authority.yaml defines only the token and authorize blocks; the internal limiter is disabled by default (its in-code defaults are permitLimit: 5, window: 00:01:00, queueLimit: 0). Add the internal block only when you need to throttle the /internal/* bootstrap routes.

When a request is throttled, AuthorityRateLimiter.Configure’s OnRejected callback writes a Retry-After response header (ceiling of the lease’s retry-after in whole seconds) and logs a warning with the request path and remote IP. Before the limiter runs, AuthorityRateLimiterMetadataMiddleware captures structured tags on the request for correlation. The tags it sets are:

Environment overrides bind through StellaOpsAuthorityConfiguration (EnvironmentPrefix = "STELLAOPS_AUTHORITY_", BindingSection = "Authority"). Because the environment-variable provider strips the prefix and binds the Authority section using __ as the hierarchy separator, the key must retain the Authority section segment after the prefix. For example:

STELLAOPS_AUTHORITY_AUTHORITY__SECURITY__RATELIMITING__TOKEN__PERMITLIMIT=60
STELLAOPS_AUTHORITY_AUTHORITY__SECURITY__RATELIMITING__TOKEN__WINDOW=00:01:00

The values below are the token limiter defaults and suggested overrides. The shipped default (AuthorityRateLimitingOptions) is token = permitLimit 30 / window 00:01:00 / queueLimit 0 and authorize = permitLimit 60 / window 00:01:00 / queueLimit 10. Note that window is capped at one hour by validation, so the “Incident lockdown” example below uses 00:05:00 (300s), well within the limit.

ScenariopermitLimitwindowqueueLimitNotes
Default production3060s0Matches the shipped token default; leaves headroom for tenant bursts.
High-trust clustered IPs6060s5Requires WAF allowlist + an alert when authority rate-limit rejections stay above ~1% sustained (see Monitoring and Alerts).
Air-gapped lab10120s0Lower concurrency reduces noise when running from shared bastion hosts.
Incident lockdown5300s0Pair with a reduced Standard-plugin lockout.maxAttempts (default 5) and SOC paging for each denial.

Partitioning behaviour

DefaultAuthorityRateLimiterPartitionKeyResolver builds the per-window partition key as follows:

This means two different client_id values from the same IP get independent token-window budgets (verified by AuthorityRateLimiterIntegrationTests.TokenEndpoint_AllowsDifferentClientIdsWithinWindow).

Lockout Interplay

Monitoring and Alerts

  1. Metrics
    • aspnetcore_rate_limiting_rejections_total — the ASP.NET Core rate-limiter rejection counter. Note: because Authority uses a single GlobalLimiter rather than named policies, the limiter label is not populated with authority-token/authority-authorize from a policy name. The authority-* strings are internal partition-key prefixes, not exported as the meter’s limiter dimension. Filter or split by service_name="stellaops-authority" and correlate the specific endpoint via the structured log tags below rather than relying on a per-endpoint limiter label. (Existing dashboards under docs/modules/authority/operations/ use the {limiter=...} form for forward compatibility; treat that series as empty until named policies are introduced.)
    • Custom counters/dashboards derived from the structured log tags emitted by AuthorityRateLimiterMetadataMiddleware (authority.endpoint, authority.remote_ip, authority.client_id, authority.forwarded_for). These are the authoritative per-endpoint, per-client correlation signals.
  2. Dashboards
    • Requests vs. rejections per endpoint.
    • Top offending clients/IP ranges in the current window.
    • Heatmap of retry-after durations to spot persistent throttling.
  3. Alerts
    • Notify SOC when 429 rates exceed 25 % for five consecutive minutes on any limiter.
    • Trigger client-specific alerts when a single client_id produces >100 throttle events/hour.

Operational Checklist