Overview
OAuth activation adds customer account approval to normal license activation. The customer signs in to the WooNooW-powered vendor store and explicitly approves the requesting website.
The merchant chooses Simple API or Secure OAuth globally and may allow per-product overrides. The client uses the same activation endpoint for both methods; it does not select the method with an activation_mode request field.
OAuth activation still uses the canonical website identity:
persistent installation UUID + normalized domain
Read Website Identity before implementing this flow.
Security properties
WooNooW's signed OAuth state binds:
- license key;
- original and normalized requesting domain;
- persistent installation UUID;
- callback
return_url;
- state expiry.
The callback URL must normalize to the same domain as the requesting site. State expires after 10 minutes. The final activation token:
- expires after 5 minutes in UTC;
- is stored only as a SHA-256 hash by WooNooW;
- is bound to the approved UUID + domain identity;
- can be used only once.
Activation flow
- 1
1. Client requests activation
Send the license key, complete website identity, and a callback URL on the requesting site.
POST /wp-json/woonoow/v1/licenses/activate
{
"license_key": "XXXX-YYYY-ZZZZ-WWWW",
"domain": "https://customer-site.com",
"installation_id": "550e8400-e29b-41d4-a716-446655440000",
"return_url": "https://customer-site.com/wp-admin/admin.php?page=my-plugin-license"
}
- 2
2. Client receives an approval URL
When the product requires OAuth, WooNooW responds with HTTP 200 OK and success: false:
{
"success": false,
"code": "oauth_required",
"message": "This license requires account verification. You will be redirected to complete activation.",
"redirect_url": "https://your-store.com/my-account/license-connect/?license_key=XXXX-YYYY-ZZZZ-WWWW&site_url=https%3A%2F%2Fcustomer-site.com&return_url=https%3A%2F%2Fcustomer-site.com%2Fcallback&installation_id=550e8400-e29b-41d4-a716-446655440000&state=eyJhbGci...&nonce=7a8b9c0d1e"
}
Treat redirect_url as opaque. Do not reconstruct or modify its signed state parameters.
- 3
3. Customer approves the website
Open redirect_url in the user's browser. The customer signs in to the vendor store, verifies the product and requesting site, and approves the activation.
- 4
4. Vendor redirects to the client callback
WooNooW redirects the browser back to the approved return_url. Depending on whether the vendor store handled approval through the Customer SPA or the PHP fallback, the query parameters differ:
- Customer SPA flow (
LicensesController::oauth_confirm): appends activation_token, license_key, and nonce.
- PHP template flow (
LicensingModule::process_license_confirmation): appends activation_token, license_key, and state.
- 5
5. Client exchanges the activation token
Complete activation by sending the same license key, combined identity, and single-use activation_token to the activation endpoint:
POST /wp-json/woonoow/v1/licenses/activate
{
"license_key": "XXXX-YYYY-ZZZZ-WWWW",
"domain": "https://customer-site.com",
"installation_id": "550e8400-e29b-41d4-a716-446655440000",
"activation_token": "temporary-single-use-token"
}
A successful response returns the activation ID, remaining seats, and product identifiers:
{
"success": true,
"activation_id": 123,
"activations_remaining": 2,
"product_id": 42,
"variation_id": 0
}
Sequence
sequenceDiagram
participant C as Client website
participant B as Customer browser
participant V as WooNooW vendor store
C->>V: POST /licenses/activate<br/>key + domain + UUID + return_url
V-->>C: oauth_required + redirect_url
C->>B: Open redirect_url
B->>V: Sign in and approve website
V->>V: Verify signed state and license ownership
V-->>B: Redirect to approved return_url<br/>with short-lived activation_token
B->>C: Callback
C->>V: POST /licenses/activate<br/>same key + domain + UUID + token
V-->>C: activation_id + activations_remaining
OAuth backend endpoints
On the vendor store, the OAuth confirmation UI interacts with two REST API endpoints. Both endpoints require authentication (is_user_logged_in()) and verify that the requested license key belongs to the currently logged-in customer (user_id === current_user_id).
1. Validate connection request
GET /wp-json/woonoow/v1/licenses/oauth/validate?license_key={key}&state={state}
Validates the signed state token, checks that the state's embedded license key matches license_key, verifies account ownership, and resolves the requesting site identity.
Response (200):
{
"license_key": "XXXX-YYYY-ZZZZ-WWWW",
"product_id": 42,
"variation_id": 0,
"product_name": "WooNooW Pro",
"variation_name": "",
"status": "active",
"activation_limit": 3,
"activation_count": 1,
"expires_at": "2027-09-08 12:00:00",
"usage_expires_at_utc": "2027-09-08T12:00:00Z"
}
2. Confirm connection and issue token
POST /wp-json/woonoow/v1/licenses/oauth/confirm
{
"license_key": "XXXX-YYYY-ZZZZ-WWWW",
"state": "eyJhbGciOiJIUzI1NiIs...",
"nonce": "7a8b9c0d1e"
}
Verifies ownership and signed state, issues a single-use activation token (5-minute TTL) bound to the approved identity, and constructs the callback redirect URL:
Response (200):
{
"success": true,
"redirect_url": "https://customer-site.com/callback?activation_token=tok_abc123&license_key=XXXX-YYYY-ZZZZ-WWWW&nonce=7a8b9c0d1e",
"activation_token": "tok_abc123"
}
Callback example for WordPress
$activation_token = sanitize_text_field(wp_unslash($_GET['activation_token'] ?? ''));
$license_key = sanitize_text_field(wp_unslash($_GET['license_key'] ?? ''));
$installation_id = get_option('my_product_installation_id', '');
$response = wp_remote_post('https://your-store.com/wp-json/woonoow/v1/licenses/activate', [
'timeout' => 15,
'headers' => ['Content-Type' => 'application/json'],
'body' => wp_json_encode([
'license_key' => $license_key,
'domain' => home_url(),
'installation_id' => $installation_id,
'activation_token'=> $activation_token,
]),
]);
Validate the local pending request before running this exchange. Do not write the raw activation token to logs or persistent settings.
Failure handling
| Code | Action |
|---|
missing_return_url | Add a callback URL to the initial activation request |
invalid_return_url | Use a callback URL on the same normalized domain as domain |
missing_state | State token query parameter was omitted on OAuth validation |
invalid_state | Restart activation; the signed state is invalid or expired |
unauthorized | The logged-in customer does not own the requested license |
license_not_found | License key does not exist |
invalid_token | Restart approval; the token is invalid, expired, or belongs to another identity |
token_consumed | Do not reuse the token; validate the license or restart the flow |
activation_limit_reached | Ask the customer to deactivate an old installation or upgrade entitlement |
activation_transaction_failed | Database error starting activation transaction on vendor store; retry request |
A network failure must not cause the client to generate a new installation UUID. Reuse the persistent identity and start a fresh OAuth request when necessary.