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