DOCS

v1.3.28
 // Pro v1.2.20

 · Latest

Security Guards

Order Daemon implements an extensible security layer based on the Strategy and Composite design patterns. This system handles CSRF protection, capability checks, and audit logging for all sensitive operations.

Architecture

The system has five pieces:

  1. Guard Interface – contract all security checks implement
  2. Concrete Guards – individual checks (nonce, capability)
  3. CompositeGuard – chains multiple guards together
  4. GuardChecker – centralized execution with automatic audit logging
  5. GuardFactory – convenience factory for common patterns
classDiagram
    Guard <|-- NonceGuard
    Guard <|-- CapabilityGuard
    Guard <|-- CompositeGuard
    CompositeGuard o-- Guard
    GuardChecker --> Guard : verifies
    GuardFactory --> Guard : creates

Core interfaces and classes

Guard interface

interface Guard {
    public function verify(): void;
}

All guards implement this. On failure they throw SecurityException.

Concrete guards

NonceGuard – CSRF protection using wp_verify_nonce().

CapabilityGuard – Role-based access via current_user_can(). Supports both general and object-specific capabilities.

CompositeGuard – All contained guards must pass. Fails on the first failure.

GuardChecker

Centralized execution with automatic audit logging of every check (success and failure).

$guard_checker = new GuardChecker();
$guard_checker->check($guard, ['context' => 'admin_action']);

Logged data includes: guard type, user context (ID, roles, IP), request context (method, user agent, referer), execution time, error details.

GuardFactory

// Form submission
$guard = GuardFactory::createFormGuards(
    $_POST['_wpnonce'],
    'my_action',
    'manage_woocommerce'
);

// AJAX
$guard = GuardFactory::createAjaxGuards(
    $_POST['_wpnonce'],
    'my_ajax_action',
    'edit_shop_orders'
);

// REST API
$guard = GuardFactory::createRestGuards(
    $request->get_header('X-WP-Nonce'),
    'wp_rest',
    'manage_options'
);

Usage examples

Form submission

try {
    $guard = GuardFactory::createFormGuards(
        $_POST['_wpnonce'],
        'my_plugin_action',
        'manage_woocommerce'
    );

    $guard_checker = OrderDaemonCompletionManagerPlugin::get_guard_checker();
    $guard_checker->check($guard, [
        'operation' => 'rule_creation',
        'rule_name' => sanitize_text_field($_POST['rule_name'])
    ]);

    process_rule_creation($_POST);

} catch (SecurityException $e) {
    wp_die('Security verification failed: ' . esc_html($e->getMessage()));
}

AJAX handler

add_action('wp_ajax_my_ajax_action', function() {
    try {
        $guard = GuardFactory::createAjaxGuards(
            $_POST['_wpnonce'],
            'my_ajax_action',
            'edit_shop_orders'
        );

        $guard_checker = OrderDaemonCompletionManagerPlugin::get_guard_checker();
        $guard_checker->check($guard, ['operation' => 'order_update']);

        wp_send_json_success(process_order_update($_POST));

    } catch (SecurityException $e) {
        wp_send_json_error(['message' => $e->getMessage()], 403);
    }
});

REST endpoint

register_rest_route('my-plugin/v1', '/secure-endpoint', [
    'methods'             => 'POST',
    'permission_callback' => '__return_true', // handled by guard
    'callback'            => function($request) {
        try {
            $guard = GuardFactory::createRestGuards(
                $request->get_header('X-WP-Nonce'),
                'wp_rest',
                'manage_woocommerce'
            );

            $guard_checker = OrderDaemonCompletionManagerPlugin::get_guard_checker();
            $guard_checker->check($guard, ['endpoint' => 'secure_endpoint']);

            return new WP_REST_Response(process_api_request($request));

        } catch (SecurityException $e) {
            return new WP_Error('security_failure', $e->getMessage(), ['status' => 403]);
        }
    },
]);

Custom guard

class CustomGuard implements Guard {
    public function verify(): void {
        if (!custom_security_check()) {
            throw new SecurityException('Custom security check failed', [
                'check_type' => 'custom_validation',
            ]);
        }
    }
}

$guard_checker->check(new CustomGuard(), ['context' => 'custom_operation']);

Composite guard

$guard = new CompositeGuard(
    new NonceGuard($_POST['_wpnonce'], 'custom_action'),
    new CapabilityGuard('edit_shop_orders', 'order_management'),
    new CustomGuard(),
);
$guard_checker->check($guard, ['operation' => 'complex_operation']);

Capability reference

OperationCapability
Most admin operationsmanage_woocommerce
Order-related actionsedit_shop_orders
Plugin settingsmanage_options

Troubleshooting

Nonce verification fails:

  • Ensure the nonce field is output in forms: wp_nonce_field('my_action')
  • Verify action strings match between creation and verification
  • Check AJAX requests include the nonce in POST data

Capability check fails:

  • Confirm the user has the required WordPress role
  • Check for capability filters modifying access
  • Verify object-specific capabilities use correct object IDs

GuardChecker instance unavailable:

  • Ensure the plugin is fully initialized before calling
  • Check for fatal errors during plugin bootstrap

Viewing security events: All guard checks are logged with security_check_passed or security_check_failed event types. Filter by these in the Insight Dashboard to audit security activity.

What’s next