From 6e7ff522251832491855fe2f2c1a750b167bf898 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 4 Jul 2025 12:08:03 +0000 Subject: [PATCH 1/2] Initial plan From 6bd94c6d902c39b63f1cb4e9f3e088b84ad7e3b7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 4 Jul 2025 12:18:19 +0000 Subject: [PATCH 2/2] Complete OAuth template implementation for PHP Co-authored-by: somashaker23 <113500400+somashaker23@users.noreply.github.com> --- .env.example | 18 ++++ .gitignore | 26 +++++ README.md | 147 +++++++++++++++++++++++++- composer.json | 16 +++ src/config/oauth.php | 28 +++++ src/public/oauth-demo.html | 187 ++++++++++++++++++++++++++++++++++ src/public/oauth/callback.php | 90 ++++++++++++++++ src/public/oauth/login.php | 55 ++++++++++ src/public/oauth/logout.php | 22 ++++ src/public/oauth/user.php | 34 +++++++ 10 files changed, 621 insertions(+), 2 deletions(-) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 src/config/oauth.php create mode 100644 src/public/oauth-demo.html create mode 100644 src/public/oauth/callback.php create mode 100644 src/public/oauth/login.php create mode 100644 src/public/oauth/logout.php create mode 100644 src/public/oauth/user.php diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d05e915 --- /dev/null +++ b/.env.example @@ -0,0 +1,18 @@ +# OAuth Configuration Environment Variables +# Copy this file to .env and update with your actual values + +# Google OAuth Configuration +GOOGLE_CLIENT_ID=your_google_client_id_here +GOOGLE_CLIENT_SECRET=your_google_client_secret_here +GOOGLE_REDIRECT_URI=http://localhost:8080/oauth/callback.php + +# Application Configuration +APP_URL=http://localhost:8080 +APP_NAME="PHP API Seed with OAuth" + +# Database Configuration (if needed) +DB_HOST=localhost +DB_PORT=3306 +DB_NAME=appdb +DB_USER=root +DB_PASSWORD=rootpassword \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7034387 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Dependencies +/vendor/ +composer.lock + +# Environment variables +.env + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db + +# Log files +*.log + +# Cache files +cache/ +tmp/ + +# Docker +docker-compose.override.yml \ No newline at end of file diff --git a/README.md b/README.md index 057fed8..386dd25 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ -# PHP Seed Project in Docker +# PHP Seed Project with OAuth Template -This is a simple PHP project designed to run in a **Docker** container. It uses **PHP-FPM**, **MySQL** (with **phpMyAdmin** for database management), and Docker Compose to set up the environment. +This is a simple PHP project designed to run in a **Docker** container with **Google OAuth integration**. It uses **PHP-FPM**, **MySQL** (with **phpMyAdmin** for database management), and Docker Compose to set up the environment. + +## Features + +- ✅ Simple PHP API structure +- 🔐 Google OAuth integration template +- 🐳 Docker containerization +- 🗄️ MySQL database with phpMyAdmin +- 📝 Ready-to-use OAuth endpoints +- 🎨 Demo frontend for testing OAuth flow ## Prerequisites @@ -8,6 +17,7 @@ Before starting, make sure you have the following installed: - **Docker**: [Install Docker](https://docs.docker.com/get-docker/) - **Docker Compose**: [Install Docker Compose](https://docs.docker.com/compose/install/) +- **Composer**: [Install Composer](https://getcomposer.org/download/) ## Getting Started @@ -16,3 +26,136 @@ Before starting, make sure you have the following installed: ```bash git clone git@github.com:somashaker23/php-api-seed.git cd php-api-seed +``` + +### 2. Install Dependencies: + +```bash +composer install +``` + +### 3. Set Up OAuth Configuration: + +#### 3.1 Create Google OAuth Credentials: + +1. Go to [Google Cloud Console](https://console.cloud.google.com/) +2. Create a new project or select an existing one +3. Enable the **Google+ API** and **Google OAuth2 API** +4. Go to **Credentials** → **Create Credentials** → **OAuth 2.0 Client ID** +5. Configure the consent screen if prompted +6. Set application type to **Web application** +7. Add authorized redirect URI: `http://localhost:8080/oauth/callback.php` +8. Copy the **Client ID** and **Client Secret** + +#### 3.2 Update Configuration: + +Edit `src/config/oauth.php` and replace: +- `YOUR_GOOGLE_CLIENT_ID` with your actual Client ID +- `YOUR_GOOGLE_CLIENT_SECRET` with your actual Client Secret + +```php +'client_id' => 'your-actual-client-id-here', +'client_secret' => 'your-actual-client-secret-here', +``` + +### 4. Start the Application: + +#### Using Docker: + +```bash +docker compose up --build +``` + +#### Using PHP built-in server: + +```bash +php -S localhost:8080 -t src/public +``` + +## Usage + +### OAuth Demo + +Visit `http://localhost:8080/oauth-demo.html` to see the OAuth integration in action: + +- **Demo Page**: `http://localhost:8080/oauth-demo.html` +- **Login**: `http://localhost:8080/oauth/login.php` +- **User Profile**: `http://localhost:8080/oauth/user.php` +- **Logout**: `http://localhost:8080/oauth/logout.php` + +### API Endpoints + +- **Main API**: `http://localhost:8080/` - Returns basic API response +- **OAuth Login**: `http://localhost:8080/oauth/login.php` - Redirects to Google OAuth +- **OAuth Callback**: `http://localhost:8080/oauth/callback.php` - Handles OAuth callback +- **User Profile**: `http://localhost:8080/oauth/user.php` - Returns authenticated user info +- **Logout**: `http://localhost:8080/oauth/logout.php` - Clears session + +### Example OAuth Flow + +1. **Login**: Visit `/oauth/login.php` +2. **Authenticate**: User logs in with Google +3. **Callback**: Google redirects to `/oauth/callback.php` +4. **Profile**: Access user data via `/oauth/user.php` +5. **Logout**: Clear session with `/oauth/logout.php` + +## Development + +### File Structure + +``` +src/ +├── config/ +│ └── oauth.php # OAuth configuration +├── oauth/ +│ ├── login.php # OAuth login endpoint +│ ├── callback.php # OAuth callback handler +│ ├── user.php # User profile endpoint +│ └── logout.php # Logout endpoint +└── public/ + ├── index.php # Main API endpoint + └── oauth-demo.html # Demo frontend +``` + +### Adding OAuth to Your Project + +1. **Include the OAuth files** in your project +2. **Update configuration** in `src/config/oauth.php` +3. **Start OAuth flow** by redirecting to `/oauth/login.php` +4. **Handle user data** from the session after authentication + +### Session Management + +User data is stored in PHP sessions after successful authentication: + +```php +$_SESSION['user'] = [ + 'id' => $userInfo->getId(), + 'email' => $userInfo->getEmail(), + 'name' => $userInfo->getName(), + 'picture' => $userInfo->getPicture(), + 'verified_email' => $userInfo->getVerifiedEmail() +]; +``` + +## Docker Services + +- **PHP Application**: `http://localhost:8080` +- **phpMyAdmin**: `http://localhost:3000` +- **MySQL**: `localhost:3306` + +## Troubleshooting + +### Common Issues + +1. **"OAuth not configured"** - Update `src/config/oauth.php` with your Google OAuth credentials +2. **"Invalid redirect URI"** - Make sure the redirect URI in Google Console matches exactly +3. **"Access denied"** - Check if the Google+ API is enabled in your Google Cloud project +4. **Composer dependencies missing** - Run `composer install` + +### Security Notes + +- Never commit real OAuth credentials to version control +- Use environment variables for production deployments +- Always validate the `state` parameter in OAuth callbacks +- Implement proper session management for production use diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..40a4369 --- /dev/null +++ b/composer.json @@ -0,0 +1,16 @@ +{ + "name": "somashaker23/php-api-seed", + "description": "PHP API Seed Project with OAuth Template", + "type": "project", + "require": { + "php": "^8.0", + "google/apiclient": "^2.15" + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "minimum-stability": "stable", + "prefer-stable": true +} \ No newline at end of file diff --git a/src/config/oauth.php b/src/config/oauth.php new file mode 100644 index 0000000..5c45fba --- /dev/null +++ b/src/config/oauth.php @@ -0,0 +1,28 @@ + [ + // Get these from Google Cloud Console: https://console.cloud.google.com/ + 'client_id' => 'YOUR_GOOGLE_CLIENT_ID', + 'client_secret' => 'YOUR_GOOGLE_CLIENT_SECRET', + 'redirect_uri' => 'http://localhost:8080/oauth/callback.php', + + // OAuth scopes - what permissions to request + 'scopes' => [ + 'openid', + 'email', + 'profile' + ], + + // OAuth endpoints + 'authorization_base_url' => 'https://accounts.google.com/o/oauth2/v2/auth', + 'token_url' => 'https://oauth2.googleapis.com/token', + 'userinfo_url' => 'https://www.googleapis.com/oauth2/v2/userinfo' + ] +]; \ No newline at end of file diff --git a/src/public/oauth-demo.html b/src/public/oauth-demo.html new file mode 100644 index 0000000..abf16c9 --- /dev/null +++ b/src/public/oauth-demo.html @@ -0,0 +1,187 @@ + + + + + + OAuth Demo - PHP API Seed + + + +
+

🔐 OAuth Demo - PHP API Seed

+

This demo shows Google OAuth integration for PHP developers.

+ +
+ +
+

Step 1: Login with Google

+

Click the button below to authenticate with Google OAuth:

+ 🔐 Login with Google +
+ + + +
+

🔧 API Endpoints

+

Test the OAuth API endpoints:

+ + + +
+
+ +
+

⚙️ Setup Instructions

+
    +
  1. Go to Google Cloud Console
  2. +
  3. Create a new project or select an existing one
  4. +
  5. Enable the Google+ API
  6. +
  7. Create OAuth 2.0 credentials
  8. +
  9. Add http://localhost:8080/oauth/callback.php as authorized redirect URI
  10. +
  11. Update src/config/oauth.php with your credentials
  12. +
  13. Run composer install to install dependencies
  14. +
+
+
+ + + + \ No newline at end of file diff --git a/src/public/oauth/callback.php b/src/public/oauth/callback.php new file mode 100644 index 0000000..49a397c --- /dev/null +++ b/src/public/oauth/callback.php @@ -0,0 +1,90 @@ + 'Missing required parameters', + 'message' => 'Authorization code or state parameter is missing' + ]); + exit; +} + +// Verify state parameter to prevent CSRF attacks +if (!isset($_SESSION['oauth_state']) || $_SESSION['oauth_state'] !== $_GET['state']) { + http_response_code(400); + echo json_encode([ + 'error' => 'Invalid state parameter', + 'message' => 'Possible CSRF attack detected' + ]); + exit; +} + +try { + // Initialize Google Client + $client = new Google_Client(); + $client->setClientId($googleConfig['client_id']); + $client->setClientSecret($googleConfig['client_secret']); + $client->setRedirectUri($googleConfig['redirect_uri']); + + // Exchange authorization code for access token + $token = $client->fetchAccessTokenWithAuthCode($_GET['code']); + + if (isset($token['error'])) { + throw new Exception($token['error_description'] ?? 'Unknown error'); + } + + // Set access token + $client->setAccessToken($token); + + // Get user information + $oauth2 = new Google_Service_Oauth2($client); + $userInfo = $oauth2->userinfo->get(); + + // Store user information in session + $_SESSION['user'] = [ + 'id' => $userInfo->getId(), + 'email' => $userInfo->getEmail(), + 'name' => $userInfo->getName(), + 'picture' => $userInfo->getPicture(), + 'verified_email' => $userInfo->getVerifiedEmail() + ]; + + // Store tokens for API access + $_SESSION['access_token'] = $token; + + // Clear the state + unset($_SESSION['oauth_state']); + + // Return success response + echo json_encode([ + 'status' => 'success', + 'message' => 'OAuth authentication successful', + 'user' => $_SESSION['user'], + 'redirect_url' => '/oauth/user.php' + ]); + +} catch (Exception $e) { + http_response_code(500); + echo json_encode([ + 'error' => 'OAuth callback failed', + 'message' => $e->getMessage() + ]); +} \ No newline at end of file diff --git a/src/public/oauth/login.php b/src/public/oauth/login.php new file mode 100644 index 0000000..b1e870a --- /dev/null +++ b/src/public/oauth/login.php @@ -0,0 +1,55 @@ + 'OAuth not configured', + 'message' => 'Please update src/config/oauth.php with your Google OAuth credentials' + ]); + exit; +} + +try { + // Initialize Google Client + $client = new Google_Client(); + $client->setClientId($googleConfig['client_id']); + $client->setClientSecret($googleConfig['client_secret']); + $client->setRedirectUri($googleConfig['redirect_uri']); + $client->setScopes($googleConfig['scopes']); + + // Generate and store state parameter for security + $state = bin2hex(random_bytes(32)); + $_SESSION['oauth_state'] = $state; + $client->setState($state); + + // Get authorization URL + $authUrl = $client->createAuthUrl(); + + // Redirect to Google OAuth + header("Location: $authUrl"); + exit; + +} catch (Exception $e) { + http_response_code(500); + header('Content-Type: application/json'); + echo json_encode([ + 'error' => 'OAuth initialization failed', + 'message' => $e->getMessage() + ]); +} \ No newline at end of file diff --git a/src/public/oauth/logout.php b/src/public/oauth/logout.php new file mode 100644 index 0000000..2c0cec5 --- /dev/null +++ b/src/public/oauth/logout.php @@ -0,0 +1,22 @@ + 'success', + 'message' => 'User logged out successfully', + 'login_url' => '/oauth/login.php' +]); \ No newline at end of file diff --git a/src/public/oauth/user.php b/src/public/oauth/user.php new file mode 100644 index 0000000..c0053d4 --- /dev/null +++ b/src/public/oauth/user.php @@ -0,0 +1,34 @@ + 'Unauthorized', + 'message' => 'User not authenticated. Please login first.', + 'login_url' => '/oauth/login.php' + ]); + exit; +} + +// Return user profile +echo json_encode([ + 'status' => 'success', + 'message' => 'User profile retrieved successfully', + 'user' => $_SESSION['user'], + 'session_info' => [ + 'authenticated' => true, + 'login_time' => $_SESSION['access_token']['created'] ?? null + ] +]); \ No newline at end of file