- Add LicenseConnect.tsx focused OAuth confirmation page in customer SPA - Add /licenses/oauth/validate and /licenses/oauth/confirm API endpoints - Update App.tsx to render license-connect outside BaseLayout (no header/footer) - Add license_activation_method field to product settings in Admin SPA - Create LICENSING_MODULE.md with comprehensive OAuth flow documentation - Update API_ROUTES.md with license module endpoints
8.7 KiB
8.7 KiB
Licensing Module Documentation
Overview
WooNooW's Licensing Module provides software license management for digital products. It supports two activation methods:
- Simple API - Direct license key validation via API
- 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:
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:
{
"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)
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):
{
"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:
- Logs into vendor portal (if not already)
- Sees license activation confirmation page
- Reviews license key and requesting site
- 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
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):
{
"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
- State Token - Prevents CSRF attacks, expires after 5 minutes
- Activation Token - Single-use, expires after 5 minutes
- User Verification - OAuth ensures license owner authorizes activation
- Domain Validation - Tracks activated domains for audit
- 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) |