How to Integrate Twitter OAuth 2.0 in PHP + (Regenerate Access Token using OAuth 2.0)

Do you want to integrate Twitter OAuth 2.0 into your application? While interacting with Twitter API 2, you need to deal with OAuth 2.0. In this tutorial, I’ll show you how to use Twitter OAuth 2.0 with PHP on your website.

Twitter comes with 2 authentication methods – OAuth 1.0a and OAuth 2.0. I already wrote an article on using OAuth 1.0a with Twitter.

How Twitter OAuth 2.0 Works?

In Twitter OAuth 2.0, you need to build a login flow and grab the access token upon successful authorization. This access token then acts as an identifier of the user account. You don’t need to ask the user to repeat the login flow again. With the access token, you can perform specific operations based on the scopes you requested during authentication.

One important thing you should know is the access token cannot be used forever. It has a certain lifespan, after which it expires. And once expired your API requests will not be succeeded. To catch this scenario, you have to regenerate the access token using the refresh token. We’ll write the code which handles the expired access token and regenerate it.

Database Configuration

As we are going to build the OAuth 2.0 flow, it needs to store the token information in the database. Create the twitteroauth table using the below SQL.

CREATE TABLE `twitteroauth` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `provider` varchar(255) NOT NULL,
  `provider_value` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

In the application, it needs to interact with the database for the following purposes.

  • Insert or update the token information
  • Fetch the access token
  • Fetch the refresh token

I am creating a class-db.php file and including a few functions to handle this stuff.

class-db.php

<?php
class DB {
    private $dbHost     = "DB_HOST";
    private $dbUsername = "DB_USERNAME";
    private $dbPassword = "DB_PASSWORD";
    private $dbName     = "DB_NAME";
 
    public function __construct(){
        if(!isset($this->db)){
            // Connect to the database
            $conn = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName);
            if($conn->connect_error){
                die("Failed to connect with MySQL: " . $conn->connect_error);
            }else{
                $this->db = $conn;
            }
        }
    }
 
    public function is_table_empty() {
        $result = $this->db->query("SELECT id FROM twitteroauth WHERE provider = 'twitter'");
        if($result->num_rows) {
            return false;
        }
 
        return true;
    }
 
    public function get_access_token() {
        $sql = $this->db->query("SELECT provider_value FROM twitteroauth WHERE provider = 'twitter'");
        $result = $sql->fetch_assoc();
        return json_decode($result['provider_value']);
    }
 
    public function get_refersh_token() {
        $result = $this->get_access_token();
        return $result->refresh_token;
    }
 
    public function update_access_token($token) {
        if($this->is_table_empty()) {
            $this->db->query("INSERT INTO twitteroauth(provider, provider_value) VALUES('twitter', '$token')");
        } else {
            $this->db->query("UPDATE twitteroauth SET provider_value = '$token' WHERE provider = 'twitter'");
        }
    }
}

Install Guzzle Library

You can test Twitter OAuth 2.0 on a local server. For a demo purpose, create a directory twitteroauth on your local PHP setup say XAMPP. Inside this directory, run the below composer command which installs the Guzzle package.

composer require guzzlehttp/guzzle

The Guzzle package is used to send HTTP Requests to the API endpoint. It also handles the API response.

Upon package installation, create a few PHP files that will be required to build our demo.

  • config.php : To store a few values as PHP constants.
  • login.php : It initiates the Twitter login flow for authentication purposes.
  • index.php : Callback or Redirect URL. Twitter redirects the user to this URL after their authentication.
  • get-user.php : In this file, we’ll write a code to fetch user details by passing the access token in the header Authorization.

OAuth 2.0 Client ID and Client Secret

To initiate the OAuth 2.0 authentication, you need to grab your client ID and client secret. Follow the below steps to acquire these values:

  • Sign up for a Twitter developer account.
  • Create a Twitter App within a developer portal.
  • Make sure you add a Twitter App to a Project. It’s compulsory for OAuth 2.0.
  • On User authentication settings, set a Redirect URL to http://localhost/twitteroauth/index.php
  • Copy your client ID and client secret.
twitter-oauth-keys

Next, to your config.php add these values as PHP constants. Also, include the database configuration and package environment.

config.php

<?php
require_once "vendor/autoload.php";
require_once "class-db.php";

define("CLIENT_ID", "");
define("CLIENT_SECRET", "");
define("REDIRECT_URL", "http://localhost/twitteroauth/index.php");

Initiate Login Flow and Store Token Information

Before initiating a login flow, you have to first build the authorization URL. This URL needs a few parameters which will be verified on the Twitter end. These parameters include client_id, scopes, redirect_url, state, and code_challenge.

The scopes parameter has values you’re asking users to approve – read tweets, write tweets, etc. 

The state and code_challenge will have a random string that should be verified at your application end. We’ll verify it in the redirect URL(index.php). Twitter sends back these parameters to cross-check if it’s the same request that one initiated.

The following code will go inside the login.php file.

<?php
session_start();
require_once 'config.php';

$client_id = CLIENT_ID;
$redirect_uri = REDIRECT_URL;
$scopes = "tweet.read users.read like.write tweet.write offline.access"; // adjust scopes as per your needs

$state = $_SESSION['state'] = uniqid();
$challenge = $_SESSION['challenge'] = uniqid();

$twitter_login_url = "https://twitter.com/i/oauth2/authorize?response_type=code&client_id=$client_id&redirect_uri=$redirect_uri&scope=$scopes&state=$state&code_challenge=$challenge&code_challenge_method=plain";
?>

<a href="<?php echo ($twitter_login_url); ?>">Login with Twitter</a>

Keep a note I passed the offline.access to the scopes variable. When this scope is set, Twitter provides you with the refresh token. Using this refresh token, we will regenerate the access token in the background.

Let’s write the code to send a request for the access token, receive the response, and store it in the database.

index.php

<?php
session_start();
require_once 'config.php';

if ( array_key_exists('state', $_GET) && ( $_GET['state'] == $_SESSION['state'] ) ) {
    if ( array_key_exists('code', $_GET) ) {
        $client = new GuzzleHttp\Client([
            'base_uri' => 'https://api.twitter.com',
        ]);

        try {
            // get access token
            $response = $client->request('POST', '/2/oauth2/token', [
                "form_params" => [
                    "grant_type" => "authorization_code",
                    "code" => $_GET['code'],
                    "client_id" => CLIENT_ID,
                    "redirect_uri" => REDIRECT_URL,
                    "code_verifier" => $_SESSION['challenge'],
                ],
            ]);
        
            $res = json_decode($response->getBody());

            $db = new DB();
            $db->update_access_token(json_encode($res));
            echo "Access token inserted successfully.";
        } catch(Exception $e) {
            echo $e->getMessage();
        }
    }
} else {
    echo "Something went wrong. Try again later.";
}

Now, you can run the login.php on the browser. Click on the login link, complete the authentication and your token details should be inserted into the database.

Get User Details with OAuth 2.0

We got the access token and can now interact with the Twitter API using OAuth 2.0. As I stated earlier, to each API request we must pass the access token so Twitter identifies the user and performs the operation. This access token will be sent as in Header Authorization.

I am taking an example of fetching user details from Twitter who have authenticated. I’ll wrap the code inside the try/catch block. This is because the control will jump to the catch block once the access token is expired. Twitter returns the 401 status code for the expired access token. Inside the catch block, we’ll regenerate the access token and update it in the database. This operation would perform in the background and without breaking the application.

get-user.php

<?php
require_once 'config.php';

get_user_details();

function get_user_details() {
    $db = new DB();
    $arr_token = (array) $db->get_access_token();
    $access_token = $arr_token['access_token'];

    try {
        // get user details
        $client = new GuzzleHttp\Client([
            'base_uri' => 'https://api.twitter.com',
        ]);

        $response = $client->request('GET', '/2/users/me', [
            "headers" => [
                "Authorization" => "Bearer ". $access_token
            ]
        ]);

        $res = json_decode($response->getBody()); // print_r($res);
        $id = $res->data->id;
        echo "<p>Twitter User ID: $id</p>";
    } catch(Exception $e) {
        if (401 == $e->getCode()) {
            $refresh_token = $db->get_refersh_token();

            $response = $client->request('POST', '/2/oauth2/token', [
                'form_params' => [
                    "grant_type" => "refresh_token",
                    "refresh_token" => $refresh_token,
                    "client_id" => CLIENT_ID,
                ],
            ]);

            $db->update_access_token($response->getBody());
            
            get_user_details();
        }
    }
}

Run this file on the browser and you should see the user details. To test if OAuth 2.0 is working correctly, run this file frequently at intervals of 2 hours.

It’s all about integrating Twitter OAuth 2.0 using PHP. I hope you understand and can easily include it in your project. Please share your thoughts and suggestions in the comment below.

Related Articles

If you liked this article, then please subscribe to our YouTube Channel for video tutorials.

Leave a Reply

Your email address will not be published. Required fields are marked *