Skip to main content

parse_www_authenticate

Function parse_www_authenticate 

Source
pub fn parse_www_authenticate(s: &str) -> Vec<Challenge>
Expand description

Parse a WWW-Authenticate / Proxy-Authenticate field value into a list of Challenges, per RFC 9110 §11.6.1:

WWW-Authenticate = #challenge
challenge        = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
auth-scheme      = token
auth-param       = token BWS "=" BWS ( token / quoted-string )
token68          = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~"
                       / "+" / "/" ) *"="

§The §11.6.1 list ambiguity

Both the challenge list AND the auth-param list inside a challenge are comma-separated, so a flat top-level comma split cannot by itself tell “next challenge” from “next auth-param of the current challenge”. §11.6.1 spells out the worked example:

WWW-Authenticate: Basic realm="simple", Newauth realm="apps",
                  type=1, title="Login to \"apps\""

which is two challenges: Basic with realm="simple", and Newauth with realm="apps", type=1, title="Login to \"apps\"".

The disambiguation rule this parser applies, after a quoted-string- aware top-level comma split (§5.6.1 #-list, so a comma inside a "…" value never splits): each list element is classified as either

  • a bare auth-param (token BWS "=" …) — it has NO scheme of its own, so it attaches to the challenge currently being built; or
  • a challenge head (auth-scheme alone, or auth-scheme 1*SP <arg>) — it starts a new challenge.

An element is a bare auth-param when its first token is immediately followed (modulo §11.2 BWS around =) by = with no intervening 1*SP scheme/argument boundary. Everything else opens a new challenge, whose first whitespace-delimited token is the auth-scheme and whose remainder (if any) is the first token68 or first auth-param.

§Token68 vs auth-param within a challenge

§11.2’s token68 may end in *"=", which collides with the auth-param =. The parser treats a challenge argument as token68 only when it is one whitespace-free run whose body is all token68 characters with any = confined to a trailing pad run AND it is not of name=value auth-param shape; otherwise the remainder is parsed as the #auth-param list. Once a challenge has committed to auth-params, subsequent bare auth-param elements attach to it.

§Robustness

Matching the rest of the driver’s §5.6.1 list handling, malformed pieces are skipped rather than failing the whole parse: an empty list element (the §11.6.1 “comma, whitespace, comma” note calls this harmless), an auth-param slot that is not token = (token / quoted-string), or a leading bare auth-param with no challenge to attach to are all dropped while the surrounding well-formed challenges survive. An obs-fold (RFC 7230 §3.2.4) anywhere in the value is normalised to a single SP before parsing.

The same grammar backs Proxy-Authenticate (§11.7.1) and, with the credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ] production being identical, a single Authorization / Proxy-Authorization value (which carries exactly one challenge- shaped credentials); a caller wanting just the credentials reads the first element of the returned Vec.