AUTH4D-334 device authorization budgets

The device flow endpoints spend a per-IP budget first, so one caller cannot use up the budget of a whole application or of a player’s code. Client-wide and tenant-wide budgets remain as backstops sized for real traffic. The routes, request shapes and success responses are unchanged.

Budgets

Budgets are spent in the order listed. The first one that is exhausted refuses the request.

Endpoint Budgets, in order
POST /device/authorization 60 an hour per IP; then 1,000 an hour per application
POST /oauth/token (device code grant) 240 a minute per IP; then 12 a minute per device code; then, only for a live device code, 3,000 a minute per application
GET /device/verify (JSON) 60 an hour per IP; then 10,000 an hour per tenant, shared with approve and deny; then 5 an hour per user code
POST /device/approval, POST /device/denial 30 an hour per IP, after the signed-in session and CSRF checks; then the same tenant and per-user-code budgets as verify
  • IP addresses come from CF-Connecting-IP and are HMAC-pseudonymised before they reach the Durable Object, like every other per-IP budget. A request with no resolved address shares one bucket instead of skipping the limit.
  • The application poll budget is spent only after the device code has been found, belongs to this tenant and application, and has not expired. Polls with unknown or expired codes never count towards it, so they cannot cause slow_down for real codes.
  • The application start budget is a backstop for many addresses at once. About 1,000 codes an hour, each live for up to 10 minutes and polled 12 times a minute, stays under the poll backstop.

Responses

A refused request returns the same error as before:

HTTP/1.1 429 Too Many Requests
Cache-Control: no-store, max-age=0
Content-Type: application/json

{ "error": "slow_down" }

When the application poll backstop refuses a poll, the device code is left exactly as it was, so the next poll after the window resets continues normally.

RFC 8628 slow_down for real codes is unchanged: a poll before the current interval has passed returns 400 slow_down and adds 5 seconds to the code’s interval.

Configuration

The defaults are DEVICE_ABUSE_BUDGETS in apps/api/src/modules/device/index.ts. DeviceFeatureOptions.budgets overrides any of them, for deployments that need different limits and for tests.

Tests: tests/integration/auth4d-334.device-budgets.test.ts.

Source: docs/api-spec/auth4d-334.md