pub fn bearer_matches(presented: Option<&str>, expected_key: &str) -> boolExpand description
Whether presented — the raw Authorization header value, or None when
the client sent none — carries expected_key.
§Why the scheme is matched case-insensitively
RFC 9110 §11.1 defines the auth scheme as a token, and tokens are
case-insensitive. bearer sk-… is therefore a correct request, and the
previous comparison — the whole "Bearer <key>" string, byte for byte —
answered it with a 401 that said the key was wrong. It was not; only its
capitalisation was, and nothing in the response said so. That is the least
actionable rejection available, and it matters here beyond pedantry: the
tunnel in front of this endpoint accepts the same header the RFC does, so
two doors checking one credential disagreed about whether it was valid.
The scheme comparison is deliberately not constant-time. It is a public
protocol keyword, not a secret, and there is nothing to leak by returning
early on it. Only the credential goes to constant_time_eq.
§What is still refused
Everything a lenient comparison would wave through. A different scheme
(Basic <key>), the bare key with no scheme at all, a prefix of the key,
and an empty credential are all rejected. The last of those is load-bearing:
settings validation refuses a blank proxy_api_key precisely so that
Bearer cannot become a credential everyone holds, and splitting the
header on its space must not reintroduce that from the other side.
Whitespace follows the grammar rather than being trimmed indiscriminately:
the scheme and the credential are separated by one or more spaces
(1*SP), and trailing optional whitespace is not part of the credential.