Hello libwww, I've encountered a situation where browsers "just work" but LWP::UserAgent fails.
This is a border case which apparently went unnoticed for decades, and for my own problem I've found a ridiculously easy workaround. So I'm not sure whether it is a good idea or worth the effort to change things. I volunteer to create a test case but am hesitating with a fix because this might break things in the real world. SETUP: * A web server with basic authentication for an auth realm (chosen somewhat, but not completely arbitrary): $realm = "data, protected"; * A LWP::UserAgent which gets passed the correct credentials with: $ua->credentials($netloc,$realm,$uid,$password); SYMPTOM: No matter what, you'll get a 401 status code for every request. The web server sends a WWW-Authenticate header: WWW-Authenticate: Basic realm="data, protected" On the client side, it turns out that the requests don't contain the corresponding Authorization header. ROOT CAUSE: When processing the WWW-Authenticate header, LWP::UserAgent unconditionally changes all commas in this header's value to semicolons: $challenge =~ tr/,/;/; # "," is used to separate auth-params!! But this modifies the realm if there's a comma in it. Therefore, there's no longer a match when the credentials are looked up later in the process, so no credentials are sent with the request. The code change happened almost exactly 20 years ago, in commit c4cefa219297e42ce73a10b6ad1fe4d9a19a9373 (1997-12-01). Since then, RFC 2068 (dated Jan 1997) was obsoleted by RFC 2617 (Jun 1999), which in turn has been obsoleted by RFC 7235 (Jun 2014). But does that say that it is reasonably safe to rely on HTTP::Header::Util to split words as intended? Is it safe to do that replacement only _after_ the string "auth-params" or are there other values where that replacment is required? WORKAROUNDS: * Either get rid of the comma in the web server's realm definition. Can be tricky it isn't _your_ server. * Or do the same unconditional modification to the realm before passing it to the LWP::UserAgent's credentials method. (BTW: Fixing it in LWP::UserAgent's get_basic_credentials method is possible but ugly, and not fully sufficient because you are advised to override this method when subclassing). * Or, if you're actually using a derived class like WWW::Mechanize and talk to just one application, use the credentials method of this class which allows to omit $netloc and $realm. -- Cheers, haj