-1

I am trying to use php curl to get the login token from an external webpage but the login token I'm receiving is different from the actual one.

Could someone please tell me what I'm missing.

$ch = curl_init();
url_setopt($ch, CURLOPT_URL, "https://grprek.jeddahknowledgeschool.com/login/index.php");
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, "");
$answer = curl_exec($ch);
echo $answer;

if (curl_error($ch)) {
    echo curl_error($ch);
}
?>
<form  action="<?php echo $virtualLink; ?>" method="post" target="_new" id="login" >
           
    <input name="logintoken" type="hidden" value="<?php echo $vlLoginToken;?>" />
    <input style="background-color: transparent;" id="username" name="username" type="hidden" value="<?php echo $username;?>" >
    <input id="password" name="password" type="hidden" value="<?php echo $vlPassword;?>">
    <input style=" width:100px; height:100px;  margin-right:auto; margin-left:auto; display:block; border:none; background-color: transparent;" 
        src="" 
        type="image" 
        alt="turnitin" 
        title="turnitin">
</form>
</td>

RiggsFolly
  • 93,638
  • 21
  • 103
  • 149
Haya
  • 19
  • 5
  • In your `cURL` request, you have set `CURLOPT_POST` to `false`, which means you are making a `GET` request instead of a `POST` request. If you want to simulate a form submission to retrieve a login token, you should set `CURLOPT_POST` to `true`. – f05135 Aug 31 '23 at 16:09
  • I tried changing it to true. Still the token I’m receiving is different. – Haya Aug 31 '23 at 16:16
  • As I understand it, this is a follow up question of: https://stackoverflow.com/questions/77013279/file-get-contents-in-php-to-get-login-token?noredirect=1#comment135772339_77013279 – KIKO Software Aug 31 '23 at 16:18
  • The login token is probably associated with the session of the user. In one case PHP is the user, in the other case your browser. These will have different session and hence different login tokens. – KIKO Software Aug 31 '23 at 16:24
  • But with the login token I’m receiving using curl I get: invalid login, and when I copy the login token manually from the browser and submit it with my form I can login – Haya Aug 31 '23 at 16:28
  • If you are receiving an `invalid login` error when using the login token obtained via cURL, but it works when you manually copy the token from the browser, it's likely that the login token you are fetching via cURL is not correctly generated or is missing some required information. – f05135 Aug 31 '23 at 16:30
  • 2
    Try to enable cookie handling in your cURL request using `CURLOPT_COOKIEJAR` and `CURLOPT_COOKIEFILE`. – f05135 Aug 31 '23 at 16:31
  • It's definetly something related to **Session** or **Cookie Handling**, because when you manually copy the login token from the browser and submit it with your form, the browser might be handling some session-related information or cookies that are not being managed by your `cURL` request – f05135 Aug 31 '23 at 16:34
  • A possible reason for receiving a different login token could be that the server might be using cookies to store session information. When you log in via a browser, the server sets a cookie with your session information, which is then sent back to the server on subsequent requests. This allows the server to recognize that you are logged in and provide you with the correct login token... – esQmo_ Aug 31 '23 at 16:35
  • Could someone please provide a sample code on how to use COOKIEJAR and COOKIEFILE in this case to achieve what I want? – Haya Aug 31 '23 at 16:41
  • TYPO = `url_setopt(` And there are to many unknowns in this code! EG `$vlLoginToken` and `$vlPassword` etc – RiggsFolly Aug 31 '23 at 16:44
  • That CURL when Un-Typo'd returns the source for a web page. So how are you getting a token out of all that HTML & JS – RiggsFolly Aug 31 '23 at 17:04
  • The login token is a hidden field in the login form in the webpage I’m loading. So when I load this page it’s there – Haya Aug 31 '23 at 17:26
  • Maybe if you add the code that pulls the token from the HTML we could see an issue – RiggsFolly Aug 31 '23 at 18:11
  • It looks like you hope to parse the HTML from the curl request and use the discovered `logintoken` within a regular HTML form. The request made from the regular form will essentially be a completely new request unless you set a cookie containing values from original curl cookiejar. In some ways it would be easier to do the POST request using curl immediately after loading the HTML and finding the token rather than set that cookie for the browser and then do the POST – Professor Abronsius Aug 31 '23 at 19:31
  • Makes much sense. Could you please provide a sample code I can try? – Haya Aug 31 '23 at 20:01

1 Answers1

0

Using a fairly basic and re-usable function below to make the curl requests you would initially perform a GET request to begin the session. The initial GET request is used to discover and store the cookies used and to parse the HTML to find the logintoken from the form.

You use DOMDocument/DOMXpath to process the HTML and find the token. That discovered token will then be used to create the POST request - ie: the login.

function curl( $url=null, $options=null ){
    /*
        Download a copy of CACERT.pem from
        https://curl.haxx.se/docs/caextract.html
        and edit path below
    */
    $cacert='c:/wwwroot/cacert.pem';
    
    $curl=curl_init();
    if( parse_url( $url, PHP_URL_SCHEME )=='https' ){
        curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, true );
        curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, 2 );
        curl_setopt( $curl, CURLOPT_CAINFO, $cacert );
    }
    curl_setopt( $curl, CURLOPT_URL, trim( $url ) );
    curl_setopt( $curl, CURLOPT_AUTOREFERER, true );
    curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, true );
    curl_setopt( $curl, CURLOPT_FAILONERROR, true );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $curl, CURLOPT_CONNECTTIMEOUT, 20 );
    curl_setopt( $curl, CURLOPT_TIMEOUT, 60 );
    curl_setopt( $curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' );
    curl_setopt( $curl, CURLOPT_MAXREDIRS, 10 );
    curl_setopt( $curl, CURLOPT_ENCODING, '' );
    
    # add runtime options
    if( isset( $options ) && is_array( $options ) ){
        foreach( $options as $param => $value ) {
            curl_setopt( $curl, $param, $value );
        }
    }
    $res=(object)array(
        'response'  =>  curl_exec( $curl ),
        'status'    =>  curl_getinfo( $curl, CURLINFO_RESPONSE_CODE )
    );
    curl_close( $curl );
    
    return $res;
}



# create a temporary file to hold cookie data used by subsequent curl requests.
$cookiejar=tempnam( sys_get_temp_dir(), '_cookiejar_' );

# Target endpoint - initially loaded using GET to find cookies and parse the HTML to find the logintoken
$url='https://grprek.jeddahknowledgeschool.com/login/index.php';

# options used to make GET request. 
# Cookie data will be saved to $cookiejar when curl_close() is called.
$options=array(
    CURLOPT_COOKIESESSION   =>  true,
    CURLOPT_COOKIEJAR       =>  $cookiejar
);

# make the request and proceed if it succeeds
$res=curl( $url, $options );
if( $res->status==200 ){
    
    # The POST parameters to send. 
    # "logintoken" will be added below!
    $args=array(
        'username'      =>  'xxx',
        'password'      =>  'xxx'
    );
    
    
    # Load the HTML to find logintoken
    libxml_use_internal_errors( true );
    $dom = new DOMDocument;
    $dom->loadHTML( $res->response );
    libxml_clear_errors();
    
    
    #create an XPath to query the DOM and find INPUT elements within the form
    $xp=new DOMXPath( $dom );
    $expr='//form[ @class="login-form" ]//input';
    $col=$xp->query( $expr );
    
    # If the XPath succeeded, grab the name/value and assign as login arguments
    if( $col && $col->length > 0 ){
        # iterate through discovered inputs, add name/value to args array.
        # do not overwrite known values of username/password ( if known of course )
        # This is where the "logintoken" is added!
        foreach( $col as $node ){
            if( !array_key_exists( $node->getAttribute('name'), $args ) ){
                $args[ $node->getAttribute('name') ]=$node->getAttribute('value');
            }
        }
        
        # create the curl options for the POST request.
        # use the cookie but do not start new cookie session.
        $options=array(
            CURLOPT_COOKIESESSION   =>  false,
            CURLOPT_COOKIEFILE      =>  $cookiejar,
            CURLOPT_POST            =>  true,
            CURLOPT_POSTFIELDS      =>  http_build_query( $args )
        );
        
        # make the curl request...
        $res=curl( $url, $options );
        if( $res->status==200 ){
            # Can progress no further or identify any errors beyond this point due to no valid credentials.
            # so simply print out HTML response that shows "Invalid login, please try again"
            # If the login succeeds then there will be different displayed HTML presumably.
            printf(
                '<pre>%s</pre>',
                print_r( $res->response, true )
            );
            
            
            #interested in seeing cookie?
            printf('<pre>%s</pre>',file_get_contents($cookiejar));
            
            # after all processing... erase cookie?
            unlink( $cookiejar );
        }else{
            printf( 'POST request failed with code: %s', $res->status );
        }
    }
}else{
    printf( 'GET request failed with code: %s', $res->status );
}
Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
  • This is great! thanks for the effort. I tried it. I could login but the login is happening in the same page I'm in. What I want is to login on a new page with a click of a button (or form submission). I tried getting the logintoken from $args, but login failed as the token is again different from the one in the browser – Haya Sep 01 '23 at 20:29