Skip to main content

alibi_plugins/oauth_provider/
rate_limit.rs

1//! Protocol quotas registered with the application's canonical rate limiter.
2use alibi_core::{EndpointRateLimit, PluginRateLimit};
3
4/// A provider rule can inherit its endpoint default, replace it, or be omitted.
5/// `Disabled` omits only the plugin rule: global/application policy still applies.
6#[derive(Debug, Clone, Default)]
7pub enum OAuthEndpointRateLimit {
8    #[default]
9    Default,
10    Disabled,
11    /// Both values are supplied, including zero, as in the published provider API.
12    Limit(EndpointRateLimit),
13}
14
15/// OAuth protocol endpoint policies, in seconds and requests per client/path.
16/// Rules are effective only when application rate limiting is enabled; its
17/// storage and ordered custom rules remain authoritative.
18#[derive(Debug, Clone, Default)]
19pub struct OAuthProviderRateLimits {
20    /// Defaults to 20 requests per 60 seconds.
21    pub token: OAuthEndpointRateLimit,
22    /// Defaults to 30 requests per 60 seconds.
23    pub authorize: OAuthEndpointRateLimit,
24    /// Defaults to 100 requests per 60 seconds.
25    pub introspect: OAuthEndpointRateLimit,
26    /// Defaults to 30 requests per 60 seconds.
27    pub revoke: OAuthEndpointRateLimit,
28    /// Defaults to 5 requests per 60 seconds.
29    pub register: OAuthEndpointRateLimit,
30    /// Defaults to 60 requests per 60 seconds, shared by GET and POST.
31    pub userinfo: OAuthEndpointRateLimit,
32    /// Defaults to 5 requests per 60 seconds.
33    pub rotate_client_keys: OAuthEndpointRateLimit,
34}
35
36type RoutePolicy<'a> = (fn(&str) -> bool, &'a OAuthEndpointRateLimit, f64);
37
38impl OAuthProviderRateLimits {
39    pub(super) fn rules(&self) -> Vec<PluginRateLimit> {
40        let routes: [RoutePolicy<'_>; 7] = [
41            (|path| path == "/oauth2/token", &self.token, 20.0),
42            (|path| path == "/oauth2/authorize", &self.authorize, 30.0),
43            (|path| path == "/oauth2/introspect", &self.introspect, 100.0),
44            (|path| path == "/oauth2/revoke", &self.revoke, 30.0),
45            (|path| path == "/oauth2/register", &self.register, 5.0),
46            (
47                |path| path == "/oauth2/client/rotate-keys",
48                &self.rotate_client_keys,
49                5.0,
50            ),
51            (|path| path == "/oauth2/userinfo", &self.userinfo, 60.0),
52        ];
53        routes
54            .into_iter()
55            .filter_map(|(matches, policy, max)| {
56                let limit = match policy {
57                    OAuthEndpointRateLimit::Disabled => return None,
58                    OAuthEndpointRateLimit::Default => EndpointRateLimit {
59                        window_seconds: 60.0,
60                        max_requests: max,
61                    },
62                    OAuthEndpointRateLimit::Limit(limit) => limit.clone(),
63                };
64                Some(PluginRateLimit { matches, limit })
65            })
66            .collect()
67    }
68}