# Authentication foundation

The database and PHP configuration support password login using a username, email address, or phone number.

## Normalization order

1. Trim the submitted `login` value.
2. If `filter_var($login, FILTER_VALIDATE_EMAIL)` succeeds, lowercase it and query `email`.
3. If the value matches E.164 (`+` followed by 8–15 digits), query `phone_e164`.
4. Otherwise lowercase it and query `username`.

Usernames must not contain `@` and should not be entirely numeric. This removes ambiguity between login types.

## Password verification

- Generate hashes with `password_hash($password, PASSWORD_DEFAULT)`.
- Verify with `password_verify($password, $storedHash)`.
- Rehash after login when `password_needs_rehash()` returns true.
- Never hash passwords with MD5, SHA-1, or a plain SQL function.
- Always return the same generic error for an unknown user and a wrong password.

## Required protections

- Prepared SQL statements
- CSRF tokens on forms
- Secure, HttpOnly, SameSite session cookies
- Session ID rotation after successful login
- Five-attempt rate limit per identifier and IP
- Hashed session and one-time tokens in the database
- HTTPS-only authentication
- 18+ and legal consent records using `user_consents`

Email and phone are nullable in the schema so the future registration flow can decide which contact method is required. The application configuration requires at least one contact method and reserves all three login methods.
