Rate limiting based on a unique attribute in the request

Not sure if we need to use Workers for this - or just the vanilla rate limiting feature.

We have a REST API. Requests to the API are either public or authenticated.

If they are authenticated, we know who the tenant is (the orgID as we call it) and who the user is - i.e. a specific person like “John Smith” who presents a token from a specific company e.g. “Pepsi”.

Given what we know - we want to rate-limit that specific user OR (not in scope at present) have the ability to rate-limit the entire organization.

This ensures that if the user’s credentials leak out or get stolen, identified by a unique HTTP header like X-Tallyfy-UserID = 21435352 (the criteria) OR/AND the OAuth token itself - we can rate limit a single user based on these attributes.

In our case, all authenticated calls to our API use a known tenant with a known user - so we want to rate-limit usage per-user, per-tenant at the edge. How do we achieve this?

I’m afraid that it’s not possible though it does seem like a cool feature I can see our company using.

2 Likes

You could do this using Durable Objects :slightly_smiling_face:

1 Like

@albert many thanks esp. for noting Reusing Durable Objects - #4 by albert

A question - the criteria for rate-limiting is super-important. The trouble with OAuth tokens or session keys is that you can always create new session keys, I believe. A malicious actor could just cycle a new key every minute, and carry on hammering an API “as” a user, without rate limiting consequences.

In your opinion/approach - are you seeing rate-limiting as a per-user thing i.e. there needs to be a header on HTTP requests indicating a userID, and rate-limiting is based on a userID’s number of API calls from any number of IP’s (because those are changeable too) and any number of OAuth/session tokens/keys?

Just trying to think of a foolproof way that a bad actor cannot get round rate limiting at all, for an authentication-driven API.

Haven’t tried this myself but might work. Use CF Transform rules https://developers.cloudflare.com/rules/transform to tag on a request header modification https://developers.cloudflare.com/rules/transform/request-header-modification/create-dashboard and use various criteria outlined at https://developers.cloudflare.com/firewall/cf-firewall-language/fields and https://developers.cloudflare.com/rules/transform/request-header-modification/reference/fields to validate legit requests and then add a secondary request header modification which your backend or CF Worker can use to validate and process the request.

Example of inspecting HTTP request header https://developers.cloudflare.com/firewall/cf-firewall-language/fields#http-header-fields

CF Transform header modifications do come before CF Workers if CF Traffic Sequence diagram is correct :slight_smile:

Examples https://developers.cloudflare.com/rules/transform/request-header-modification/examples

How about rate limiting the OAuth token creation endpoint and the actual token. Would that work?

you could I guess - but you can keep rotating your country and referrer IP to look like someone new on every request, right?

With the token - it’s temporary by nature, and I was actually digging into the OAuth API defaults we use - it doesn’t seem like there’s any refresh token limit.

Don’t you require some form of authentication to create an OAuth token? I’d just rate limit that identification, be it username or something else, using Durable Objects like I showed above. Though I’ve never used OAuth before so I might not know what I’m talking about :slightly_smiling_face: