I'm trying to create a login action using CURL with PHP in a form with CSRF token.
The form is located at this address: https://example.com/account/login and the action of the form refers to: https://example.com/account/login
If I try it from my local server to remote address, it works perfectly. If I try it from remote server to the same address, it doesn't work. What I need to check in your opinion?
This is my code:
//URL of the login form.
define('LOGIN_FORM_URL', 'https://example.com/account/login');
//Login action URL. Sometimes, this is the same URL as the login form.
define('LOGIN_ACTION_URL', 'https://example.com/account/login');
//Initiate cURL.
$this->curl = curl_init(LOGIN_ACTION_URL);
//Tells cURL to return the output once the request has been executed.
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
//Do we want to follow any redirects?
curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($this->curl, CURLOPT_AUTOREFERER, true);
//Where our cookie details are saved. This is typically required
//for authentication, as the session ID is usually saved in the cookie file.
curl_setopt($this->curl, CURLOPT_COOKIEJAR, COOKIE_FILE);
curl_setopt($this->curl, CURLOPT_COOKIEFILE, COOKIE_FILE);
//Sets the user agent. Some websites will attempt to block bot user agents.
//Hence the reason I gave it a Chrome user agent.
curl_setopt($this->curl, CURLOPT_USERAGENT, USER_AGENT);
//We don't want any HTTPS errors.
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
//Execute the login request.
$resultLogin = curl_exec($this->curl);
$dom = new DomDocument();
$token = '';
libxml_use_internal_errors(true);
$dom->loadHTML($resultLogin);
$tokens = $dom->getElementsByTagName("input");
for ($i = 0; $i < $tokens->length; $i++) {
$meta = $tokens->item($i);
if ($meta->getAttribute('name') === '_csrf_token')
$token = $meta->getAttribute('value');
}
$postValues = array(
'username' => $this->username,
'password' => $this->password,
'login' => '',
'_csrf_token' => $token
);
//Set the URL that we want to send our POST request to. In this
//case, it's the action URL of the login form.
curl_setopt($this->curl, CURLOPT_URL, LOGIN_ACTION_URL);
curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
//Tell cURL that we want to carry out a POST request.
curl_setopt($this->curl, CURLOPT_POST, true);
//Set our post fields / date (from the array above).
//curl_setopt($this->curl, CURLOPT_POSTFIELDS, http_build_query($postValues));
curl_setopt($this->curl, CURLOPT_POSTFIELDS, http_build_query($postValues));
// Add headers
curl_setopt($this->curl, CURLOPT_HTTPHEADER, $headers);
//We don't want any HTTPS errors.
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
//Where our cookie details are saved. This is typically required
//for authentication, as the session ID is usually saved in the cookie file.
curl_setopt($this->curl, CURLOPT_COOKIEJAR, COOKIE_FILE);
curl_setopt($this->curl, CURLOPT_COOKIEFILE, COOKIE_FILE);
//Sets the user agent. Some websites will attempt to block bot user agents.
//Hence the reason I gave it a Chrome user agent.
curl_setopt($this->curl, CURLOPT_USERAGENT, USER_AGENT);
//Tells cURL to return the output once the request has been executed.
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
//Allows us to set the referer header. In this particular case, we are
//fooling the server into thinking that we were referred by the login form.
curl_setopt($this->curl, CURLOPT_REFERER, LOGIN_FORM_URL);
//Do we want to follow any redirects?
curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true);
$resultLogin2 = curl_exec($this->curl);
#UPDATE 1
After a debug I generated Verbose output from CURL execute. The first thing that I noticed is that on my remote file I can find this:
* skipping SSL peer certificate verification
but not in the local file. Maybe it is the reason why it doesn't work on remote?
#UPDATE 2
I printed on a file this json_encode(curl_getinfo($this->curl))) and I got two different results. Here details:
LOCAL DEBUG -- {\"url\":\"https:\\/\\/mysite.com\\/account\\/login\",\"content_type\":\"text\\/html; charset=UTF-8\",\"http_code\":403,\"header_size\":685,\"request_size\":1010,\"filetime\":-1,\"ssl_verify_result\":0,\"redirect_count\":0,\"total_time\":0.176508,\"namelookup_time\":0.000194,\"connect_time\":0.000213,\"pretransfer_time\":0.000894,\"size_upload\":112,\"size_download\":42170,\"speed_download\":239602,\"speed_upload\":636,\"download_content_length\":42170,\"upload_content_length\":112,\"starttransfer_time\":0.174651,\"redirect_time\":0,\"redirect_url\":\"\",\"primary_ip\":\"server_ip\",\"certinfo\":[],\"primary_port\":443,\"local_ip\":\"ip_of_my_local_computer\",\"local_port\":53952,\"http_version\":2,\"protocol\":2,\"ssl_verifyresult\":0,\"scheme\":\"HTTPS\",\"appconnect_time_us\":224,\"connect_time_us\":213,\"namelookup_time_us\":194,\"pretransfer_time_us\":894,\"redirect_time_us\":0,\"starttransfer_time_us\":174651,\"total_time_us\":176508}
REMOTE DEBUG -- {\"url\":\"https:\\/\\/mysite.com\\/account\\/login\",\"content_type\":\"text\\/html; charset=UTF-8\",\"http_code\":403,\"header_size\":685,\"request_size\":1010,\"filetime\":-1,\"ssl_verify_result\":0,\"redirect_count\":0,\"total_time\":0.125804,\"namelookup_time\":3.5e-5,\"connect_time\":3.7e-5,\"pretransfer_time\":0.000151,\"size_upload\":112,\"size_download\":42170,\"speed_download\":335203,\"speed_upload\":890,\"download_content_length\":42170,\"upload_content_length\":112,\"starttransfer_time\":0.125545,\"redirect_time\":0,\"redirect_url\":\"\",\"primary_ip\":\"server_ip\",\"certinfo\":[],\"primary_port\":443,\"local_ip\":\"ip_of_my_remote_server\",\"local_port\":39082}
As you can see, the first line (local server) I have some additional infos at the and of the line.
Thanks