Aug 15 2011

Implementing Twitter sign-in with Silex and PHP

Set-up

  • Install pecl oauth
  • Grab the Silex .phar archive
  • Create a Twitter application

pecl oauth

Install the pecl oauth extension

For example:

$ pecl install oauth

Silex

For those not acquainted with Silex:

Silex is a PHP microframework for PHP 5.3

A microframework provides the guts for building simple single-file apps.

It's awesome.

All you need is the silex.phar file and you're away. Download it.

For the example, I've setup a virtual host of example.local on my development machine. The apache module mod_rewrite and a .htaccess file are used to rewrite requests to index.php.

# .htaccess
<IfModule mod_rewrite.c>
    Options -MultiViews

    RewriteEngine On
    #RewriteBase /path/to/app
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

Create a Twitter application

Create a Twitter app

Once you've created your application, you'll need your consumer key and consumer secret. These are used to sign every request made to the API.

Implementation

A complete summary along with a pretty diagram of what we're trying to achieve can be found here.

Basic OAuth request cycle:

  • Retrieve a request token
  • Request authorization
  • Exchange the request token for an access token

More information - https://dev.twitter.com/docs/auth/oauth

Basic Silex application

// index.php
define('CONS_KEY', 'Application consumer key');
define('CONS_SECRET', 'Application consumer secret');

require_once __DIR__.'/silex.phar'; 

$app = new Silex\Application(); 

// register the session extension
$app->register(new Silex\Extension\SessionExtension());

$app->get('/', function() use($app) { 
    $username = $app['session']->get('username');

    if ($username == null) {
        return 'Welcome Guest. <a href="/login">Login</a>'; 
    } else {
        return 'Welcome ' . $app->escape($username);
    }
}); 

$app->run(); 

Add the /login route

The first part of the process requires the retrieval of a request token. Authorization is requested by redirecting to https://twitter.com/oauth/authenticate.

// index.php
$app->get('/login', function () use ($app) {
    // check if the user is already logged-in
    if (null !== ($username = $app['session']->get('username'))) {
        return $app->redirect('/');
    }

    $oauth = new OAuth(CONS_KEY, CONS_SECRET, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
    $request_token = $oauth->getRequestToken('https://twitter.com/oauth/request_token');

    $app['session']->set('secret', $request_token['oauth_token_secret']);

    return $app->redirect('https://twitter.com/oauth/authenticate?oauth_token=' . $request_token['oauth_token']);
});

Add the /auth route

In my example setup the URL would be http://example.local/auth. Set your Twitter application callback URL in the app settings to be the auth route.

Within this action, the request token is exchanged with the access token which allows usage of the Twitter API on behalf of the user.

// index.php
$app->get('/auth', function() use ($app) {
    // check if the user is already logged-in
    if (null !== ($username = $app['session']->get('username'))) {
        return $app->redirect('/');
    }

    $oauth_token = $app['request']->get('oauth_token');

    if ($oauth_token == null) {
        $app->abort(400, 'Invalid token');
    }

    $secret = $app['session']->get('secret');

    $oauth = new OAuth(CONS_KEY, CONS_SECRET, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
    $oauth->setToken($oauth_token, $secret);

    try {
        $oauth_token_info = $oauth->getAccessToken('https://twitter.com/oauth/access_token');
    } catch (OAuthException $e) {
        $app->abort(401, $e->getMessage());
    }

    // retrieve Twitter user details
    $oauth->setToken($oauth_token_info['oauth_token'], $oauth_token_info['oauth_token_secret']);
    $oauth->fetch('https://twitter.com/account/verify_credentials.json');
    $json = json_decode($oauth->getLastResponse());

    $app['session']->set('username', $json->screen_name);

    return $app->redirect('/');
});

Resources

comments powered by Disqus

Info

I'm Ade Slade, a PHP web developer.