Skip to main content

bearer_matches

Function bearer_matches 

Source
pub fn bearer_matches(presented: Option<&str>, expected_key: &str) -> bool
Expand 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.