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
//! Shared plumbing for the OAuth adapters' outbound HTTP calls.
//!
//! Two adapters talk to an authorization server — introspecting a token and
//! redeeming a code — and both need the same two things: a reason string that
//! cannot leak the credential the request carried, and a bounded read of the
//! response. They live here rather than in each adapter because a size cap
//! copied into two files is a cap that will eventually be fixed in one of them.
/// The most these adapters will read from one response.
///
/// An authorization server is not trusted to bound its own answer. One that is
/// compromised, or merely streaming forever, would otherwise be a way to
/// exhaust this process's memory from a single call — and the call that does it
/// is one this process believed was authenticated. 64 KiB is far more than any
/// legal response: both documents are a handful of short strings.
pub const MAX_RESPONSE_BYTES: usize = 64 * 1024;
/// Read a response body, stopping if it grows past [`MAX_RESPONSE_BYTES`].
///
/// Enforced while reading rather than after, because `content_length` is a claim
/// the peer makes about itself and is absent entirely from a chunked response —
/// checking it and then calling `bytes()` would bound only the responses that
/// chose to be bounded. `chunk()` needs no `StreamExt`, which keeps this off the
/// `futures` facade for one loop.
///
/// The failure is a reason string rather than a shared error type on purpose:
/// introspection and redemption refuse in their own error enums, and this
/// function has no business knowing either of them.
pub async
/// Why an HTTP call to the authorization server failed, without the credential.
///
/// `reqwest`'s `Display` for a transport error names the URL and the cause but
/// never the body, and these adapters only ever put credentials in a body — so
/// the failure text is safe to surface in a log.
///
/// Asserted by each adapter's redaction test.