cURL Friendships / create, bad authentication data

4

Good with the help of Inkeliz response, this question , I was able to authenticate with Twitter via form.

login.php file :

<?php

require_once '../modules/config.php';
require_once '../modules/class/Cookies.php';

$cookie = [];

$username = trim(filter_input(INPUT_POST, 'username'));
$password = trim(filter_input(INPUT_POST, 'password'));

$index_url = 'https://twitter.com';

$token = curl_init();
curl_setopt_array($token, [
      CURLOPT_URL             => $index_url,
      CURLOPT_CUSTOMREQUEST   => 'GET',
      CURLOPT_RETURNTRANSFER  => true,
      CURLOPT_SSL_VERIFYPEER  => false,
      CURLOPT_SSL_VERIFYHOST  => 2,
      CURLOPT_USERAGENT       => $_SERVER['HTTP_USER_AGENT'],
      //CURLOPT_COOKIEFILE      => __DIR__ . DIRECTORY_SEPARATOR . 'cookies' . DIRECTORY_SEPARATOR . $username . '.txt',
      CURLOPT_COOKIEJAR       => __DIR__ . SEPARATOR . 'cookies' . SEPARATOR . $username . '.txt',
      CURLOPT_COOKIESESSION   => true,
      CURLOPT_REFERER         => $index_url,
      CURLOPT_HEADER          => true,
      CURLOPT_HTTPHEADER      => ['Cookie:' . http_build_query($cookie, '', ';') . ';'],
      CURLOPT_HEADERFUNCTION => function ($curl, $header) use (&$cookie) {
        if (stripos($header, 'Set-Cookie:') === 0) {
          if (preg_match('/Set-Cookie:\s?(.*?)=(.*?);/i', $header, $matches)) {
            $cookie[$matches[1]] = urldecode($matches[2]);
          }
        }
        return strlen($header);
      }
    ]
);    
$access = curl_exec($token);

preg_match('/value="(.*?)" name="authenticity_token"/', $access, $matches);

$authenticity_token = $matches[1];

$session_post = "session[username_or_email]=$username&session[password]=$password&return_to_ssl=true&scribe_log=&redirect_after_login=%2F&authenticity_token=$authenticity_token";

$session_url = 'https://twitter.com/sessions';

curl_setopt_array($token, [
      CURLOPT_URL             => $session_url,
      CURLOPT_CUSTOMREQUEST   => 'POST',
      CURLOPT_POSTFIELDS      => $session_post,
      CURLOPT_RETURNTRANSFER  => true,
      CURLOPT_HTTPHEADER      => [
        "Content-type: application/x-www-form-urlencoded",
        'Cookie: '. http_build_query($cookie, '', ';').';',
      ],
      CURLOPT_USERAGENT       => $_SERVER['HTTP_USER_AGENT'],
      CURLOPT_HEADER          => true,
      CURLOPT_FOLLOWLOCATION  => true,
      CURLOPT_MAXREDIRS       => 2,
      CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
      CURLOPT_POSTREDIR       => 2,
      CURLOPT_AUTOREFERER     => 1
  ]

);
$auth = curl_exec($token);

if (isset($cookie['auth_token']))
{
  $twid = filter_var($cookie['twid'], FILTER_SANITIZE_NUMBER_INT);

  Cookies::set('login_token', $cookie['ct0']);
  Cookies::set('kdt', $cookie['kdt']);
  Cookies::set('user_id', $twid);
  Cookies::set('auth_token', $cookie['auth_token']);
  Cookies::set('username', $username);

  $_SESSION[SITE_TITLE . '_session'] = $username;

  echo json_encode(array(
    "status"      => "success",
    "message"     => "Autenticação bem sucedida, estamos te redirecionando.",
  ));
}
else
{
  echo json_encode(
    array(
      "status" => "error",
      'message'=> "Não foi possível autenticar com o Twitter.",
    ));
}

Notice that we saved two tokens in cookies : auth_token and login_token , being auth_token = $authenticity_token; and login_token = cookie[ct0] , ct0 comes from Twitter. >

The login is ok, then I have cURL to get information from the logged in user, which I was able to do with help of this my question and answered by Anderson Carlos Woss , is also ok, recovery, screen_name , name , foto , among others ...

Now comes my doubt, I know that to use the API needs a token, and I also know that this token is cookie ct0 , but I do not know how to use it, see me code .

File, friend.php

<?php

require_once '../modules/config.php';
require_once '../modules/class/Cookies.php';


$username = Cookies::get('username');

$friend_url = 'https://api.twitter.com/1.1/friendships/create.json';

$friend = curl_init();

curl_setopt_array($friend, [
        CURLOPT_URL             => $friend_url,
        CURLOPT_SSL_VERIFYPEER  => 1,
        CURLOPT_SSL_VERIFYHOST  => 2,
        CURLOPT_CAINFO          => ROOT . 'modules' . SEPARATOR . 'cacert' . SEPARATOR . 'cacert-2017-06-07.pem',
        CURLOPT_CUSTOMREQUEST   => 'POST',
        CURLOPT_POSTFIELDS      => 'screen_name=' . $username,
        CURLOPT_USERAGENT       => $_SERVER['HTTP_USER_AGENT'],
        CURLOPT_COOKIEJAR       => __DIR__ . SEPARATOR . 'cookies' . SEPARATOR . $username . '.txt',
        CURLOPT_COOKIESESSION   => true,
        CURLOPT_RETURNTRANSFER  => true,
        CURLOPT_HTTPHEADER      => [
            "Content-type: application/json; charset=utf-8",
      ],
        CURLOPT_HEADER          => 0,
    ]

);

$response  = curl_exec($friend);

var_dump($response);

Running the code in the browser returns me the error 215 Bad Authentication data .

Good how do I know it's the cookie [ct0] that I should use? Take a look at this question at

EDIT 1

Class Cookie.php

<?php

class Cookies {
    private static $storage = array();

    public static function get($key) {

        if( isset($_COOKIE[$key])) {
            return $_COOKIE[$key];
        } else {
            if(isset(static::$storage[$key])) {
                return static::$storage[$key];
            }

        }
    }

    public static function set($key, $value) {
        static::$storage[$key] = $value;
        setcookie($key, $value, time() + (2 * 3600), '/');
    }

    public static function remove($key, $value) {
        setcookie($key, $value, time()-3600, '/');
    }
}

EDIT 2

As Inkeliz mentioned in the comments the token is in a JS file, and I was able to extract this token , however how should I use it now? Anyone have an idea? See my code:

require_once './system/config.php';

$TwitterUser = null;

if (isset($_SESSION[SITE_TITLE . '_SESSION'])) {
    $TwitterUser = $_SESSION[SITE_TITLE . '_SESSION'];
}

$twitter_url_js = 'https://abs.twimg.com/k/pt/init.pt.8a8c7bc568e38012a94b.js';

$getToken = curl_init();
curl_setopt_array($getToken, [
        CURLOPT_URL                         => $twitter_url_js,
        CURLOPT_CUSTOMREQUEST   => 'GET',
        CURLOPT_RETURNTRANSFER  => true,
        CURLOPT_SSL_VERIFYPEER  => false,
        CURLOPT_SSL_VERIFYHOST  => 2,
        CURLOPT_USERAGENT               => $_SERVER['HTTP_USER_AGENT'],
        CURLOPT_HEADER                  => true,
    ]
);

$token = curl_exec($getToken);

preg_match('/\"([A-z0-9%]{114})\";/', $token, $matches);

$auth_token = $matches[1];

$friend_post = http_build_query([
        'screen_name' => $TwitterUser
    ]
);

$twitter_friend_url = 'https://api.twitter.com/1.1/friendships/create.json';

curl_setopt_array($getToken, [
        CURLOPT_URL                         => $twitter_friend_url,
        CURLOPT_CUSTOMREQUEST       => 'POST',
        CURLOPT_POSTFIELDS          => $friend_post,
        CURLOPT_RETURNTRANSFER  => true,
        CURLOPT_SSL_VERIFYPEER  => false,
        CURLOPT_SSL_VERIFYHOST  => 2,
        CURLOPT_USERAGENT               => $_SERVER['HTTP_USER_AGENT'],
        CURLOPT_HEADER                  => true,
    ]
);

$friend = curl_exec($getToken);

var_dump($friend);

Good with cURL I get this as a response:

'HTTP/1.1 400 Bad Request
content-length: 62
content-type: application/json; charset=utf-8
date: Sun, 16 Jul 2017 23:41:51 GMT
server: tsa_d
set-cookie: guest_id=v1%3A150024851187284588; Domain=.twitter.com; Path=/; Expires=Tue, 16-Jul-2019 23:41:51 UTC
strict-transport-security: max-age=631138519
x-connection-hash: 8c0410547b9456c4ac13f360b8c8dbc3
x-response-time: 132
x-tsa-request-body-time: 0

{"errors":[{"code":215,"message":"Bad Authentication data."}]}' (length=472)

EDIT 3

I've changed some information in HTTP now returns var_dump($friend); :

$twitter_friend_url = 'https://api.twitter.com/1.1/friendships/create.json';

curl_setopt_array($getToken, [
        CURLOPT_URL                         => $twitter_friend_url,
        CURLOPT_CUSTOMREQUEST       => 'OPTIONS',
        CURLOPT_HTTPHEADER          => [
      'Access-Control-Request-Method: POST',
      'Access-Control-Request-Headers: authorization,x-csrf-token,x-twitter-active-user,x-twitter-auth-type',
      'DNT: 1',
      'Origin: https://twitter.com' 
        ], 
        CURLOPT_RETURNTRANSFER  => true,
        CURLOPT_SSL_VERIFYPEER  => false,
        CURLOPT_SSL_VERIFYHOST  => 2,
        CURLOPT_USERAGENT               => $_SERVER['HTTP_USER_AGENT'],
        CURLOPT_HEADER                  => true,
    ]
);

$friend = curl_exec($getToken);

var_dump($friend);
    
asked by anonymous 10.07.2017 / 21:14

1 answer

1

If you monitored the information sent to Twitter then you should have noticed the presence of the authorization , x-csrf-token , x-twitter-active-user and x-twitter-auth-type headers.

All of them are not present in your code.

You need to use something like:

CURLOPT_HTTPHEADER => [
  'origin: https://twitter.com',
  'cookie: ' . $todos_os_cookies_do_twitter,

  'authorization: Bearer ' . $auth_token,
  'x-csrf-token: ' . $ct0,

  'x-twitter-auth-type: OAuth2Session',
  'x-twitter-active-user: yes',

  'referer: https://twitter.com',
]

Considering that $ct0 is the value of the cookie with the name of ct0 .

While the $auth_token is the token that is "embedded" inside JS (could use preg_match('/\"([A-Z0-9%]{114})\";/i', $token, $matches); , which is what it is using in the code).

$todos_os_cookies_do_twitter is all the cookies you have on Twitter.

This authorization apparently always starts with AAAAAAAAAAAAAAAAAAAAA , which makes it easy to find it% in JS .

In addition to clear you must make the request as POST and not OPTIONS . OPTIONS is used as prefight . Then you should use CURLOPT_CUSTOMREQUEST => 'POST' or CURLOPT_POST => 1 .

Then you need to set CURLOPT_POSTFIELDS to data, which you test differently in your code. In case use exactly as Twitter uses, that is:

    CURLOPT_POSTFIELDS => http_build_query(
        ['challenges_passed' => false,
        'handles_challenges' => 1,
        'include_blocked_by' => true,
        'include_blocking' => true,
        'include_can_dm' => true,
        'include_followed_by' => true,
        'include_mute_edge' => true,
        'skip_status' => true,
        'user_id' => $id_twitter_quem_quer_seguir
    ], '', '&', PHP_QUERY_RFC3986),

I do not know what the variables indicate except the last user_id which is who you want to follow, for example I used 83430421 , in fact the $id_twitter_quem_quer_seguir must be the user ID that will receive the follower.

Also make sure $auth_token is correct.

    
19.07.2017 / 17:01