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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! The identity a per-user rate-limit decision may be keyed on (#1171).
//!
//! #1143 deleted the HTTP per-user allowance, and the reason is the whole design of this
//! module. The only identity available at the limiter came from `extract_jwt_subject`,
//! which base64-decoded a JWT payload and never checked the signature. A fresh key is a
//! fresh *full* bucket, so varying `sub` did not merely grow the map: it handed the
//! caller an unlimited budget. Measured then: 50 of 50 requests allowed against
//! `rps_per_ip = 1, burst = 1`, from one IP, unauthenticated. Deleting it removed a
//! bypass rather than a control.
//!
//! What it left behind is a real gap, though: every HTTP request buckets on its IP, so
//! all the authenticated users behind one egress address share one budget — and the
//! per-user allowance exists precisely because an identified caller is a different risk
//! from an anonymous address.
//!
//! Restoring it needs a *verified* subject, which is what this seam carries: the
//! deployment's own configured validator, not a decoder. A token that does not verify
//! yields `None` and the request falls back to the IP bucket, so a forged JWT cannot
//! mint anything — the property #1143 established, kept as a test.
//!
//! The verification is a second one: the transport's auth layer runs later and does its
//! own, plus revocation and the service-account seam. Sharing a result across the two
//! would mean this layer deciding what counts as authenticated, which is not its job. An
//! HS256 check is an HMAC; an OIDC check is an RS256 verify against an already-cached
//! JWKS. Neither is a network call on the hot path.
use Arc;
use ;
use ;
/// The validator a per-user rate-limit decision verifies its subject with.
///
/// An enum rather than a trait object, because the set is closed and known: `attach_auth`
/// picks between exactly these two modes, in this order. Adding a third auth mode should
/// be a compile error here as well as there — a `dyn` seam would instead let the limiter
/// silently keep bucketing everyone on their address.
/// The bearer token, from the `Authorization` header or the `__Host-access_token`
/// cookie — the same two places [`crate::middleware::oidc_auth_middleware`] looks, so a
/// request cannot be authenticated by the transport and anonymous to the limiter.