# Licensing Module Documentation ## Overview WooNooW's Licensing Module provides software license management for digital products. It supports two activation methods: 1. **Simple API** - Direct license key validation via API 2. **Secure OAuth** - User verification via vendor portal before activation --- ## API Endpoints ### Admin Endpoints (Authenticated Admin) ``` GET /licenses # List all licenses (with pagination, search) GET /licenses/{id} # Get single license POST /licenses # Create license PUT /licenses/{id} # Update license DELETE /licenses/{id} # Delete license ``` ### Public Endpoints (For Client Software) ``` POST /licenses/validate # Validate license key POST /licenses/activate # Activate license on domain POST /licenses/deactivate # Deactivate license from domain ``` ### OAuth Endpoints (Authenticated User) ``` GET /licenses/oauth/validate # Validate OAuth state and license ownership POST /licenses/oauth/confirm # Confirm activation and get token ``` --- ## Activation Flows ### 1. Simple API Flow Direct license activation without user verification. Suitable for trusted environments. ``` Client Vendor API | | |-- POST /licenses/activate -| | {license_key, domain} | | | |<-- {success, activation_id}| ``` **Example Request:** ```bash curl -X POST "https://vendor.com/wp-json/woonoow/v1/licenses/activate" \ -H "Content-Type: application/json" \ -d '{ "license_key": "XXXX-YYYY-ZZZZ-WWWW", "domain": "https://customer-site.com", "machine_id": "optional-unique-id" }' ``` **Example Response:** ```json { "success": true, "activation_id": 123, "license_key": "XXXX-YYYY-ZZZZ-WWWW", "status": "active", "expires_at": "2025-01-31T00:00:00Z", "activation_limit": 3, "activation_count": 1 } ``` --- ### 2. Secure OAuth Flow (Recommended) User must verify ownership on vendor portal before activation. More secure. ``` Client Vendor Portal Vendor API | | | |-- POST /licenses/activate -| | | {license_key, domain} | | | | | |<-- {oauth_redirect, state}-| | | | | |== User redirects browser ==| | | | | |-------- BROWSER ---------->| | | /my-account/license-connect?license_key=...&state=...| | | | | [User logs in if needed] | | [User sees confirmation page] | | [User clicks "Authorize"] | | | | | |-- POST /oauth/confirm -->| | |<-- {token} --------------| | | | |<------- REDIRECT ----------| | | {return_url}?activation_token=xxx | | | | |-- POST /licenses/activate -----------------------> | | {license_key, activation_token} | | | | |<-- {success, activation_id} --------------------------| ``` --- ## OAuth Flow Step by Step ### Step 1: Client Requests Activation (OAuth Mode) ```bash curl -X POST "https://vendor.com/wp-json/woonoow/v1/licenses/activate" \ -H "Content-Type: application/json" \ -d '{ "license_key": "XXXX-YYYY-ZZZZ-WWWW", "domain": "https://customer-site.com", "return_url": "https://customer-site.com/activation-callback", "activation_mode": "oauth" }' ``` **Response (OAuth Required):** ```json { "success": false, "oauth_required": true, "oauth_redirect": "https://vendor.com/my-account/license-connect/?license_key=XXXX-YYYY-ZZZZ-WWWW&site_url=https://customer-site.com&return_url=https://customer-site.com/activation-callback&state=abc123&nonce=xyz789", "state": "abc123" } ``` ### Step 2: User Opens Browser to OAuth URL Client opens the `oauth_redirect` URL in user's browser. The user: 1. Logs into vendor portal (if not already) 2. Sees license activation confirmation page 3. Reviews license key and requesting site 4. Clicks "Authorize" to confirm ### Step 3: User Gets Redirected Back After authorization, user is redirected to `return_url` with token: ``` https://customer-site.com/activation-callback?activation_token=xyz123&license_key=XXXX-YYYY-ZZZZ-WWWW&nonce=xyz789 ``` ### Step 4: Client Exchanges Token for Activation ```bash curl -X POST "https://vendor.com/wp-json/woonoow/v1/licenses/activate" \ -H "Content-Type: application/json" \ -d '{ "license_key": "XXXX-YYYY-ZZZZ-WWWW", "domain": "https://customer-site.com", "activation_token": "xyz123" }' ``` **Response (Success):** ```json { "success": true, "activation_id": 456, "license_key": "XXXX-YYYY-ZZZZ-WWWW", "status": "active" } ``` --- ## Configuration ### Site-Level Settings In Admin SPA: **Settings > Licensing** | Setting | Description | |---------|-------------| | Default Activation Method | `api` or `oauth` - Default for all products | | License Key Format | Format pattern for generated keys | | Default Validity Period | Days until license expires | | Default Activation Limit | Max activations per license | ### Per-Product Settings In Admin SPA: **Products > Edit Product > General Tab** | Setting | Description | |---------|-------------| | Enable Licensing | Toggle to enable license generation | | Activation Method | `Use Site Default`, `Simple API`, or `Secure OAuth` | --- ## Database Schema ### Licenses Table (`wp_woonoow_licenses`) | Column | Type | Description | |--------|------|-------------| | id | BIGINT | Primary key | | license_key | VARCHAR(255) | Unique license key | | product_id | BIGINT | WooCommerce product ID | | order_id | BIGINT | WooCommerce order ID | | user_id | BIGINT | Customer user ID | | status | VARCHAR(50) | active, inactive, expired, revoked | | activation_limit | INT | Max allowed activations | | activation_count | INT | Current activation count | | expires_at | DATETIME | Expiration date | | created_at | DATETIME | Created timestamp | | updated_at | DATETIME | Updated timestamp | ### Activations Table (`wp_woonoow_license_activations`) | Column | Type | Description | |--------|------|-------------| | id | BIGINT | Primary key | | license_id | BIGINT | Foreign key to licenses | | domain | VARCHAR(255) | Activated domain | | machine_id | VARCHAR(255) | Optional machine identifier | | status | VARCHAR(50) | active, deactivated, pending | | user_agent | TEXT | Client user agent | | activated_at | DATETIME | Activation timestamp | --- ## Customer SPA: License Connect Page The OAuth confirmation page is available at: ``` /my-account/license-connect/ ``` ### Query Parameters | Parameter | Required | Description | |-----------|----------|-------------| | license_key | Yes | License key to activate | | site_url | Yes | Requesting site URL | | return_url | Yes | Callback URL after authorization | | state | Yes | CSRF protection token | | nonce | No | Additional security nonce | ### UI Features - **Focused Layout** - No header/sidebar/footer, just the authorization card - **Brand Display** - Shows vendor site name - **License Details** - Displays license key, site URL, product name - **Security Warning** - Warns user to only authorize trusted sites - **Authorize/Deny Buttons** - Clear actions for user --- ## Security Considerations 1. **State Token** - Prevents CSRF attacks, expires after 5 minutes 2. **Activation Token** - Single-use, expires after 5 minutes 3. **User Verification** - OAuth ensures license owner authorizes activation 4. **Domain Validation** - Tracks activated domains for audit 5. **Rate Limiting** - Consider implementing on activation endpoints --- ## Files Reference | File | Purpose | |------|---------| | `includes/Modules/Licensing/LicensingModule.php` | Module registration, endpoint handlers | | `includes/Modules/Licensing/LicenseManager.php` | Core license operations | | `includes/Api/LicensesController.php` | REST API endpoints | | `customer-spa/src/pages/Account/LicenseConnect.tsx` | OAuth confirmation UI | | `customer-spa/src/pages/Account/index.tsx` | Routing for license pages | | `customer-spa/src/App.tsx` | Top-level routing (license-connect outside BaseLayout) |