PHP authentication

From Rixort Wiki
Jump to navigation Jump to search

Login

  • Store hash of password in database
  • Check password by fetching row based on username, then use password_verify (which is safe against timing attacks)
  • After a successful verification, call password_needs_rehash to see if the hash needs to be updated, e.g. if you have increased the hash cost

Session cookies

Whether you use the built-in functionality or setcookie, you need to ensure that:

  • Sessions are only sent in cookies, not URL parameters (session.use_cookies = 1, session.use_only_cookies = 1)
  • Only send session cookies for HTTP requests (session.cookie_httponly = 1 or $options['httponly'] = true)
  • Only send cookies for secure requests (session.cookie_secure = 1 or $options['secure'] = true)
  • Cookies are restricted to the domain (session.cookie_domain = "example.org" or $options['domain'] = 'example.org')
  • Use strict mode (session.use_strict_mode = 1)
  • Set the SameSite attribute appropriately, probably to 'Strict' unless you really need another type (session.cookie_samesite = "Strict" or $options['samesite'] = 'Strict')
  • Session lifetime is set to zero seconds, which in most browsers will mean the cookie is deleted when the browser is closed (session.cookie_lifetime = 0 or $options['expires'] = 0)

Note you cannot rely on the session cookie being deleted when the browser is closed, as this behaviour is not controlled by PHP and many users leave their browsers open all the time anyway. However, you can delete the session identifier from the server (e.g. using garbage collection), which will effectively render the cookie useless because there will be no matching record.

Things you might want to consider:

  • Regenerate the session ID regularly - this might be important for applications where users stay logged in for a long time, e.g. the entire working day
  • Regenerate the session ID when privileges are changed
  • Restricting cookies to the subdomain, e.g. if you use www.example.org then cookies should be set for that domain and not example.org
  • If you are on a shared server, setting session.save_path to a restricted directory (i.e. not world-readable, which it often is by default) will help prevent other users from viewing the session IDs. Note that all that is required to get the session IDs is the ability to list files in the directory, because the filenames usually contain the session ID - which may be sufficient to hijack sessions. This is redundant if sessions are saved in Redis, a database etc.

Do not mess around with options such as session.hash_function (removed as of 7.1 anyway). Your PHP distribution vendor should have set these to sensible values - if not you have bigger things to worry about.

Remember that a session ID is a shared token between the client and the server. Any client with the token can convince the server that it is authorised to access the data held alongside the token, and therefore the token should be viewed as a secret and handled as such (do not output it to the page, do not include in URLs, always send over HTTPS etc.)

References