Note: security & performance considerations are discussed below.
Changed concept of "cookie authentication". Currently, the token auth is stored insecurely in the piwik_auth cookie. When this cookie is in a request to Piwik, this token auth is used to authenticate the request. The authentication is also delegated to the Auth implementation. This PR changes the strategy.
Now, the session stores information related to who the session is for (including IP address, user agent and a randomly generated secret). The piwik_auth cookie now contains a md5 hash of this randomly generated string + the last time a user's password was changed.
If the cookie is present in a request, Piwik core will use
SessionAuth, and bypass plugin based authentication altogether. SessionAuth will check that the session has been authenticated already, check that the request using the session is from the same place that initiated the session, and that the password hasn't changed since.
ts_password_modified. This column holds the last time the user's password was changed. This column is used to automatically invalidate sessions after a user's password is changed (so we don't have to iterate over sessions or anything).
There should be no BC breaks. Plugins do not have to call
Login::initAuthenticationFromCookie() anymore, but existing implementations don't have to be modified.
What info is compromised if the piwik_auth cookie is compromised?
Would an attacker be able to use the piwik_auth cookie to gain access to Piwik?
What would an attacker gain if the server side session variables were somehow compromised?
The only way I can think of for an attacker to gain access to a session, is for the attacker to:
Since we're using a weak hash in SessionAuth, there's no real overhead to this solution.
Since sessions are not invalidated manually (eg, by iterating over every session), there is no overhead added to the change password workflow, either.
Keeping SessionAuth in core also allows plugin authentication to be more costly if required. Once a session is established, plugin based authentication won't happen again.
Some ideas for making Piwik even more secure (not necessarily related to this PR):
Common::generateUniqId()'s use of md5 & uniqid w/
random_bytes()(there's are polyfills for PHP 5.*, eg, https://github.com/symfony/polyfill). Would prevent attackers from being able to guess what new token auths would be.
Not sure if every test will pass, but this should be good to review.
FYI, going to add another commit, had a new idea.
Nevermind, not as good an idea as I thought.
Actually, nevermind to my nevermind, it might be a good idea...
Noticed an issue, putting back into WIP.
Closing in favor of https://github.com/piwik/piwik/pull/12208 which uses branch in piwik/piwik