OAuth Activation Flow

User-approved license activation with signed state and combined website identity

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:

text
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.

    http
    POST /wp-json/woonoow/v1/licenses/activate
    Content-Type: application/json
    
    json
    {
      "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:

    json
    {
      "success": false,
      "code": "oauth_required",
      "message": "This license requires account verification...",
      "redirect_url": "https://your-store.com/my-account/license-connect/..."
    }
    

    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 to the approved return_url with query parameters including:

    • activation_token;
    • license_key;
    • nonce.

    Only accept callbacks for a locally pending activation request. Keep any local CSRF/request-correlation value in the client session; WooNooW validates its own signed state on the vendor side.

  5. 5. Client exchanges the activation token

    Complete activation by sending the same license key and combined identity used in step 1.

    http
    POST /wp-json/woonoow/v1/licenses/activate
    Content-Type: application/json
    
    json
    {
      "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 contains the final activation_id and activations_remaining.

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

Callback example for WordPress

php
$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

CodeAction
missing_return_urlAdd a callback URL to the initial activation request
invalid_return_urlUse a callback URL on the same normalized domain as domain
invalid_stateRestart activation; the signed state is invalid or expired
invalid_tokenRestart approval; the token is invalid, expired, or belongs to another identity
token_consumedDo not reuse the token; validate the license or restart the flow
activation_limit_reachedAsk the customer to deactivate an old installation or change entitlement

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.

Last updated Jul 29, 2026