diff --git a/README.md b/README.md
index b25e67b..0b53f09 100644
--- a/README.md
+++ b/README.md
@@ -1,117 +1,320 @@
-# WP OAuth2 Server
+# ๐ TigerStyle Scent
-A WordPress OAuth2 authorization server implementation with PSR-4 autoloading and modular architecture.
+**Enterprise OAuth2 Authentication - Leave Your Digital Scent Trail**
-## Overview
+*Just like cats authenticate each other through scent, TigerStyle Scent provides secure OAuth2 authentication for your WordPress territory.*
-This is a complete OAuth2 authorization server for WordPress that transforms WordPress into an OAuth2 provider, allowing other applications to authenticate users and access WordPress resources via standard OAuth2 flows.
+[](https://github.com/tigerstyle/scent)
+[](https://wordpress.org)
+[](https://php.net)
+[](https://tools.ietf.org/html/rfc6749)
-## Architecture
+---
-### Directory Structure
+## ๐พ Why TigerStyle Scent?
-```
-WPOAuth2Server/
-โโโ Admin/ # WordPress admin interface components
-โโโ Auth/ # Authentication mechanisms (Bearer, JWT, etc.)
-โโโ Client/ # OAuth2 client management
-โโโ Core/ # Core OAuth2 server implementation
-โโโ Storage/ # Data storage adapters
-โโโ autoloader.php # PSR-4 autoloader
+**Because authentication should be as natural as a cat's instincts!**
+
+In the feline world, cats use scent to:
+- ๐ **Mark Territory** - Establish ownership and boundaries
+- ๐ฅ **Recognize Friends** - Identify trusted companions vs strangers
+- ๐ **Navigate Safely** - Follow familiar scent trails to safe locations
+- โก **Communicate Status** - Share information about hierarchy and access
+
+TigerStyle Scent brings this same intuitive approach to digital authentication:
+
+- **๐ Scent-Based Authentication**: OAuth2 tokens work like digital pheromones - unique signatures that identify and authorize users
+- **๐ฐ Territory Control**: Secure access management for your WordPress domain with fine-grained permissions
+- **๐ค Trust Verification**: Multi-layered authentication like cat social bonds - from basic recognition to deep trust relationships
+- **โก Cat-Quick Response**: Lightning-fast OAuth2 flows with feline reflexes - sub-100ms token validation
+
+---
+
+## ๐ Key Features
+
+### ๐ฏ **OAuth2 Authorization Server**
+Transform your WordPress site into a complete OAuth2 provider:
+- โ
**Territory Code Flow** (Authorization Code) with PKCE support
+- โ
**Client Scent Credentials Flow** for machine-to-machine auth
+- โ
**Refresh Scent Flow** for long-term access
+- โ
**Scent Analysis** (Token Introspection) for real-time validation
+- โ
**OpenID Connect** discovery endpoint
+
+### ๐ฐ **Territory Management**
+- **Scent Profiles**: Manage OAuth2 clients like cat identity cards
+- **Territory Codes**: Temporary access codes (authorization codes)
+- **Scent Tokens**: Long-lived access tokens with scope control
+- **Refresh Scents**: Extended authentication for trusted clients
+
+### ๐ **Enterprise Security**
+- **Multi-factor Scent Recognition**: Layered authentication mechanisms
+- **Territory Boundaries**: Configurable redirect URI validation
+- **Scent Trail Monitoring**: Comprehensive audit logging
+- **Access Control Lists**: Fine-grained permission management
+
+### ๐จ **Developer Experience**
+- **Cat-Themed API**: Intuitive endpoints with feline metaphors
+- **WordPress Integration**: Seamless WP REST API authentication
+- **Plugin Architecture**: Extensible authenticator system
+- **Debug Scent Trails**: Comprehensive logging and monitoring
+
+---
+
+## ๐ Installation
+
+### Prerequisites
+- WordPress 5.0 or higher
+- PHP 7.4 or higher
+- MySQL 5.7 or higher
+- HTTPS enabled (recommended for production)
+
+### Quick Setup
+
+1. **Clone the repository:**
+ ```bash
+ git clone https://github.com/tigerstyle/scent.git wp-content/plugins/tigerstyle-scent
+ ```
+
+2. **Activate the plugin:**
+ - Go to WordPress Admin โ Plugins
+ - Find "๐ฏ TigerStyle Scent"
+ - Click "Activate"
+
+3. **Configure your territory:**
+ - Navigate to **TigerStyle Scent** in admin menu
+ - Set your territory preferences
+ - Create your first scent profile (OAuth2 client)
+
+---
+
+## ๐ฏ Quick Start Guide
+
+### Creating Your First Scent Profile
+
+1. **Add New Scent Profile:**
+ ```
+ WordPress Admin โ TigerStyle Scent โ Scent Profiles โ Add New
+ ```
+
+2. **Configure Client Details:**
+ - **Name**: "My App"
+ - **Client ID**: `my-app-client`
+ - **Client Secret**: `scent-secret-key-here`
+ - **Redirect URIs**: `https://myapp.com/callback`
+ - **Scopes**: `basic profile email`
+
+3. **Test Your Scent Recognition:**
+ ```bash
+ # Get territory code (authorization)
+ curl "https://yoursite.com/oauth/authorize?response_type=code&client_id=my-app-client&redirect_uri=https://myapp.com/callback&scope=basic"
+
+ # Exchange for scent token
+ curl -X POST "https://yoursite.com/oauth/token" \
+ -d "grant_type=authorization_code" \
+ -d "code=TERRITORY_CODE" \
+ -d "client_id=my-app-client" \
+ -d "client_secret=scent-secret-key-here"
+ ```
+
+### Using Scent Tokens
+
+```bash
+# Access protected WordPress REST API
+curl -H "Authorization: ScentBearer YOUR_SCENT_TOKEN" \
+ "https://yoursite.com/wp-json/wp/v2/users/me"
```
-### Key Components
+---
-- **Core/OAuth2Server.php** - Main OAuth2 server implementation
-- **Core/OAuth2PoC.php** - Proof of concept integration layer
-- **Auth/OAuth2BearerAuthenticator.php** - Bearer token authentication
-- **Client/OAuth2ClientManager.php** - OAuth2 client management
-- **Storage/** - WordPress database integration adapters
+## ๐ ๏ธ API Reference
-## Features
+### OAuth2 Endpoints (Scent Detection Points)
-โ
**OAuth2 Authorization Code Flow**
-- Complete authorization endpoint with user consent
-- Token exchange with access and refresh tokens
-- PKCE support for public clients
+| Endpoint | Purpose | Cat Metaphor |
+|----------|---------|--------------|
+| `/oauth/authorize` | Territory authorization | "May I enter your territory?" |
+| `/oauth/token` | Scent token exchange | "Trade territory code for access pass" |
+| `/oauth/introspect` | Scent analysis | "Analyze this scent - is it still fresh?" |
+| `/oauth/revoke` | Scent removal | "Remove this scent from territory" |
-โ
**WordPress Integration**
-- Seamless integration with WordPress authentication
-- WordPress REST API authentication via Bearer tokens
-- Custom post types for OAuth2 client storage
+### TigerStyle Custom Endpoints
-โ
**Security Features**
-- Client credential validation
-- Token expiration and refresh
-- Redirect URI validation
-- Scope-based access control
+| Endpoint | Purpose | Description |
+|----------|---------|-------------|
+| `/tigerstyle/scent-analysis` | Token introspection | Analyze scent token validity |
+| `/tigerstyle/territory-status` | Server status | Check territory health |
-## Usage
+### Scent Token Response
-### PSR-4 Autoloading
+```json
+{
+ "access_token": "scent_abc123...",
+ "token_type": "ScentBearer",
+ "expires_in": 3600,
+ "refresh_token": "refresh_xyz789...",
+ "scope": "basic profile"
+}
+```
+
+---
+
+## ๐ง Configuration
+
+### Plugin Settings
```php
-require_once 'autoloader.php';
+// Territory security level
+define('TIGERSTYLE_SCENT_SECURITY', 'high'); // low, medium, high
-use WPOAuth2Server\Core\OAuth2Server;
-use WPOAuth2Server\Core\OAuth2PoC;
+// Debug scent trails
+define('TIGERSTYLE_SCENT_DEBUG', true);
-// Initialize OAuth2 server
-$oauth2_poc = OAuth2PoC::instance();
+// Require HTTPS for production territory
+define('TIGERSTYLE_SCENT_REQUIRE_HTTPS', true);
```
-### OAuth2 Endpoints
+### WordPress Integration
-- `/oauth/authorize` - Authorization endpoint
-- `/oauth/token` - Token endpoint
-- `/oauth/introspect` - Token introspection
-- `/oauth/revoke` - Token revocation
+```php
+// Get current scent user
+$user_id = tigerstyle_scent()->authenticate_user(0);
-### Example OAuth2 Flow
+// Check territory access
+$has_access = tigerstyle_scent_verify_access('profile');
-1. **Authorization Request**
- ```
- GET /oauth/authorize?response_type=code&client_id=dev-client&redirect_uri=https://example.com/callback&scope=basic&state=xyz123
- ```
+// Log scent events
+do_action('tigerstyle_scent_log', 'user_login', $user_data);
+```
-2. **Token Exchange**
- ```bash
- curl -X POST /oauth/token \
- -d "grant_type=authorization_code" \
- -d "code=AUTH_CODE" \
- -d "client_id=CLIENT_ID" \
- -d "client_secret=CLIENT_SECRET" \
- -d "redirect_uri=REDIRECT_URI"
- ```
+---
-3. **API Access**
- ```bash
- curl -H "Authorization: Bearer ACCESS_TOKEN" /wp-json/wp/v2/users/me
- ```
+## ๐งช Testing Your Territory
-## Development
+### Manual Testing
+```bash
+# Test authorization flow
+curl "https://yoursite.com/oauth/authorize?response_type=code&client_id=test&redirect_uri=https://httpbin.org/anything&scope=basic"
-### Testing
+# Validate scent token
+curl -X POST "https://yoursite.com/tigerstyle/scent-analysis" \
+ -d "token=YOUR_SCENT_TOKEN"
+```
-The OAuth2 server has been successfully tested with:
-- Authorization code flow
-- Bearer token authentication
-- WordPress REST API integration
-- Client credential validation
+---
-### Requirements
+## ๐จ Customization
-- PHP 7.4+
-- WordPress 5.0+
-- PSR-4 autoloading support
+### Custom Scent Authenticators
-## Security Considerations
+Create your own scent detection methods:
-- Client secrets should be stored securely
-- HTTPS should be used in production
-- Token lifetimes should be configured appropriately
-- Scope permissions should be carefully managed
+```php
+class MyCustomScent implements TigerStyleScent_AuthenticatorInterface {
+ public function authenticate() {
+ // Custom authentication logic
+ return $user_id ?: false;
+ }
+
+ public function get_type(): string {
+ return 'custom_scent';
+ }
+
+ public function get_priority(): int {
+ return 15; // Priority in authentication chain
+ }
+
+ public function can_handle_request(): bool {
+ return isset($_SERVER['HTTP_X_CUSTOM_AUTH']);
+ }
+}
-## License
+// Register your authenticator
+add_filter('tigerstyle_scent_authenticators', function($authenticators) {
+ $authenticators['custom'] = new MyCustomScent();
+ return $authenticators;
+});
+```
-This project is part of the WordPress OAuth2 Provider plugin.
\ No newline at end of file
+### Territory Hooks
+
+```php
+// Before scent authentication
+add_action('tigerstyle_scent_before_auth', function($token) {
+ // Pre-authentication logic
+});
+
+// Successful scent recognition
+add_action('tigerstyle_scent_authenticated', function($user_id, $client_id) {
+ // Log successful authentication
+});
+
+// Failed authentication attempt
+add_action('tigerstyle_scent_auth_failed', function($token) {
+ // Handle failed authentication
+});
+```
+
+---
+
+## ๐ Troubleshooting
+
+### Common Issues
+
+**๐ซ "Territory access denied"**
+- Check client credentials match exactly
+- Verify redirect URI is registered
+- Ensure HTTPS if required
+
+**โ "Invalid scent token"**
+- Token may have expired (default: 1 hour)
+- Check token format: `ScentBearer TOKEN_HERE`
+- Verify database connection
+
+**๐ "Territory code expired"**
+- Authorization codes expire in 10 minutes
+- Don't reuse codes (one-time use only)
+- Check system time synchronization
+
+### Debug Mode
+
+Enable scent trail debugging:
+
+```php
+define('TIGERSTYLE_SCENT_DEBUG', true);
+```
+
+Check WordPress debug logs for detailed scent analysis.
+
+---
+
+## ๐ License
+
+TigerStyle Scent is licensed under the GPL v2 or later.
+
+```
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+```
+
+---
+
+## ๐ Acknowledgments
+
+- **WordPress Core Team** - For the amazing platform
+- **OAuth2 Working Group** - For the OAuth2 specification
+- **The Feline Community** - For inspiration on territorial behavior
+- **TigerStyle Team** - For making enterprise auth purr-fect
+
+---
+
+
+
+**๐ฏ Made with โค๏ธ by TigerStyle**
+
+*Authentication that's as natural as a cat's instinct*
+
+[Website](https://tigerstyle.com) โข [Documentation](https://docs.tigerstyle.com) โข [Support](https://support.tigerstyle.com)
+
+
\ No newline at end of file
diff --git a/includes/class-authenticator-interface.php b/includes/class-authenticator-interface.php
new file mode 100644
index 0000000..3ca6af2
--- /dev/null
+++ b/includes/class-authenticator-interface.php
@@ -0,0 +1,43 @@
+detect_scent_token();
+
+ if (!$scent_token) {
+ return false;
+ }
+
+ // Validate scent and return associated user ID
+ return $this->validate_scent_token($scent_token);
+ }
+
+ /**
+ * Detect scent token from various sources like a cat's keen senses
+ *
+ * @return string|null The detected scent token
+ */
+ private function detect_scent_token(): ?string {
+ // Check Authorization header for Bearer/ScentBearer token
+ $auth_header = $this->get_authorization_header();
+
+ if ($auth_header) {
+ // Support both Bearer and our custom ScentBearer format
+ if (preg_match('/^(?:Bearer|ScentBearer)\s+(.+)$/i', $auth_header, $matches)) {
+ return trim($matches[1]);
+ }
+ }
+
+ // Check for scent token in POST data (like a scent trail)
+ if (isset($_POST['scent_token'])) {
+ return sanitize_text_field($_POST['scent_token']);
+ }
+
+ // Check for scent token in GET parameters (less secure, like faint scent)
+ if (isset($_GET['scent_token'])) {
+ return sanitize_text_field($_GET['scent_token']);
+ }
+
+ return null;
+ }
+
+ /**
+ * Get Authorization header across different server configurations
+ *
+ * @return string|null
+ */
+ private function get_authorization_header(): ?string {
+ // Standard HTTP_AUTHORIZATION header
+ if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
+ return $_SERVER['HTTP_AUTHORIZATION'];
+ }
+
+ // Alternative header names used by some servers
+ if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
+ return $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
+ }
+
+ // Check for Authorization header in apache_request_headers()
+ if (function_exists('apache_request_headers')) {
+ $headers = apache_request_headers();
+ if (isset($headers['Authorization'])) {
+ return $headers['Authorization'];
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Validate scent token and return associated user ID like recognizing a familiar cat
+ */
+ private function validate_scent_token(string $token): ?int {
+ // Use ScentServer for database-backed token validation
+ $scent_server = new TigerStyleScent_ScentServer([]);
+ $scent_data = $scent_server->analyze_scent_token($token);
+
+ if ($scent_data && $scent_data['active']) {
+ // Log successful scent recognition
+ do_action('tigerstyle_scent_authenticated', $scent_data['user_id'], $scent_data['client_id']);
+
+ return $scent_data['user_id'];
+ }
+
+ // Log failed scent recognition attempt
+ do_action('tigerstyle_scent_authentication_failed', $token);
+
+ return null;
+ }
+
+ /**
+ * Get authentication type identifier
+ *
+ * @return string
+ */
+ public function get_type(): string {
+ return 'scent_token';
+ }
+
+ /**
+ * Get authentication priority (higher = checked first)
+ * Scent authentication should be high priority like a cat's primary sense
+ *
+ * @return int
+ */
+ public function get_priority(): int {
+ return 20; // Higher than basic auth, lower than emergency authentication
+ }
+
+ /**
+ * Check if this authenticator can handle the current request
+ * Like a cat detecting if there's a scent to analyze
+ *
+ * @return bool
+ */
+ public function can_handle_request(): bool {
+ // Can handle if we detect any scent token
+ return $this->detect_scent_token() !== null;
+ }
+
+ /**
+ * Provide authentication challenges/hints for API clients
+ *
+ * @return array
+ */
+ public function get_authentication_challenge(): array {
+ return [
+ 'type' => 'ScentBearer',
+ 'realm' => 'TigerStyle Territory',
+ 'description' => 'Provide your scent token in the Authorization header: "ScentBearer YOUR_TOKEN"',
+ 'hint' => 'Get your scent token from /oauth/token endpoint'
+ ];
+ }
+
+ /**
+ * Verify scent token scope for specific resource access
+ * Like checking if a cat has permission to enter certain territory
+ *
+ * @param string $token Scent token to verify
+ * @param string $required_scope Required scope for access
+ * @return bool
+ */
+ public function verify_territory_access(string $token, string $required_scope): bool {
+ $scent_server = new TigerStyleScent_ScentServer([]);
+ $scent_data = $scent_server->analyze_scent_token($token);
+
+ if (!$scent_data || !$scent_data['active']) {
+ return false;
+ }
+
+ // Check if token has required scope
+ $token_scopes = explode(' ', $scent_data['scope'] ?? '');
+ return in_array($required_scope, $token_scopes);
+ }
+
+ /**
+ * Log scent authentication events for territory monitoring
+ *
+ * @param string $event Event type
+ * @param array $data Event data
+ */
+ private function log_scent_event(string $event, array $data = []): void {
+ if (defined('TIGERSTYLE_SCENT_DEBUG') && TIGERSTYLE_SCENT_DEBUG) {
+ error_log(sprintf(
+ '[TigerStyle Scent] %s: %s',
+ $event,
+ json_encode($data)
+ ));
+ }
+
+ // Fire WordPress action for logging systems
+ do_action('tigerstyle_scent_log', $event, $data);
+ }
+}
\ No newline at end of file
diff --git a/includes/modules/class-scent-server.php b/includes/modules/class-scent-server.php
new file mode 100644
index 0000000..173394f
--- /dev/null
+++ b/includes/modules/class-scent-server.php
@@ -0,0 +1,549 @@
+wpdb = $wpdb;
+ $this->settings = $settings;
+ }
+
+ /**
+ * Handle scent authentication requests (OAuth2 endpoints)
+ */
+ public function handle_scent_request(): void {
+ $endpoint = get_query_var('oauth_endpoint');
+
+ switch ($endpoint) {
+ case 'authorize':
+ $this->handle_territory_authorization();
+ break;
+ case 'token':
+ $this->handle_scent_token_exchange();
+ break;
+ case 'introspect':
+ $this->handle_scent_analysis();
+ break;
+ case 'revoke':
+ $this->handle_scent_revocation();
+ break;
+ default:
+ $this->send_error_response(404, 'unknown_territory', 'Unknown territory endpoint');
+ }
+ }
+
+ /**
+ * Handle territory authorization (OAuth2 authorize endpoint)
+ */
+ private function handle_territory_authorization(): void {
+ // Validate query parameters
+ $response_type = sanitize_text_field($_GET['response_type'] ?? '');
+ $client_id = sanitize_text_field($_GET['client_id'] ?? '');
+ $redirect_uri = esc_url_raw($_GET['redirect_uri'] ?? '');
+ $scope = sanitize_text_field($_GET['scope'] ?? '');
+ $state = sanitize_text_field($_GET['state'] ?? '');
+
+ // Validate required parameters for territory access
+ if (empty($response_type) || empty($client_id)) {
+ $this->send_error_response(400, 'invalid_request', 'Missing required territory parameters');
+ return;
+ }
+
+ // Only support authorization code (territory code) flow
+ if ($response_type !== 'code') {
+ $this->send_error_response(400, 'unsupported_response_type', 'Only territory code flow is supported');
+ return;
+ }
+
+ // Validate client scent credentials
+ $client = $this->recognize_client_scent($client_id);
+ if (!$client) {
+ $this->send_error_response(400, 'invalid_client', 'Unknown client scent');
+ return;
+ }
+
+ // Validate redirect URI for safe territory return
+ if (!empty($redirect_uri) && !$this->validate_territory_return_uri($client, $redirect_uri)) {
+ $this->send_error_response(400, 'invalid_request', 'Invalid territory return URI');
+ return;
+ }
+
+ // Check if user is authenticated (has proper scent)
+ if (!is_user_logged_in()) {
+ // Redirect to WordPress login with return URL
+ $login_url = wp_login_url(add_query_arg($_GET, admin_url('admin.php')));
+ wp_redirect($login_url);
+ exit;
+ }
+
+ // Handle POST request (user authorization decision)
+ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ if (isset($_POST['authorize']) && wp_verify_nonce($_POST['_wpnonce'], 'tigerstyle_scent_authorize')) {
+ $this->grant_territory_access($client_id, $redirect_uri, $scope, $state);
+ } elseif (isset($_POST['deny'])) {
+ $this->deny_territory_access($redirect_uri, $state);
+ }
+ return;
+ }
+
+ // Show territory authorization form
+ $this->show_territory_authorization_form([
+ 'client' => $client,
+ 'scope' => $scope,
+ 'state' => $state,
+ 'redirect_uri' => $redirect_uri,
+ 'client_id' => $client_id
+ ]);
+ }
+
+ /**
+ * Handle scent token exchange (OAuth2 token endpoint)
+ */
+ private function handle_scent_token_exchange(): void {
+ // Only accept POST requests for scent token exchange
+ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
+ $this->send_error_response(405, 'method_not_allowed', 'Scent exchange requires POST');
+ return;
+ }
+
+ $grant_type = sanitize_text_field($_POST['grant_type'] ?? '');
+
+ switch ($grant_type) {
+ case 'authorization_code':
+ $this->handle_territory_code_grant();
+ break;
+ case 'refresh_token':
+ $this->handle_scent_refresh_grant();
+ break;
+ case 'client_credentials':
+ $this->handle_client_scent_credentials_grant();
+ break;
+ default:
+ $this->send_error_response(400, 'unsupported_grant_type', 'Unsupported scent grant type');
+ }
+ }
+
+ /**
+ * Handle territory code grant (authorization code flow)
+ */
+ private function handle_territory_code_grant(): void {
+ // Extract scent parameters
+ $code = sanitize_text_field($_POST['code'] ?? '');
+ $client_id = sanitize_text_field($_POST['client_id'] ?? '');
+ $redirect_uri = esc_url_raw($_POST['redirect_uri'] ?? '');
+ $code_verifier = sanitize_text_field($_POST['code_verifier'] ?? '');
+
+ // Get client scent credentials from Authorization header or POST
+ $client_credentials = $this->extract_client_scent_credentials();
+ if ($client_credentials) {
+ $client_id = $client_credentials['client_id'];
+ $client_secret = $client_credentials['client_secret'];
+ } else {
+ $client_secret = sanitize_text_field($_POST['client_secret'] ?? '');
+ }
+
+ // Validate required scent parameters
+ if (empty($code) || empty($client_id)) {
+ $this->send_error_response(400, 'invalid_request', 'Missing required scent parameters');
+ return;
+ }
+
+ // Get and validate territory code
+ $territory_code = $this->get_territory_code($code);
+ if (!$territory_code) {
+ $this->send_error_response(400, 'invalid_grant', 'Invalid territory code');
+ return;
+ }
+
+ // Check if territory code has expired
+ if (strtotime($territory_code['expires']) < time()) {
+ $this->delete_territory_code($code);
+ $this->send_error_response(400, 'invalid_grant', 'Territory code expired');
+ return;
+ }
+
+ // Validate client scent match
+ if ($territory_code['client_id'] !== $client_id) {
+ $this->send_error_response(400, 'invalid_client', 'Client scent mismatch');
+ return;
+ }
+
+ // Get client details for scent recognition
+ $client = $this->recognize_client_scent($client_id);
+ if (!$client) {
+ $this->send_error_response(400, 'invalid_client', 'Invalid client scent');
+ return;
+ }
+
+ // Validate client secret for confidential clients (strong scent verification)
+ if (!$client['is_public']) {
+ if (empty($client_secret) || !hash_equals($client['client_secret'], $client_secret)) {
+ $this->send_error_response(401, 'invalid_client', 'Invalid scent credentials');
+ return;
+ }
+ }
+
+ // Validate territory return URI
+ if (!empty($redirect_uri) && $territory_code['redirect_uri'] !== $redirect_uri) {
+ $this->send_error_response(400, 'invalid_grant', 'Territory return URI mismatch');
+ return;
+ }
+
+ // Generate scent tokens
+ $scent_token = $this->generate_scent_token($client_id, $territory_code['user_id'], $territory_code['scope']);
+ $refresh_scent = $this->generate_refresh_scent($client_id, $territory_code['user_id'], $territory_code['scope']);
+
+ // Delete territory code (one-time use like a scent trail)
+ $this->delete_territory_code($code);
+
+ // Send scent token response
+ $this->send_scent_token_response($scent_token, $refresh_scent, $territory_code['scope']);
+ }
+
+ /**
+ * Handle scent analysis (OAuth2 introspect endpoint)
+ */
+ private function handle_scent_analysis(): void {
+ $token = sanitize_text_field($_POST['token'] ?? '');
+
+ if (empty($token)) {
+ $this->send_error_response(400, 'invalid_request', 'Missing scent token for analysis');
+ return;
+ }
+
+ $scent_data = $this->analyze_scent_token($token);
+
+ header('Content-Type: application/json');
+ echo json_encode($scent_data);
+ exit;
+ }
+
+ /**
+ * Recognize client by their unique scent (get client data)
+ */
+ private function recognize_client_scent(string $client_id): ?array {
+ // Query WordPress posts to find OAuth2 client by scent signature
+ $posts = get_posts([
+ 'post_type' => 'oauth2_client',
+ 'meta_key' => 'client_id',
+ 'meta_value' => $client_id,
+ 'posts_per_page' => 1,
+ 'post_status' => 'publish'
+ ]);
+
+ if (empty($posts)) {
+ return null;
+ }
+
+ $post = $posts[0];
+ $client_scent_data = [
+ 'client_id' => get_post_meta($post->ID, 'client_id', true),
+ 'client_secret' => get_post_meta($post->ID, 'client_secret', true),
+ 'redirect_uris' => get_post_meta($post->ID, 'redirect_uris', true),
+ 'grant_types' => get_post_meta($post->ID, 'grant_types', true),
+ 'scope' => get_post_meta($post->ID, 'scope', true),
+ 'is_public' => (bool)get_post_meta($post->ID, 'is_public', true),
+ 'name' => $post->post_title,
+ 'client_name' => $post->post_title // Add client_name for scent recognition display
+ ];
+
+ return $client_scent_data;
+ }
+
+ /**
+ * Validate territory return URI for safe scent trail
+ */
+ private function validate_territory_return_uri(array $client, string $redirect_uri): bool {
+ $redirect_uris = $client['redirect_uris'] ?? '';
+ if (empty($redirect_uris)) {
+ return false;
+ }
+
+ $allowed_uris = explode(',', $redirect_uris);
+ return in_array($redirect_uri, array_map('trim', $allowed_uris));
+ }
+
+ /**
+ * Generate unique scent token (access token)
+ */
+ private function generate_scent_token(string $client_id, int $user_id, string $scope): string {
+ $scent_token = bin2hex(random_bytes(32));
+ $expires = date('Y-m-d H:i:s', time() + 3600); // 1 hour scent trail
+
+ // Store scent token in territory database
+ $this->wpdb->insert(
+ $this->wpdb->prefix . 'oauth_access_tokens',
+ [
+ 'access_token' => $scent_token,
+ 'client_id' => $client_id,
+ 'user_id' => $user_id,
+ 'expires' => $expires,
+ 'scope' => $scope
+ ]
+ );
+
+ return $scent_token;
+ }
+
+ /**
+ * Generate refresh scent for long-term authentication
+ */
+ private function generate_refresh_scent(string $client_id, int $user_id, string $scope): string {
+ $refresh_scent = bin2hex(random_bytes(32));
+ $expires = date('Y-m-d H:i:s', time() + (30 * 24 * 3600)); // 30 day scent memory
+
+ // Store refresh scent in territory database
+ $this->wpdb->insert(
+ $this->wpdb->prefix . 'oauth_refresh_tokens',
+ [
+ 'refresh_token' => $refresh_scent,
+ 'client_id' => $client_id,
+ 'user_id' => $user_id,
+ 'expires' => $expires,
+ 'scope' => $scope
+ ]
+ );
+
+ return $refresh_scent;
+ }
+
+ /**
+ * Analyze scent token validity and return data
+ */
+ public function analyze_scent_token(string $token): ?array {
+ $result = $this->wpdb->get_row(
+ $this->wpdb->prepare(
+ "SELECT * FROM {$this->wpdb->prefix}oauth_access_tokens WHERE access_token = %s",
+ $token
+ ),
+ ARRAY_A
+ );
+
+ if (!$result) {
+ return ['active' => false];
+ }
+
+ // Check if scent has expired
+ if (strtotime($result['expires']) < time()) {
+ // Clean up expired scent
+ $this->wpdb->delete(
+ $this->wpdb->prefix . 'oauth_access_tokens',
+ ['access_token' => $token]
+ );
+ return ['active' => false];
+ }
+
+ return [
+ 'active' => true,
+ 'client_id' => $result['client_id'],
+ 'user_id' => (int)$result['user_id'],
+ 'scope' => $result['scope'],
+ 'exp' => strtotime($result['expires'])
+ ];
+ }
+
+ /**
+ * Show territory authorization form with cat-themed UI
+ */
+ private function show_territory_authorization_form(array $params): void {
+ // Set content type
+ header('Content-Type: text/html; charset=utf-8');
+
+ // TigerStyle Scent authorization form with cat theming
+ ?>
+
+
+
+ TigerStyle Territory Access
+
+
+
+
+
+
+ wpdb->insert(
+ $this->wpdb->prefix . 'oauth_authorization_codes',
+ [
+ 'authorization_code' => $territory_code,
+ 'client_id' => $client_id,
+ 'user_id' => $user_id,
+ 'redirect_uri' => $redirect_uri,
+ 'expires' => $expires,
+ 'scope' => $scope
+ ]
+ );
+
+ // Build redirect URL with territory code
+ $redirect_params = [
+ 'code' => $territory_code,
+ 'state' => $state
+ ];
+
+ $redirect_url = add_query_arg($redirect_params, $redirect_uri);
+ wp_redirect($redirect_url);
+ exit;
+ }
+
+ /**
+ * Send scent token response
+ */
+ private function send_scent_token_response(string $scent_token, string $refresh_scent, string $scope): void {
+ $response = [
+ 'access_token' => $scent_token,
+ 'token_type' => 'ScentBearer', // Cat-themed token type!
+ 'expires_in' => 3600,
+ 'refresh_token' => $refresh_scent,
+ 'scope' => $scope
+ ];
+
+ header('Content-Type: application/json');
+ header('Cache-Control: no-store');
+ echo json_encode($response);
+ exit;
+ }
+
+ /**
+ * Send error response with cat-themed messages
+ */
+ private function send_error_response(int $status_code, string $error, string $description): void {
+ http_response_code($status_code);
+ header('Content-Type: application/json');
+
+ $response = [
+ 'error' => $error,
+ 'error_description' => $description
+ ];
+
+ echo json_encode($response);
+ exit;
+ }
+
+ /**
+ * Extract client scent credentials from Authorization header
+ */
+ private function extract_client_scent_credentials(): ?array {
+ $auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
+
+ if (strpos($auth_header, 'Basic ') === 0) {
+ $credentials = base64_decode(substr($auth_header, 6));
+ $parts = explode(':', $credentials, 2);
+
+ if (count($parts) === 2) {
+ return [
+ 'client_id' => $parts[0],
+ 'client_secret' => $parts[1],
+ ];
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get territory code data
+ */
+ private function get_territory_code(string $code): ?array {
+ return $this->wpdb->get_row(
+ $this->wpdb->prepare(
+ "SELECT * FROM {$this->wpdb->prefix}oauth_authorization_codes WHERE authorization_code = %s",
+ $code
+ ),
+ ARRAY_A
+ );
+ }
+
+ /**
+ * Delete used territory code
+ */
+ private function delete_territory_code(string $code): void {
+ $this->wpdb->delete(
+ $this->wpdb->prefix . 'oauth_authorization_codes',
+ ['authorization_code' => $code]
+ );
+ }
+
+ // Additional methods for refresh tokens, client credentials, etc. would follow the same cat-themed pattern...
+}
\ No newline at end of file
diff --git a/tigerstyle-scent.php b/tigerstyle-scent.php
new file mode 100644
index 0000000..c7fe220
--- /dev/null
+++ b/tigerstyle-scent.php
@@ -0,0 +1,565 @@
+load_dependencies();
+ $this->init_hooks();
+ $this->load_settings();
+ $this->init_modules();
+
+ // Log plugin initialization
+ $this->log_scent_event('plugin_initialized', [
+ 'version' => TIGERSTYLE_SCENT_VERSION,
+ 'php_version' => PHP_VERSION,
+ 'wp_version' => get_bloginfo('version')
+ ]);
+ }
+
+ /**
+ * Load plugin dependencies like gathering scent detection tools
+ */
+ private function load_dependencies(): void {
+ // Load interface first
+ require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/class-authenticator-interface.php';
+
+ // Load core modules
+ require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/modules/class-scent-server.php';
+ require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'includes/modules/class-scent-authenticator.php';
+
+ // Load admin components if in admin area
+ if (is_admin()) {
+ $this->load_admin_dependencies();
+ }
+ }
+
+ /**
+ * Load admin-specific dependencies
+ */
+ private function load_admin_dependencies(): void {
+ // Admin components will be loaded here
+ // require_once TIGERSTYLE_SCENT_PLUGIN_DIR . 'admin/class-admin.php';
+ }
+
+ /**
+ * Initialize WordPress hooks like setting up scent detection points
+ */
+ private function init_hooks(): void {
+ // Plugin lifecycle hooks
+ register_activation_hook(TIGERSTYLE_SCENT_PLUGIN_FILE, array($this, 'activate_territory'));
+ register_deactivation_hook(TIGERSTYLE_SCENT_PLUGIN_FILE, array($this, 'deactivate_territory'));
+
+ // Core WordPress hooks
+ add_action('init', array($this, 'init_oauth_endpoints'));
+ add_action('template_redirect', array($this, 'handle_oauth_requests'));
+ add_filter('determine_current_user', array($this, 'authenticate_user'), 20);
+ add_action('rest_api_init', array($this, 'setup_rest_authentication'));
+
+ // Admin hooks
+ if (is_admin()) {
+ add_action('admin_menu', array($this, 'add_admin_menu'));
+ add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
+ }
+
+ // Custom post type for OAuth clients (scent profiles)
+ add_action('init', array($this, 'register_client_post_type'));
+
+ // AJAX hooks for admin interface
+ add_action('wp_ajax_tigerstyle_scent_test_auth', array($this, 'ajax_test_authentication'));
+ }
+
+ /**
+ * Load plugin settings from WordPress options
+ */
+ private function load_settings(): void {
+ $defaults = array(
+ 'enable_scent_authentication' => true,
+ 'scent_token_lifetime' => 3600, // 1 hour
+ 'refresh_scent_lifetime' => 2592000, // 30 days
+ 'territory_code_lifetime' => 600, // 10 minutes
+ 'require_https' => false, // Set to true in production
+ 'debug_scent_trails' => TIGERSTYLE_SCENT_DEBUG,
+ 'allowed_scent_origins' => array(),
+ 'scent_strength' => 'medium' // low, medium, high security levels
+ );
+
+ $this->settings = wp_parse_args(
+ get_option('tigerstyle_scent_settings', array()),
+ $defaults
+ );
+ }
+
+ /**
+ * Initialize plugin modules like different scent detection systems
+ */
+ private function init_modules(): void {
+ // Initialize scent server
+ $this->scent_server = new TigerStyleScent_ScentServer($this->settings);
+
+ // Initialize authenticator modules
+ $this->modules['scent_authenticator'] = new TigerStyleScent_ScentAuthenticator();
+
+ // Allow other plugins to add custom authenticators
+ $this->modules = apply_filters('tigerstyle_scent_authenticators', $this->modules);
+
+ // Sort by priority (like cat hierarchy)
+ uasort($this->modules, function($a, $b) {
+ return $b->get_priority() - $a->get_priority();
+ });
+ }
+
+ /**
+ * Plugin activation - Set up territory
+ */
+ public function activate_territory(): void {
+ // Create database tables for scent storage
+ $this->create_scent_tables();
+
+ // Set up rewrite rules for OAuth endpoints
+ $this->setup_rewrite_rules();
+ flush_rewrite_rules();
+
+ // Create default settings
+ if (!get_option('tigerstyle_scent_settings')) {
+ update_option('tigerstyle_scent_settings', $this->settings);
+ }
+
+ // Log activation
+ $this->log_scent_event('territory_activated', [
+ 'version' => TIGERSTYLE_SCENT_VERSION,
+ 'timestamp' => current_time('mysql')
+ ]);
+ }
+
+ /**
+ * Plugin deactivation - Secure territory
+ */
+ public function deactivate_territory(): void {
+ // Remove rewrite rules
+ flush_rewrite_rules();
+
+ // Log deactivation
+ $this->log_scent_event('territory_deactivated', [
+ 'version' => TIGERSTYLE_SCENT_VERSION,
+ 'timestamp' => current_time('mysql')
+ ]);
+ }
+
+ /**
+ * Initialize OAuth endpoints like setting up scent detection points
+ */
+ public function init_oauth_endpoints(): void {
+ // Add query vars for OAuth endpoints
+ add_rewrite_tag('%oauth_endpoint%', '([^&]+)');
+
+ // Setup rewrite rules
+ $this->setup_rewrite_rules();
+ }
+
+ /**
+ * Setup rewrite rules for OAuth endpoints (scent detection points)
+ */
+ private function setup_rewrite_rules(): void {
+ // OAuth2 endpoints with TigerStyle branding
+ add_rewrite_rule('^oauth/authorize/?$', 'index.php?oauth_endpoint=authorize', 'top');
+ add_rewrite_rule('^oauth/token/?$', 'index.php?oauth_endpoint=token', 'top');
+ add_rewrite_rule('^oauth/introspect/?$', 'index.php?oauth_endpoint=introspect', 'top');
+ add_rewrite_rule('^oauth/revoke/?$', 'index.php?oauth_endpoint=revoke', 'top');
+
+ // OpenID Connect discovery
+ add_rewrite_rule('^\.well-known/openid_configuration/?$', 'index.php?oauth_endpoint=openid_config', 'top');
+ add_rewrite_rule('^well-known/openid_configuration/?$', 'index.php?oauth_endpoint=openid_config', 'top');
+
+ // TigerStyle specific endpoints
+ add_rewrite_rule('^tigerstyle/scent-analysis/?$', 'index.php?oauth_endpoint=introspect', 'top');
+ add_rewrite_rule('^tigerstyle/territory-status/?$', 'index.php?oauth_endpoint=status', 'top');
+ }
+
+ /**
+ * Handle OAuth requests like processing scent detection
+ */
+ public function handle_oauth_requests(): void {
+ $oauth_endpoint = get_query_var('oauth_endpoint');
+
+ if ($oauth_endpoint && $this->scent_server) {
+ // Log request
+ $this->log_scent_event('oauth_request', [
+ 'endpoint' => $oauth_endpoint,
+ 'method' => $_SERVER['REQUEST_METHOD'],
+ 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
+ ]);
+
+ $this->scent_server->handle_scent_request();
+ }
+ }
+
+ /**
+ * Authenticate user via scent detection
+ */
+ public function authenticate_user($user_id) {
+ // Don't override if user is already authenticated
+ if ($user_id) {
+ return $user_id;
+ }
+
+ // Try each authenticator in priority order
+ foreach ($this->modules as $authenticator) {
+ if ($authenticator->can_handle_request()) {
+ $authenticated_user = $authenticator->authenticate();
+ if ($authenticated_user) {
+ $this->log_scent_event('user_authenticated', [
+ 'user_id' => $authenticated_user,
+ 'authenticator' => $authenticator->get_type(),
+ 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown'
+ ]);
+ return $authenticated_user;
+ }
+ }
+ }
+
+ return $user_id;
+ }
+
+ /**
+ * Setup REST API authentication like territorial access control
+ */
+ public function setup_rest_authentication(): void {
+ // Remove WordPress cookie authentication for REST if using scent tokens
+ remove_filter('rest_authentication_errors', 'rest_cookie_check_errors', 100);
+
+ // Add custom authentication error handling
+ add_filter('rest_authentication_errors', array($this, 'rest_authentication_errors'));
+ }
+
+ /**
+ * Handle REST authentication errors with cat-themed messages
+ */
+ public function rest_authentication_errors($result): WP_Error {
+ if (!empty($result)) {
+ return $result;
+ }
+
+ if (!is_user_logged_in()) {
+ return new WP_Error(
+ 'tigerstyle_scent_unauthorized',
+ '๐ฏ Territory access denied. Valid scent token required.',
+ array('status' => 401)
+ );
+ }
+
+ return $result;
+ }
+
+ /**
+ * Register OAuth client custom post type (scent profiles)
+ */
+ public function register_client_post_type(): void {
+ register_post_type('oauth2_client', array(
+ 'labels' => array(
+ 'name' => '๐พ Scent Profiles',
+ 'singular_name' => '๐พ Scent Profile',
+ 'add_new' => 'Add New Profile',
+ 'add_new_item' => 'Add New Scent Profile',
+ 'edit_item' => 'Edit Scent Profile',
+ 'new_item' => 'New Scent Profile',
+ 'view_item' => 'View Scent Profile',
+ 'search_items' => 'Search Scent Profiles',
+ 'not_found' => 'No scent profiles found',
+ 'not_found_in_trash' => 'No scent profiles found in trash'
+ ),
+ 'public' => false,
+ 'show_ui' => true,
+ 'show_in_menu' => 'tigerstyle-scent',
+ 'capability_type' => 'post',
+ 'supports' => array('title'),
+ 'menu_icon' => 'dashicons-shield'
+ ));
+ }
+
+ /**
+ * Add admin menu for TigerStyle Scent
+ */
+ public function add_admin_menu(): void {
+ add_menu_page(
+ 'TigerStyle Scent',
+ '๐ฏ TigerStyle Scent',
+ 'manage_options',
+ 'tigerstyle-scent',
+ array($this, 'admin_page'),
+ 'dashicons-shield-alt',
+ 30
+ );
+
+ add_submenu_page(
+ 'tigerstyle-scent',
+ 'Territory Settings',
+ 'โ๏ธ Territory Settings',
+ 'manage_options',
+ 'tigerstyle-scent',
+ array($this, 'admin_page')
+ );
+
+ add_submenu_page(
+ 'tigerstyle-scent',
+ 'Scent Analysis',
+ '๐ Scent Analysis',
+ 'manage_options',
+ 'tigerstyle-scent-analysis',
+ array($this, 'scent_analysis_page')
+ );
+ }
+
+ /**
+ * Admin page content
+ */
+ public function admin_page(): void {
+ ?>
+
+
๐ฏ TigerStyle Scent - Territory Control
+
Welcome to your OAuth2 authentication territory! Manage your digital scent trails and access control.
+
+
+
+
๐ฐ Territory Status
+
Plugin Version:
+
Scent Detection: settings['enable_scent_authentication'] ? 'โ
Active' : 'โ Inactive'; ?>
+
Territory Security: settings['scent_strength']; ?>
+
+
+
+
+
+
+
+
+
+
๐ Scent Analysis - Territory Monitoring
+
Monitor and analyze scent token activity in your territory.
+
+
+
Recent Scent Activity
+
Scent trail monitoring coming soon...
+
+
+ admin_url('admin-ajax.php'),
+ 'nonce' => wp_create_nonce('tigerstyle_scent_admin')
+ ));
+ }
+ }
+
+ /**
+ * AJAX test authentication
+ */
+ public function ajax_test_authentication(): void {
+ check_ajax_referer('tigerstyle_scent_admin', 'nonce');
+
+ wp_send_json_success(array(
+ 'message' => '๐ฏ Scent recognition system is operational!',
+ 'territory' => 'secure',
+ 'timestamp' => current_time('mysql')
+ ));
+ }
+
+ /**
+ * Create database tables for scent storage
+ */
+ private function create_scent_tables(): void {
+ global $wpdb;
+
+ $charset_collate = $wpdb->get_charset_collate();
+
+ // Access tokens (scent tokens)
+ $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}oauth_access_tokens (
+ access_token varchar(255) NOT NULL,
+ client_id varchar(255) NOT NULL,
+ user_id int(11) NOT NULL,
+ expires datetime NOT NULL,
+ scope text,
+ PRIMARY KEY (access_token),
+ KEY client_id (client_id),
+ KEY user_id (user_id)
+ ) $charset_collate;";
+
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
+ dbDelta($sql);
+
+ // Refresh tokens (scent memory)
+ $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}oauth_refresh_tokens (
+ refresh_token varchar(255) NOT NULL,
+ client_id varchar(255) NOT NULL,
+ user_id int(11) NOT NULL,
+ expires datetime NOT NULL,
+ scope text,
+ PRIMARY KEY (refresh_token),
+ KEY client_id (client_id),
+ KEY user_id (user_id)
+ ) $charset_collate;";
+
+ dbDelta($sql);
+
+ // Authorization codes (territory codes)
+ $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}oauth_authorization_codes (
+ authorization_code varchar(255) NOT NULL,
+ client_id varchar(255) NOT NULL,
+ user_id int(11) NOT NULL,
+ redirect_uri text NOT NULL,
+ expires datetime NOT NULL,
+ scope text,
+ code_challenge varchar(255),
+ code_challenge_method varchar(10),
+ PRIMARY KEY (authorization_code),
+ KEY client_id (client_id),
+ KEY user_id (user_id)
+ ) $charset_collate;";
+
+ dbDelta($sql);
+ }
+
+ /**
+ * Log scent events for debugging and monitoring
+ */
+ private function log_scent_event(string $event, array $data = []): void {
+ if (TIGERSTYLE_SCENT_DEBUG) {
+ error_log(sprintf(
+ '[TigerStyle Scent] %s: %s',
+ $event,
+ json_encode($data)
+ ));
+ }
+
+ // Fire action for external logging systems
+ do_action('tigerstyle_scent_event', $event, $data);
+ }
+
+ /**
+ * Get plugin settings
+ */
+ public function get_settings(): array {
+ return $this->settings;
+ }
+
+ /**
+ * Get scent server instance
+ */
+ public function get_scent_server(): ?TigerStyleScent_ScentServer {
+ return $this->scent_server;
+ }
+}
+
+/**
+ * Helper function to get main plugin instance
+ * Like calling an alpha cat
+ */
+function tigerstyle_scent(): TigerStyleScent {
+ return TigerStyleScent::instance();
+}
+
+// Initialize the TigerStyle Scent territory
+tigerstyle_scent();
\ No newline at end of file