Authentication and Throttling#
This document primarily serves to document our additions to DRF’s built-in throttling support. In order to accomplish this, some basic facts about our OAuth flow and configuration must also be explained.
This document deals primarily with the server’s perspective of the OAuth flow and assumes you are familiar with the user’s perspective. If you are not familiar with the user’s perspective, please study the Register and Authenticate section of the API documentation.
Furthermore, this section assumes at least a surface level understanding of the
django-oauth-toolkit library and its concepts. In particular, it is necessary
to understand the
Application concept, the docs for which can be found here.
When a user makes the initial request to create their OAuth application, we
ThrottledApplication model to associate to the likewise generated
OAuth client. Whenever the user generates a new token using their client ID and
key pair, it is automatically associated with the
ThrottledApplication for the
client via a
foreign key referencing the application on the access token.
This allows us to retrieve the application for the token using just the token
ThrottledApplication is an extension of the base
django-oauth-toolkit that adds an additional concept of a
rate_limit_model. Each rate limit model can be thought of as a “tiers” of rate
limiting that the Openverse API supports.
Rate limit models (tiers)#
The following tiers exist:
standard: The default rate limit that anyone is able to unlock simply by authenticating. Slightly higher and much more useful limit for an application.
enhanced: A selectively granted rate limit that allows for significantly higher burst and sustained requests.
exempt: A rate limit model that exists purely to accommodate internal infrastructural needs. For example, the server that renders the frontend can use tokens of this tier to prevent itself from being rate limited by the API during server side rendering. Likewise, when we need to circumvent the throttling to do load testing, we use a key of this tier.
Each of these tiers also have corresponding throttle classes that are configured
settings.py. Each throttle class declares a “scope” applied to it. The
“scope” defines the rate. The throttle class merely indicates to the view
whether it itself applies to the incoming request. If it does not, then it
None cache key from
get_cache_key and the view ignores the
throttle class. If the throttle does apply to the request, then it returns a
formatted cache key that the base DRF view then uses to determine whether the
requester is still within the limits of their scope.
To further understand this concept, it may be helpful to read the code for
check_throttles method of the DRF base view class.
Each of the tiers above have their own scope namespace. For example, enhanced
applications will use the scopes namespaced with
enhanced_oauth2_client_credentials. To determine which scope a given
authenticated request should have applied to it, we need to determine which
application rate limit tier it belongs to. To simplify this abstract process, we
OAuth2IdRateThrottle base class. All it does is take an incoming
authenticated request, retrieve the application for the given access token, and
then create a cache key based on the client ID and scope if the class is
configured to handle the application’s rate limit tier.
Individual tiers have complementary subclasses of
configure which scope to apply to a particular rate limit tier. Please refer to
catalog.api.utils.throttle module for example implementations of this