Skip to main content
This guide only works if you have CoCart v4.8 and up installed.

What is authentication injection?

Authentication injection refers to the ability to insert custom authentication logic into the existing login process. This allows developers to implement additional security measures, such as custom validation rules, external system integration, role-based access control, or comprehensive logging mechanisms, without modifying the core authentication flow.

Overview

CoCart’s authentication injection system is built around a series of hooks (filters and actions) that allow you to customize the login process. These hooks provide entry points to modify the behavior of authentication, enabling you to add layers of security or integrate with external systems.

Available Hooks

Each hook is documented below with its description, parameters, and practical usage examples.

cocart_login_permission_callback

Made available since v4.8.0
Allows you to modify the permission result after basic authentication. This is the primary hook for adding custom validation, external system checks, or role-based access control.
add_filter( 'cocart_login_permission_callback', function( $permission, $current_user, $request, $endpoint ) {
    // Your additional authentication logic here
    return $permission; // or return WP_Error to deny access
}, 10, 4 );
permission
boolean|WP_Error
Current permission status (true after basic auth)
current_user
WP_User
The authenticated user object
request
WP_REST_Request
The current REST API request
endpoint
string
The endpoint being accessed (‘login’)
Return Values
boolean|WP_Error

cocart_login_permission_granted

Made available since v4.8.0
Fires when login permission is successfully granted. Perfect for audit logging and post-authentication tasks.
add_action( 'cocart_login_permission_granted', function( $current_user, $request, $endpoint ) {
    // Log successful authentication
    error_log("Login granted for user: {$current_user->ID}");
}, 10, 3 );
current_user
WP_User
The authenticated user object
request
WP_REST_Request
The current REST API request
endpoint
string
The endpoint being accessed (‘login’)

cocart_login_secure_auth_methods

Made available since v4.8.0
Allows customizing which authentication methods skip additional checks (like custom validation or external system verification).
add_filter( 'cocart_login_secure_auth_methods', function( $secure_methods, $current_method ) {
    // Add custom secure authentication methods
    $secure_methods[] = 'custom_oauth';
    return $secure_methods;
}, 10, 2 );
secure_methods
array
Array of authentication methods considered secure (default: [‘jwt’, ‘api_key’])
current_method
string
The current authentication method being used

cocart_login_collection_params

Made available since v4.8.0
Allows you to add additional parameters to the login endpoint for custom authentication data.
add_filter( 'cocart_login_collection_params', function( $additional_params ) {
    $additional_params['department_code'] = array(
        'description' => 'Employee department code',
        'type' => 'string',
        'required' => false,
        'sanitize_callback' => 'sanitize_text_field',
    );

    $additional_params['license_key'] = array(
        'description' => 'Application license key',
        'type' => 'string',
        'pattern' => '^[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$',
    );

    return $additional_params;
} );
additional_params
array
Array of additional parameters to add to the login endpoint

API Usage Examples

  • cURL
  • PHP
  • JavaScript
curl -X POST "https://yoursite.com/wp-json/cocart/v2/login" \
  -H "Authorization: Basic $(echo -n 'username:password' | base64)" \
  -H "Content-Type: application/json"
curl -X POST "https://yoursite.com/wp-json/cocart/v2/login" \
  -H "Authorization: Basic $(echo -n 'username:password' | base64)" \
  -H "Content-Type: application/json" \
  -H "X-Client-ID: mobile-app" \
  -H "X-App-Version: 1.2.3"
curl -X POST "https://yoursite.com/wp-json/cocart/v2/login" \
  -H "Authorization: Basic $(echo -n 'username:password' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "device_id": "mobile-app-12345",
    "app_version": "2.1.0"
  }'
curl -X POST "https://yoursite.com/wp-json/cocart/v2/login" \
  -H "Authorization: Bearer your-jwt-token-here" \
  -H "Content-Type: application/json"

Response Examples

Successful Login

{
    "success": true,
    "data": {
        "jwt_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
        "refresh_token": "abc123def456...",
        "user_id": 123,
        "user_email": "user@example.com",
        "user_display_name": "John Doe"
    }
}

Unsupported Version

{
    "code": "cocart_unsupported_version",
    "message": "Unsupported API version",
    "data": {
        "status": 400,
        "requested_version": "1.0",
        "supported_versions": ["2.0", "2.1", "2.2"]
    }
}

Device Not Registered

{
    "code": "cocart_device_not_registered",
    "message": "This device is not registered for this account",
    "data": {
        "status": 403,
        "device_registration_required": true
    }
}

Rate Limited

{
    "code": "cocart_rate_limited",
    "message": "Too many login attempts. Please try again later.",
    "data": {
        "status": 429,
        "retry_after": 3600
    }
}

Authentication Flow

  • First-Time Login (Basic Auth + Custom Validation)
  • Subsequent Requests (JWT Token)
1

Initial Authentication

User provides username/password via Basic Auth
2

Basic Validation

Basic authentication succeeds → user authenticated
3

Permission Callback

Permission callback runs → detects basic_auth method
4

Custom Validation

Custom filters execute → check for additional requirements (device, etc.)
5

Additional Data Prompt

If additional data required → returns error with specific requirements
6

Validation Success

User provides required data → validation succeeds
7

JWT Token Issued

Successful login response includes JWT token for future requests (if active)

Advanced Configuration

Customizing Secure Authentication Methods

You can modify which authentication methods skip additional checks like custom validation:
add_filter( 'cocart_login_secure_auth_methods', 'my_secure_auth_methods', 10, 2 );

function my_secure_auth_methods( $secure_methods, $current_method ) {
    // Add custom secure authentication methods
    $secure_methods[] = 'custom_oauth';

    // Remove JWT from secure methods (force additional validation even with JWT)
    $secure_methods = array_diff( $secure_methods, array( 'jwt' ) );

    return $secure_methods;
}

Custom Authentication Provider

Create a custom authentication provider that integrates with external systems:
add_filter( 'cocart_login_permission_callback', 'custom_ldap_auth', 10, 4 );

function custom_ldap_auth( $permission, $current_user, $request, $endpoint ) {
    if ( true !== $permission ) {
        return $permission;
    }

    // Check if LDAP authentication is required for this user
    $require_ldap = get_user_meta( $current_user->ID, 'require_ldap_auth', true );

    if ( $require_ldap ) {
        $ldap_token = $request->get_param( 'ldap_token' );

        if ( empty( $ldap_token ) ) {
            return new WP_Error(
                'cocart_ldap_required',
                'LDAP authentication required',
                array( 'status' => 400, 'ldap_required' => true )
            );
        }

        // Validate with LDAP server
        if ( ! validate_ldap_token( $current_user->user_login, $ldap_token ) ) {
            return new WP_Error(
                'cocart_ldap_invalid',
                'Invalid LDAP credentials',
                array( 'status' => 401 )
            );
        }
    }

    return $permission;
}

Implementation Guidelines

  1. Always check the current permission status first - If it’s already an error, don’t override it
  2. Respect secure authentication methods - Use the cocart_login_secure_auth_methods filter appropriately
  3. Provide clear error messages - Include helpful information in error responses
  4. Use appropriate HTTP status codes - 400 for missing required data, 401 for invalid credentials
  5. Include metadata in error responses - Help clients understand what’s needed
  6. Implement rate limiting - Protect against brute force attacks
  7. Log security events - Use the permission granted action for audit trails
  8. Validate all inputs - Sanitize and validate all request parameters
  9. Follow WordPress coding standards - Maintain consistency with WordPress conventions

Security Best Practices

Always validate user input and implement proper error handling when extending authentication.
  • Validate all input parameters - Use WordPress sanitization functions like sanitize_text_field()
  • Always check the permission status first - Return early if permission is already denied
  • Use appropriate HTTP status codes - 400 for bad requests, 401 for authentication failures, 403 for insufficient permissions
  • Log security events - Use the cocart_login_permission_granted action for audit trails

Testing Your Implementation

Simple Test Filter

Test the authentication injection mechanism with a basic filter:
// Simple test filter for development
add_filter( 'cocart_login_permission_callback', 'test_auth_injection', 10, 4 );

function test_auth_injection( $permission, $user, $request, $endpoint ) {
    if ( true !== $permission ) {
        return $permission;
    }

    $test_param = $request->get_param( 'test_auth' );

    if ( 'allow' !== $test_param ) {
        return new WP_Error(
            'test_auth_required',
            'Add test_auth=allow parameter for testing',
            array( 'status' => 400 )
        );
    }

    return true;
}

Test with cURL

# This should fail
curl -X POST "https://yoursite.com/wp-json/cocart/v2/login" \
  -H "Authorization: Basic $(echo -n 'username:password' | base64)" \
  -H "Content-Type: application/json"

# This should succeed
curl -X POST "https://yoursite.com/wp-json/cocart/v2/login" \
  -H "Authorization: Basic $(echo -n 'username:password' | base64)" \
  -H "Content-Type: application/json" \
  -d '{"test_auth": "allow"}'

Common Use Cases

These examples demonstrate practical implementations of authentication injection for common security requirements.
add_filter( 'cocart_login_permission_callback', 'sso_integration', 10, 4 );
function sso_integration( $permission, $current_user, $request, $endpoint ) {
    if ( true !== $permission ) {
        return $permission;
    }

    $sso_token = $request->get_param( 'sso_token' );
    if ( ! empty( $sso_token ) ) {
        // Validate SSO token with external provider
        $sso_valid = validate_sso_token( $sso_token, $current_user->user_email );

        if ( ! $sso_valid ) {
            return new WP_Error(
                'cocart_sso_invalid',
                'Invalid SSO token',
                array( 'status' => 401 )
            );
        }
    }

    return $permission;
}
add_filter( 'cocart_login_permission_callback', 'role_based_auth', 10, 4 );
function role_based_auth( $permission, $current_user, $request, $endpoint ) {
    if ( true !== $permission ) {
        return $permission;
    }

    // Require additional verification for admin users
    if ( in_array( 'administrator', $current_user->roles ) ) {
        $admin_code = $request->get_param( 'admin_verification_code' );

        if ( empty( $admin_code ) ) {
            return new WP_Error(
                'cocart_admin_verification_required',
                'Additional verification required for admin users',
                array( 'status' => 400, 'admin_verification_required' => true )
            );
        }

        if ( ! verify_admin_code( $current_user->ID, $admin_code ) ) {
            return new WP_Error(
                'cocart_admin_verification_invalid',
                'Invalid admin verification code',
                array( 'status' => 401 )
            );
        }
    }

    return $permission;
}
add_filter( 'cocart_login_permission_callback', 'device_registration_check', 10, 4 );
function device_registration_check( $permission, $current_user, $request, $endpoint ) {
    if ( true !== $permission ) {
        return $permission;
    }

    $device_id = $request->get_param( 'device_id' );
    $user_agent = $request->get_header( 'user_agent' );

    if ( empty( $device_id ) ) {
        return new WP_Error(
            'cocart_device_id_required',
            'Device ID is required for authentication',
            array( 'status' => 400 )
        );
    }

    // Check if device is registered for this user
    $registered_devices = get_user_meta( $current_user->ID, 'registered_devices', true ) ?: array();

    if ( ! in_array( $device_id, $registered_devices ) ) {
        return new WP_Error(
            'cocart_device_not_registered',
            'This device is not registered for this account',
            array( 'status' => 403, 'device_registration_required' => true )
        );
    }

    return $permission;
}
add_filter( 'cocart_login_permission_callback', 'geolocation_check', 10, 4 );
function geolocation_check( $permission, $current_user, $request, $endpoint ) {
    if ( true !== $permission ) {
        return $permission;
    }

    $ip_address = CoCart_Authentication::get_ip_address();
    $country_code = get_country_from_ip( $ip_address );

    // Block certain countries
    $blocked_countries = array( 'CN', 'RU', 'KP' );
    $allowed_countries = get_option( 'allowed_countries', array( 'US', 'CA', 'GB', 'AU' ) );

    if ( in_array( $country_code, $blocked_countries ) ) {
        return new WP_Error(
            'cocart_geo_blocked',
            'Access from your location is not permitted',
            array( 'status' => 403, 'country_code' => $country_code )
        );
    }

    // Optional: Only allow specific countries
    if ( ! empty( $allowed_countries ) && ! in_array( $country_code, $allowed_countries ) ) {
        return new WP_Error(
            'cocart_geo_restricted',
            'Access is restricted to approved regions only',
            array( 'status' => 403, 'country_code' => $country_code )
        );
    }

    return $permission;
}
add_filter( 'cocart_login_permission_callback', 'time_based_access', 10, 4 );
function time_based_access( $permission, $current_user, $request, $endpoint ) {
    if ( true !== $permission ) {
        return $permission;
    }

    $current_time = current_time( 'H:i' );
    $current_day = current_time( 'w' ); // 0 = Sunday, 6 = Saturday

    // Get user-specific access hours
    $access_schedule = get_user_meta( $current_user->ID, 'access_schedule', true );

    if ( ! empty( $access_schedule ) ) {
        $allowed = false;

        // Check if current time falls within allowed schedule
        if ( isset( $access_schedule[ $current_day ] ) ) {
            $day_schedule = $access_schedule[ $current_day ];

            foreach ( $day_schedule as $time_slot ) {
                if ( $current_time >= $time_slot['start'] && $current_time <= $time_slot['end'] ) {
                    $allowed = true;
                    break;
                }
            }
        }

        if ( ! $allowed ) {
            $next_available = get_next_available_time( $access_schedule );

            return new WP_Error(
                'cocart_time_restricted',
                'Access is not permitted at this time',
                array(
                    'status' => 403,
                    'current_time' => $current_time,
                    'next_available' => $next_available
                )
            );
        }
    }

    return $permission;
}
add_filter( 'cocart_login_permission_callback', 'validate_custom_headers', 10, 4 );
function validate_custom_headers( $permission, $current_user, $request, $endpoint ) {
    if ( true !== $permission ) {
        return $permission;
    }

    // Validate client identifier
    $client_id = $request->get_header( 'X-Client-ID' );
    $app_version = $request->get_header( 'X-App-Version' );

    if ( ! empty( $client_id ) ) {
        $client_config = get_client_configuration( $client_id );

        if ( ! $client_config ) {
            return new WP_Error(
                'cocart_unknown_client',
                'Unknown client identifier.',
                array( 'status' => 400 )
            );
        }

        // Check minimum app version requirements
        if ( ! empty( $app_version ) && ! empty( $client_config['min_version'] ) ) {
            if ( version_compare( $app_version, $client_config['min_version'], '<' ) ) {
                return new WP_Error(
                    'cocart_outdated_client',
                    'Client version is outdated and no longer supported.',
                    array(
                        'status' => 426,
                        'current_version' => $app_version,
                        'minimum_version' => $client_config['min_version']
                    )
                );
            }
        }

        // Store client info for logging
        update_user_meta( $current_user->ID, 'last_client_info', array(
            'client_id' => $client_id,
            'app_version' => $app_version,
            'login_time' => current_time( 'mysql' )
        ) );
    }

    return $permission;
}
All authentication extensions follow WordPress coding standards and integrate seamlessly with CoCart’s existing authentication system. The examples above demonstrate practical implementations for common security requirements.
I