Two Factor Authentication support is available in CoCart Plus starting from v1.6.0 .
Prerequisites
CoCart Plus automatically detects the plugin and loads 2FA support only when available.
In the following request examples below, you would replace <username> and <password> with your credentials before sending the request.
Authentication Flow
1. Initial Login Attempt (No 2FA Code)
When a user with 2FA enabled attempts to login without providing a 2FA code:
# Store response and HTTP status code
response = $( curl -s -w "\n%{http_code}" -X POST https://your-store.com/wp-json/cocart/v2/login \
-H "Content-Type: application/json" \
-d '{
"username": "<username>",
"password": "<password>"
}' )
# Extract HTTP status code (last line) and response body
http_code = $( echo " $response " | tail -n1 )
body = $( echo " $response " | sed '$d' )
# Handle 2FA requirement
if [ " $http_code " = "401" ]; then
echo "2FA required. Response:"
echo " $body "
# Parse JSON to extract 2FA info (requires jq)
# available_providers=$(echo "$body" | jq -r '.data.available_providers[]')
# default_provider=$(echo "$body" | jq -r '.data.default_provider')
fi
Response (401 Unauthorized):
{
"code" : "cocart_2fa_required" ,
"message" : "2FA verification required. Please provide a 2FA code using one of these providers: email, totp" ,
"data" : {
"status" : 401 ,
"2fa_required" : true ,
"available_providers" : [ "email" , "totp" ],
"default_provider" : "totp" ,
"email_sent" : false
}
}
Important: If the default provider is email, an email with the verification code is automatically sent to the user’s email address, and email_sent will be true.
2. Complete Login with 2FA Code
Option A: Using Default Provider (Recommended)
# Complete login with 2FA code
response = $( curl -s -w "\n%{http_code}" -X POST https://your-store.com/wp-json/cocart/v2/login \
-H "Content-Type: application/json" \
-d '{
"username": "[email protected] ",
"password": "password123",
"2fa_code": "123456"
}' )
# Extract HTTP status code and response body
http_code = $( echo " $response " | tail -n1 )
body = $( echo " $response " | sed '$d' )
# Handle response
if [ " $http_code " = "200" ]; then
echo "Login successful!"
echo " $body "
# Extract token if using JWT (requires jq)
# token=$(echo "$body" | jq -r '.token')
else
echo "Login failed. Response:"
echo " $body "
fi
Option B: Specifying Provider Explicitly
# Complete login with explicit 2FA provider
response = $( curl -s -w "\n%{http_code}" -X POST https://your-store.com/wp-json/cocart/v2/login \
-H "Content-Type: application/json" \
-d '{
"username": "[email protected] ",
"password": "password123",
"2fa_code": "123456",
"2fa_provider": "email"
}' )
# Extract HTTP status code and response body
http_code = $( echo " $response " | tail -n1 )
body = $( echo " $response " | sed '$d' )
# Handle response
if [ " $http_code " = "200" ]; then
echo "Login successful!"
echo " $body "
# Extract token if using JWT (requires jq)
# token=$(echo "$body" | jq -r '.token')
else
echo "Login failed. Response:"
echo " $body "
fi
Default Provider Logic
The default provider is determined by the following priority order:
Last Successfully Used Provider : The provider the user most recently used for successful authentication (CoCart Plus tracks this automatically)
User’s Primary Provider : The provider set as primary in the user’s Two Factor settings
First Enabled Provider : If no primary provider is set, uses the first provider in the enabled providers list
Fallback : Empty string if no providers are enabled (shouldn’t occur in practice)
Provider Memory & Smart Defaults
CoCart Plus automatically remembers which 2FA provider each user successfully used last time, making subsequent logins more convenient:
Automatic Tracking
When : Every successful 2FA authentication
What : Stores the provider alias and timestamp
Where : User meta keys _cocart_2fa_last_used_provider and _cocart_2fa_last_used_timestamp
Benefits
Faster logins : Users don’t need to specify their preferred provider each time
Better UX : Reduces cognitive load for users with multiple 2FA methods
Fail-safe : Always validates that the remembered provider is still enabled
API Parameters
2fa_code
Type : String
Required : Conditional (required only if user has 2FA enabled)
Description : The verification code from the user’s 2FA provider
2fa_provider
Type : String
Required : No
Enum : Dynamically populated from available Two Factor providers
Description : Specific provider to use for verification
Available Providers : The list includes all providers installed with the Two Factor plugin using clean aliases (e.g., email, totp, backup)
Provider-Specific Behavior
TOTP (Time-based One-Time Password)
Uses apps like Google Authenticator, Authy
Codes are 6-digit numbers that expire every 30 seconds
No additional setup required during login
Email
Sends verification codes via email
Automatic Email Sending : When email is the default provider and no code is provided, an email is automatically sent
Codes typically expire after 15 minutes
Response includes "email_sent": true when email is sent
Backup Codes
Static codes that can be used when primary method is unavailable
Each code can only be used once
Treated like any other provider in the API
Error Handling
Invalid 2FA Code
{
"code" : "cocart_2fa_invalid_code" ,
"message" : "Invalid 2FA code provided." ,
"data" : {
"status" : 401
}
}
Invalid Provider
{
"code" : "cocart_2fa_invalid_provider" ,
"message" : "Invalid 2FA provider: invalid_provider_name" ,
"data" : {
"status" : 400
}
}
Client Implementation Example
async function loginWithCoCart ( username , password , twoFactorCode = null , provider = null ) {
const payload = { username , password };
if ( twoFactorCode ) {
payload [ '2fa_code' ] = twoFactorCode ;
}
if ( provider ) {
payload [ '2fa_provider' ] = provider ;
}
try {
const response = await fetch ( '/wp-json/cocart/v2/login' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( payload )
});
const data = await response . json ();
if ( response . status === 401 && data . data ?.[ '2fa_required' ]) {
// Handle 2FA requirement
const defaultProvider = data . data . default_provider ;
const emailSent = data . data . email_sent ;
if ( emailSent ) {
alert ( 'Verification code sent to your email' );
}
// Prompt user for 2FA code and retry
const code = prompt ( 'Enter your 2FA code:' );
return loginWithCoCart ( username , password , code , defaultProvider );
}
if ( ! response . ok ) {
throw new Error ( data . message );
}
return data ; // Successful login
} catch ( error ) {
console . error ( 'Login failed:' , error );
throw error ;
}
}
Security Considerations
All 2FA validation uses the Two Factor plugin’s security measures
Codes are validated with replay protection
Email codes have built-in expiration
Rate limiting is handled by the Two Factor plugin
TOTP validation accounts for clock drift
No 2FA codes are logged or stored by CoCart