Implementing Twitter sign-in with Silex and PHP
Set-up
- Install pecl oauth
- Grab the Silex
.phararchive - 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
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('/');
});