Nette Http 3.2: change access to credentials
A new version of Nette Http 3.2 has been released, which includes a backwards incompatible change that was made for security reasons. It concerns the way to obtain a username and password when logging in via HTTP Basic Authentication, the oldest technique performed directly by the browser.
Whereas previously the data were returned by methods of the
Nette\Http\Url class, now the new
Nette\Http\Request::getBasicCredentials() method is used to
// $request is a Nette\Http\Request object // previously $url = $request->getUrl(); $user = $url->getUser(); $password = $url->getPassword(); // since nette/http 3.2 [$user, $password] = $request->getBasicCredentials(); // $url->getUser() and $url->getPassword() now return ''
The reason for this change is purely security. Because the username and
password are no longer part of the
Url object, the risk that they
will be disclosed when the address is written out has disappeared (i.e.
Access to name and password via
$request->getUrl() has been
used in Nette since the beginning. Firstly, the Url class already had the
corresponding methods, but also in browsers it is possible to pass the username
and password directly in the address as
http://username:firstname.lastname@example.org, so such a solution was
offered. Today's browsers limit this functionality in various ways because it
has been misused for nefarious purposes. For example, attackers have lured users
https://YourBank.com@HackersSite.com/, which at first glance
looks like the real
YourBank.com address, but the first part of the
URL is actually a username.
But back to Nette. The risk of exposing login credentials was directly preceded by the Url class, which simply did not output them:
// Nette 2.x (and also 0.x) $url = new Nette\Http\Url('http://user:email@example.com'); echo $url; // http://example.org
Over time, however, there were requests to change the behavior because it was confusing to programmers. Starting with Nette Http 3.0, credentials are thus printed out:
// Nette 3.x $url = new Nette\Http\Url('http://user:firstname.lastname@example.org'); echo $url; // http://user:email@example.com
At the same time, instead of the original
presenters started working with a copy without credentials,
$request->getUrl()->withoutUserInfo(). However, and this is
the reason for the current change, the programmers may not have been aware that
printing out the original
$request->getUrl() had the risk of
disclosing credentials. Therefore, as of Nette Http 3.2, credentials are not
passed to the Url object at all. Thus, printing
$request->getUrl() is completely safe.
Instead, they are passed via the
Authorization header, which
contents can be decoded by the new
// Nette Http 3.2 $request->getHeader('Authorization'); // 'Basic dXNlcjpwYXNzd29yZA==' $request->getBasicCredentials(); // ['user', 'password']
If the browser does not send login credentials or if another authentication
method is used (e.g. Digest Access Authentication), method
getBasicCredentials() returns null.