Current focus: Google OAuth 2.0 / OpenID Connect prototype
Primary integration target: Nadine Resto-POS customer / landing-page authentication
Long-term goal: A reusable, framework-free PHP + MySQL authentication template that can be integrated into other projects and eventually released as open source.
This document covers the current authentication system, repository structure, database design, local authentication flow, security practices, and the planned Google authentication integration.
- Overview
- Project Goals
- Repository Structure
- Current Authentication
- Database Schema
- Configuration
- Local Auth Flow
- Core Functions
- Pages & Routes
- Session Management
- Google OAuth / OpenID Connect
- Google OAuth Prototype
- Google OAuth Flow
- Google Account Mapping
- Resto-POS Integration
- Reusable OAuth Architecture
- Development Roadmap
- Security Practices
- Common Errors & Fixes
- FAQ
- References
Simple-Auth-Template is a plain PHP + MySQL authentication starter project.
The current implementation provides a basic local authentication foundation:
- Registration
- Login
- Password hashing
- PHP sessions
- Protected pages
- Logout
- Basic project configuration
The project intentionally does not use a PHP framework. The goal is to keep the code readable and understandable for developers who know basic PHP, HTML, CSS, and MySQL.
The next major feature is Google authentication using Google's OAuth 2.0 / OpenID Connect capabilities.
The Google integration is being designed as a reusable authentication feature rather than a feature that only belongs to one application.
- Keep the existing local authentication working.
- Build a working Google authentication prototype.
- Authenticate a Google account and create a local PHP session.
- Store the Google identity against a local user/customer account.
- Integrate the authentication system into the Resto-POS landing page.
- Keep customer authentication separate from staff/admin authentication.
- Improve error handling and security.
- Make Google OAuth configuration reusable across projects.
- Separate authentication logic from application-specific code.
- Support additional OAuth providers where practical.
- Provide clear setup and integration documentation.
- Publish the reusable authentication template as an open-source project.
The current repository is intentionally small and is still evolving.
Simple-Auth-Template/
│
├── Documentation.md # Project and authentication documentation
├── readme.md # Short project overview
├── main.php # Main project/demo page
│
├── includes/
│ ├── auth.php # Authentication logic
│ ├── config.php # Application configuration
│ └── db.php # Database connection
│
├── public/
│ ├── login.php # Login page
│ ├── register.php # Registration page
│ ├── logout.php # Logout endpoint
│ └── assets/
│ └── css/
│ ├── auth.css
│ └── style.css
│
└── src/
├── footer.php # Shared footer
├── header.php # Shared header
└── page2.php # Additional demo page
The structure may change as the OAuth module becomes more reusable. Do not treat the future architecture described later in this document as the current repository structure.
The current system uses traditional application-managed authentication.
User
↓
Login / Register
↓
PHP
↓
MySQL
↓
PHP Session
↓
Protected Page
Passwords are handled by PHP password hashing functions rather than being stored as plain text.
Google authentication will be added alongside this system instead of immediately replacing it.
The current authentication model uses a local users table.
Example schema:
CREATE DATABASE IF NOT EXISTS simple_auth;
USE simple_auth;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);| Column | Type | Description |
|---|---|---|
id |
INT, PK, AUTO_INCREMENT | Local application user ID |
username |
VARCHAR(100) | User's display name |
email |
VARCHAR(150), UNIQUE | Local account email |
password |
VARCHAR(255) | Password hash for local authentication |
created_at |
TIMESTAMP | Account creation timestamp |
The Google integration should not use the Google account identifier as the application's primary user ID.
A future schema can separate provider information from the local user record:
CREATE TABLE user_oauth_accounts (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
provider VARCHAR(50) NOT NULL,
provider_user_id VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY unique_provider_user (
provider,
provider_user_id
),
FOREIGN KEY (user_id)
REFERENCES users(id)
ON DELETE CASCADE
);This design allows one local user to potentially have multiple authentication providers later.
Example:
users
│
├── local password
│
└── user_oauth_accounts
├── google
├── github (future)
└── other (future)
For the Resto-POS integration, the same concept can be applied to a dedicated customers table so customer accounts remain separate from staff/admin accounts.
The current database/application configuration is stored in:
includes/config.php
Typical configuration values include:
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'simple_auth');
define('BASE_URL', 'http://localhost/Simple-Auth-Template/public');Google OAuth credentials should not be committed to a public repository.
A future configuration can use environment variables or an ignored local configuration file:
GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET
GOOGLE_REDIRECT_URI
Recommended repository pattern:
config/google.example.php # Safe example with empty values
config/google.php # Local secrets; ignored by Git
Never commit a real Google client secret.
User fills registration form
↓
Server receives POST data
↓
Validate input
↓
Check whether email already exists
↓
password_hash()
↓
Insert user into MySQL
↓
Redirect to login
User enters email + password
↓
Server receives POST data
↓
Find local user
↓
password_verify()
↓
Create PHP session
↓
Redirect to protected page
User requests protected page
↓
auth_guard()
↓
Check PHP session
↓
Authenticated?
┌────┴────┐
YES NO
↓ ↓
Page loads Redirect to login
User clicks logout
↓
logout.php
↓
session_unset()
↓
session_destroy()
↓
Redirect to login
The authentication layer is centered around functions such as:
Creates a local user account and returns a success value or an error.
Validates the user's password and creates the authenticated PHP session.
Protects pages that require authentication.
Returns whether the current session contains an authenticated local user.
Clears the current authentication session.
Function names and implementation may evolve as the reusable authentication module is refactored.
Current public authentication pages include:
| File | Purpose |
|---|---|
public/login.php |
Local login form |
public/register.php |
Local registration form |
public/logout.php |
Logout endpoint |
The exact URL depends on the configured local web root.
Example:
http://localhost/Simple-Auth-Template/public/login.php
Future Google authentication endpoints are expected to live in a dedicated authentication area, for example:
/auth/google/login.php
/auth/google/callback.php
The exact path is not finalized during the prototype stage.
The local authentication system uses PHP native sessions.
Example local session values:
$_SESSION['user_id'];
$_SESSION['username'];For the future Resto-POS customer authentication flow, customer sessions should remain separate from staff/admin sessions.
Example target design:
// Customer
$_SESSION['customer_id'];
$_SESSION['customer_authenticated'];
// Staff/Admin
$_SESSION['user_id'];
$_SESSION['role'];This separation is important because a customer authenticated through Google must not automatically receive staff or admin privileges.
The goal is to allow users to authenticate through their Google account instead of creating another password for the application.
The intended flow is:
Customer
↓
Landing Page
↓
Continue with Google
↓
Google authentication
↓
Google identity
↓
Local customer account
↓
PHP session
↓
Ordering system
OAuth 2.0 is primarily an authorization protocol. OpenID Connect (OIDC) adds an identity layer on top of OAuth 2.0.
For this project, the requirement is authentication — identifying who the Google user is — so the implementation should use Google's identity capabilities rather than treating an access token as a user ID.
Google's current Sign in with Google documentation identifies the sub claim as the unique Google Account identifier and requires server-side verification of the returned ID token. See the official documentation:
https://developers.google.com/identity/gsi/web/reference/html-reference
The first milestone is intentionally small.
Prove that one Google account can authenticate successfully and create a local PHP session.
Do not build the complete reusable framework before this works.
[ ] Create/configure Google Cloud project
[ ] Configure Google OAuth credentials
[ ] Configure authorized redirect URI
[ ] Add Google login button/link
[ ] Start authentication flow
[ ] Receive Google's response
[ ] Validate the response
[ ] Obtain Google identity
[ ] Create local PHP session
[ ] Display authenticated user
[ ] Logout
The prototype does not need to solve every future use case.
The target server-side authorization flow is:
1. User clicks "Continue with Google"
↓
2. Application generates a random state value
↓
3. State is stored in the PHP session
↓
4. Browser is redirected to Google
↓
5. User selects/authenticates a Google account
↓
6. Google returns an authorization response
↓
7. Application validates state
↓
8. Application exchanges the authorization code / processes the identity response
↓
9. Application validates the Google identity token
↓
10. Application finds or creates the local user/customer
↓
11. Application creates its own PHP session
↓
12. User is redirected to the application
Google's current identity documentation also supports the Sign in with Google HTML/JavaScript APIs, which can return an ID token directly to a server login endpoint. The exact Google flow should be selected based on the prototype implementation and desired UX.
Official reference:
https://developers.google.com/identity/gsi/web/reference/js-reference
The OAuth state value is a security mechanism used to associate the response with the authentication request initiated by the application.
Example:
$state = bin2hex(random_bytes(32));
$_SESSION['oauth_state'] = $state;When the response returns, the application should verify the value before continuing.
Conceptually:
if (!isset($_GET['state'])) {
exit('Missing OAuth state.');
}
if (!isset($_SESSION['oauth_state'])) {
exit('Missing session state.');
}
if (!hash_equals($_SESSION['oauth_state'], $_GET['state'])) {
exit('Invalid OAuth state.');
}
unset($_SESSION['oauth_state']);The exact callback parameters depend on the selected Google authentication flow.
A Google ID token is a signed JWT containing identity claims.
Important claims include:
iss Issuer
sub Stable Google account identifier
aud Audience / client ID
email User email
name User name, when provided
picture Profile image, when provided
exp Token expiration time
The sub value should be treated as the provider-specific Google user ID.
Example:
Google Account
↓
Google `sub`
↓
user_oauth_accounts.provider_user_id
↓
local user_id / customer_id
↓
PHP session
Do not use the Google access token as the local user ID.
Google's documentation states that the ID token must be verified before trusting its claims and that exp is for token validation, not for determining whether the application's local session has ended.
These tokens have different purposes.
Used to communicate authenticated identity information to the application.
Who is the user?
Used to authorize calls to Google APIs on behalf of the user.
What Google API data/actions did the user authorize?
For the initial login prototype, the application should request only the identity information it actually needs.
Do not add Google API permissions such as Drive, Calendar, YouTube, etc. unless a real feature requires them.
For a basic identity/login implementation, the target identity scopes are:
openid
email
profile
Only request additional scopes when the application genuinely needs access to another Google API.
This keeps the authentication flow simpler and reduces unnecessary permissions.
A web application OAuth client requires configuration such as:
Client ID
Client Secret
Authorized redirect URI
Example development redirect URI:
http://localhost/Simple-Auth-Template/auth/google/callback.php
Example Resto-POS development URI:
http://localhost/Resto-POS/auth/google/callback.php
Production should use the actual HTTPS domain and a registered redirect URI.
Redirect URIs must match the Google configuration exactly.
For production deployments, Google requires secure redirect URIs and JavaScript origins. See:
https://developers.google.com/identity/protocols/oauth2/production-readiness/policy-compliance
The application should maintain its own user/customer record.
The preferred mapping is:
Google
│
│ provider = google
│ provider_user_id = sub
▼
OAuth account table
│
│ local user_id / customer_id
▼
Application account
│
▼
PHP session
Google identity received
↓
Find provider + provider_user_id
↓
Found
↓
Load local account
↓
Create session
Google identity received
↓
Provider account not found
↓
Check local email/account rules
↓
Create or link local account
↓
Create OAuth relationship
↓
Create session
Account-linking rules must be designed carefully before production. Automatically merging accounts solely because an email address matches should only be done when the application's identity rules support it safely.
The first real integration target is the Resto-POS customer landing page.
The authentication systems should remain logically separate:
Landing Page
↓
Google Login / Local Customer Login
↓
customer_id
↓
Menu
↓
Cart
↓
Checkout
↓
Order
Existing Staff/Admin Login
↓
Role
↓
POS / Admin Dashboard
Customer authentication ≠ Staff/Admin authorization
A Google-authenticated customer must not receive admin or staff permissions simply because the customer authenticated successfully.
This matches the larger Resto-POS architecture direction where customer, staff, and administrator functions are protected independently.
The long-term goal is to make the Google implementation reusable instead of writing a separate Google login implementation for every project.
The target architecture is approximately:
Simple-Auth-Template
│
├── Local Authentication
│
├── OAuth Layer
│ ├── Google
│ ├── GitHub (future)
│ └── Other providers (future)
│
├── User / Customer Mapping
│
└── Session Management
Application-specific code should communicate with the reusable authentication layer rather than directly implementing Google's protocol everywhere.
A future API could expose functions similar to:
google_authorization_url();
google_handle_callback();
google_get_identity();
find_or_create_oauth_user();Or, if the project remains procedural:
google_get_authorization_url();
google_handle_callback();
google_get_user();
google_find_or_create_user();The exact API is intentionally not finalized during the prototype stage.
Different projects should eventually provide only their own configuration.
Example:
$googleConfig = [
'client_id' => GOOGLE_CLIENT_ID,
'client_secret' => GOOGLE_CLIENT_SECRET,
'redirect_uri' => GOOGLE_REDIRECT_URI,
];The OAuth logic should not need to know whether it is being used by:
- Resto-POS
- A portfolio
- A blog
- An e-commerce project
- A school project
- Another PHP application
Only the configuration and application-specific user mapping should change.
The recommended order is:
Prototype
↓
MVP
↓
Resto-POS Integration
↓
Reusable Authentication Module
↓
Open Source Release
Priority: CURRENT
Goal: prove that Google authentication works.
[ ] Google Cloud configuration
[ ] OAuth credentials
[ ] Login UI
[ ] Google authentication flow
[ ] Callback / response handling
[ ] State / security validation
[ ] Identity verification
[ ] PHP session
[ ] Logout
One Google account can:
Click Login
↓
Authenticate with Google
↓
Return to the application
↓
Be recognized by PHP
↓
Receive a local authenticated session
↓
Access a protected page
↓
Logout
Goal: connect Google authentication to the local database.
[ ] OAuth account table
[ ] Local user/customer mapping
[ ] Existing account detection
[ ] New account creation
[ ] Safe account-linking rules
[ ] Customer session
[ ] Error handling
[ ] Secure configuration
[ ] Session ID regeneration after authentication
Result:
Google Authentication
↓
Local MySQL Account
↓
Application Session
Goal: connect customer authentication to the restaurant landing page and ordering flow.
Landing Page
↓
Customer Login
↓
Google / Local Auth
↓
Customer Session
↓
Menu
↓
Cart
↓
Checkout
↓
Order
Staff/admin authentication remains separate.
Goal: make the authentication system portable to other PHP projects.
[ ] Separate OAuth logic
[ ] Configuration system
[ ] Provider abstraction
[ ] Reusable user mapping
[ ] Better error handling
[ ] Security hardening
[ ] Example integration
[ ] Installation guide
Goal: make the project usable by other developers.
[ ] Clean README
[ ] Full Documentation.md
[ ] Installation guide
[ ] Google Cloud setup guide
[ ] Database schema
[ ] Example configuration
[ ] Security guide
[ ] Contributing guide
[ ] License
[ ] Example project
[ ] Remove all secrets/test credentials
The current project is an educational/reusable starter and should be hardened before production use.
| Practice | Status / Direction |
|---|---|
| Password hashing | Use password_hash() |
| Password verification | Use password_verify() |
| PHP sessions | Used for application authentication |
| Protected routes | Use authentication guards |
| OAuth state | Required for OAuth authorization flows |
| Google ID token validation | Required before trusting identity claims |
| HTTPS | Required for production |
| Prepared statements | Recommended for all database queries |
| CSRF protection | Required before production |
| Rate limiting | Recommended for login endpoints |
| Secret management | Never commit client secrets |
[ ] Validate state
[ ] Use cryptographically random state values
[ ] Validate ID token signature / claims using an appropriate library or Google's recommended verification method
[ ] Validate issuer
[ ] Validate audience/client ID
[ ] Validate expiration
[ ] Protect client secret
[ ] Use exact redirect URIs
[ ] Use HTTPS in production
[ ] Do not store unnecessary Google tokens
[ ] Request only required scopes
[ ] Regenerate session ID after successful login
[ ] Use secure cookies in production
[ ] Use HttpOnly cookies
[ ] Use SameSite cookie protection
[ ] Destroy sessions on logout
[ ] Keep customer and staff/admin sessions logically separate
[ ] Use prepared statements
[ ] Validate input
[ ] Use unique provider identifiers
[ ] Avoid storing unnecessary OAuth tokens
[ ] Never store Google passwords
| Error | Likely Cause | Fix |
|---|---|---|
Connection failed |
Wrong MySQL credentials | Check includes/config.php |
| Blank page after login | Session not started | Start the PHP session before accessing $_SESSION |
| Redirect loop | Auth guard/session mismatch | Check session initialization and guard logic |
Call to undefined function |
Missing include | Verify require_once paths |
| Password always wrong | Incorrect hashing/verification | Hash during registration and verify during login |
redirect_uri_mismatch |
Callback URI does not exactly match Google configuration | Check Google OAuth client settings and application URI |
| Invalid OAuth state | State was missing, changed, or session state was lost | Generate/store/validate state correctly |
| Invalid ID token | Token failed validation | Validate signature and required claims before creating a session |
| Google login works but local account is missing | OAuth identity was not mapped to local DB | Implement provider/account mapping |
The project currently uses plain HTML and CSS.
The authentication UI can be styled independently from the authentication logic.
This is important for reuse: a future project should be able to use the same authentication backend while providing its own UI.
A protected page should include the authentication layer and call the appropriate guard before displaying private content.
Conceptually:
<?php
require_once '../includes/auth.php';
auth_guard();
?>
<h1>Protected Page</h1>The exact include path depends on the page location.
The planned provider model is:
Authentication
├── Local
├── Google
├── GitHub
└── Future Providers
Each provider should be responsible for its provider-specific authentication flow while the application continues using its own local user/customer ID.
Yes, but the current project is intentionally framework-free. A Laravel implementation would likely use Laravel's authentication and OAuth ecosystem instead of copying the procedural implementation directly.
No. The current Google work is planned as a prototype first. Security validation, account linking, secret management, HTTPS, error handling, and production configuration must be completed before production deployment.
Not necessarily. Basic Google authentication focuses on obtaining and verifying the user's identity. An access token is primarily needed when the application wants to call an authorized Google API on the user's behalf.
No. Keep a local application user/customer ID and map the Google provider ID (sub) to that local account.
Yes. That is one of the long-term goals. The provider-specific implementation should be separated from the application's local account/session logic.
Because authentication answers who the user is, while authorization determines what the user is allowed to do. A customer signing in with Google should not automatically gain staff/admin privileges.
Because the project is still validating the Google authentication flow. The recommended approach is to make the smallest working prototype first, then refactor the working implementation into reusable components.
-
Google OAuth 2.0 documentation: https://developers.google.com/identity/protocols/oauth2
-
Google Sign in with Google HTML API reference: https://developers.google.com/identity/gsi/web/reference/html-reference
-
Google Sign in with Google JavaScript API reference: https://developers.google.com/identity/gsi/web/reference/js-reference
-
Google OAuth production-readiness and policy guidance: https://developers.google.com/identity/protocols/oauth2/production-readiness/policy-compliance
- YouTube reference used during planning: https://youtu.be/z4tU69VlHFQ
The immediate goal is Phase 1 — Prototype.
Do not implement the entire reusable authentication architecture yet.
The next development target is:
Simple-Auth-Template
↓
Google Login
↓
Google Identity
↓
PHP Session
↓
Protected Page
Once that flow works reliably, the project can move to MySQL account mapping, Resto-POS integration, reusable abstractions, and finally an open-source release.
Documentation maintained as the Simple-Auth-Template project evolves.