Back to Blog
Lesson 33 of the Advanced WordPress Plugin Engineering: Scale, Security & React UIs course
WordPressJune 28, 20264 min read

Licensing Infrastructure: Secure Remote Verification for WordPress Plugins

Learn to build a secure Licensing infrastructure for your WordPress plugin. Implement remote verification, manage activation states, and prevent unauthorized use.

WordPressPHPLicensingSaaSSecurityAPIplugin-development

Previously in this course, we covered Internationalization (i18n) to ensure our plugin reaches a global audience. Now that your plugin is ready for the world, you need a way to protect your intellectual property and monetize your work.

Implementing robust Licensing for a WordPress plugin is as much about Security as it is about SaaS business logic. You aren't just checking a string; you are establishing a trust relationship between your server and your user's site.

The Licensing Architecture

At its core, a licensing system requires three distinct components:

  1. The Licensing Server: A remote API (SaaS) that tracks license keys, activations, and expiration dates.
  2. Local Status Management: Storing the license state securely in the wp_options table.
  3. The Activation Flow: A handshake process that validates the key and binds it to a specific site URL.

The Licensing Handshake Process

When a user enters their key, your plugin must perform a secure POST request to your licensing server.

Sequence diagram: participant U as User Site; participant S as Licensing Server; U → S: POST /activate key, site_url; S → S: Validate key/limit; S → U: JSON Response status, expiry, token; U → U: Store encrypted response

Implementing Local License Management

We avoid querying the remote server on every page load. Instead, we store the license status in wp_options and use a transient to cache the remote validation result.

Worked Example: The License Manager Service

We will create a LicenseManager class. This class handles the logic of storing the key and verifying it against your remote API.

PHP
namespace KnowledgeBase\Licensing;

class LicenseManager {
    private const OPTION_KEY = 'kb_license_data';

    public function activate(string $key, string $site_url): array {
        $response = wp_remote_post('https:#6A9955">//api.your-saas.com/v1/activate', [
            'body' => [
                'key' => $key,
                'url' => $site_url,
            ],
            'timeout' => 15,
        ]);

        if (is_wp_error($response)) {
            return ['status' => 'error', 'message' => 'Connection failed.'];
        }

        $data = json_decode(wp_remote_retrieve_body($response), true);

        if ($data['success']) {
            update_option(self::OPTION_KEY, [
                'key' => $key,
                'status' => 'active',
                'expires' => $data['expires']
            ]);
            return ['status' => 'success'];
        }

        return ['status' => 'invalid', 'message' => 'Invalid license key.'];
    }

    public function is_active(): bool {
        $data = get_option(self::OPTION_KEY);
        return isset($data['status']) && $data['status'] === 'active';
    }
}

Building the Activation Flow

To ensure this is secure, your activation flow must prevent "key sharing." When the activation request reaches your server, you should store the home_url() of the requester. If the same key is activated on ten different domains, your server should return an error.

Security Considerations:

  • SSL/TLS: Never send license keys over plain HTTP.
  • Data Masking: Only store the last four characters of the license key in your database to prevent full key exposure if the wp_options table is compromised.
  • Rate Limiting: Protect your licensing API endpoints using Postgres Rate Limiting and Redis Patterns for Multi-Tenant APIs to prevent brute-force attacks on your keys.

Hands-on Exercise

  1. Define the Schema: Create a new file src/Licensing/LicenseManager.php in your plugin.
  2. Implement the UI: Create a simple React component in your admin dashboard that takes a text input and a "Activate" button.
  3. Hook the Action: Use the Custom REST API Integration technique to send the key from your React component to a custom WordPress REST endpoint that triggers your LicenseManager::activate() method.

Common Pitfalls

  • Trusting the Client: Never perform license verification purely on the client-side. The client can be modified by the user. Always verify the status via a server-side is_active() check before rendering premium features.
  • Ignoring Network Failures: If your licensing server goes down, your users shouldn't lose access to their site. Implement a "grace period" logic where the license remains active for 72 hours after a failed remote check.
  • Hardcoding API Keys: Do not hardcode your private licensing API keys in the plugin source. Use environment variables or a secure configuration file that is excluded from version control.

Recap

We've built a foundation for a Licensing system that leverages wp_options for local state and a remote API for validation. By integrating this with your Advanced Admin Dashboards, you provide a professional experience for your users while keeping your SaaS infrastructure secure.

Up next: Automated Update API — we will learn how to hook your custom licensing status into the WordPress Update API to deliver one-click updates to your paying customers.

Similar Posts