User Login
Overview
Section titled โOverviewโUser login is the process of verifying a userโs identity and granting access to the system. The server receives the userโs credentials, looks up the account in the database, verifies the password against the stored hash, and creates a session if the credentials are valid.
The key steps are:
- User submits credentials (email/username + password).
- Server looks up the user in the database.
- Server verifies the password against the stored hash.
- If valid, the server creates a session.
- User is redirected to a protected page.
Login Form Design
Section titled โLogin Form DesignโA practical approach is to use a single โidentifierโ field that accepts either an email address or a username, combined with a password field. This gives users the flexibility to log in with whichever they prefer, without requiring two separate forms.
Password Verification
Section titled โPassword VerificationโWhen verifying passwords, always use password_verify(). Never compare hashes directly.
The wrong approaches:
- Comparing plain text to a hash (
$password === $hash) will never work because they are completely different strings. - Hashing the input and comparing (
password_hash($input) === $hash) will also fail because each call topassword_hash()produces a unique hash due to the random salt.
The correct approach is to use password_verify($plainPassword, $storedHash). This function extracts the salt from the stored hash, applies it to the input password, and performs a constant-time comparison that prevents timing attacks.
Authentication Process
Section titled โAuthentication ProcessโThe authentication logic follows this pattern:
- Try to find the user by email first, then by username.
- If no user is found, return
null(invalid credentials). - Use
password_verify()to compare the submitted password with the stored hash. - If the password matches, return the user data. Otherwise, return
null.
Always return the same generic response for any authentication failure. Do not say โEmail not foundโ (which reveals that the email is not registered) or โWrong passwordโ (which confirms the email exists). Always respond with โInvalid credentialsโ to prevent user enumeration attacks.
Session Data
Section titled โSession DataโAfter a successful login, store the following data in the session:
user_id- the database IDuser_email- the email addressuser_name- the full name for displayuser_role- for authorization checks (admin/customer)is_authenticated- a boolean flag set totrue
Storing this data avoids querying the database on every request and enables quick access to user information for display and authorization. Session data is stored on the server; only the session ID is sent to the browser as a cookie.
Login Flow
Section titled โLogin Flowโโโโโโโโโโโโโโโโโโโโโ User enters โโ email/username โโ + password โโโโโโโโโโโฌโโโโโโโโโ โ โผโโโโโโโโโโโโโโโโโโโโ Validate input โโ (required?) โโโโโโโโโโโฌโโโโโโโโโ โ โโโโโโดโโโโโ โ โ โผ โผ Valid Invalid โ โ โ โโโ> Show error, โ redirect back โผโโโโโโโโโโโโโโโโโโโโ Find user by โโ email/username โโโโโโโโโโโฌโโโโโโโโโ โ โโโโโโดโโโโโ โ โ โผ โผ Found Not Found โ โ โ โโโ> "Invalid credentials" โผ redirect backโโโโโโโโโโโโโโโโโโโโ Verify passwordโโ password_verifyโโโโโโโโโโโฌโโโโโโโโโ โ โโโโโโดโโโโโ โ โ โผ โผ Match No Match โ โ โ โโโ> "Invalid credentials" โ redirect back โผโโโโโโโโโโโโโโโโโโโโ Create session โโ - user_id โโ - user_role โโ - is_auth=true โโโโโโโโโโโฌโโโโโโโโโ โ โผโโโโโโโโโโโโโโโโโโโโ Redirect based โโ on role: โโ Admin > /admin โโ User > /dash โโโโโโโโโโโโโโโโโโโโProtecting Routes with Middleware
Section titled โProtecting Routes with MiddlewareโMiddleware is code that runs before your route handler, acting as a gatekeeper. It intercepts every request and decides whether to allow it through or redirect the user.
User Request > Middleware > Route Handler > Response | Check session | Is authenticated? / \ Yes No | | Continue Redirect to loginAn AuthMiddleware checks whether the session variable is_authenticated is set to true. If it is, the request proceeds to the route handler. If not, the user is redirected to the login page with an error message.
Role-Based Access Control
Section titled โRole-Based Access ControlโAuthorization goes one step further than authentication by restricting access based on user roles.
Two levels of middleware provide this:
AuthMiddlewarechecks if the user is logged in (any role).AdminAuthMiddlewarechecks if the user is logged in and has the admin role.
The AdminAuthMiddleware logic works as follows: if the user is not authenticated, redirect to login. If the user is authenticated but is not an admin, redirect to the user dashboard with an โAccess deniedโ message. If the user is authenticated and is an admin, grant access.
Access Control Matrix
Section titled โAccess Control Matrixโ| Route | Not Logged In | Customer | Admin |
|---|---|---|---|
/login | Allow | Allow | Allow |
/register | Allow | Allow | Allow |
/dashboard | Redirect to login | Allow | Allow |
/admin/dashboard | Redirect to login | Denied | Allow |
/admin/users | Redirect to login | Denied | Allow |
Public routes have no middleware. User routes use AuthMiddleware. Admin routes use AdminAuthMiddleware, which also checks authentication.
Security Considerations
Section titled โSecurity ConsiderationsโSeveral security practices are built into this login process:
- Use prepared statements for all database queries to prevent SQL injection.
- Return consistent โInvalid credentialsโ messages so attackers cannot determine whether a specific email or username exists.
- Configure session cookies with
httponly(prevents JavaScript access),secure(HTTPS only),samesite(CSRF protection), and regenerate the session ID periodically. - Consider rate limiting login attempts per IP or user to mitigate brute-force attacks.