Sign-in with Twitter in a Silex application.


I’ve working in a pet-project with Silex and I wanted to perform a Sign-in with Twitter. Implementing Sign in with Twitter is pretty straightforward and it’s also well explained in the Twitter’s developers site. Now we only need to implement those HTTP client requests within PHP. We can create the REST client with curl but nowadays I prefer to use the great library called Guzzle to perform those kind of opperations. So let’s start.

The idea is to create something reusable. I don’t want to spend too much time including the Sign-in with Twitter in my proyects, so my first idea was to create a class with all the needed code and mount this class as group of Silex controllers (as it’s defined here). I also want to keep the class as standard as possible and avoiding the usage of any other external dependencies (except Guzzle)..

Imagine a simple Silex application:

<?php
// www/index.php
include __DIR__ . "/../vendor/autoload.php";

$app = new Silex\Application();
$app->get('/', function () {
    return 'Hello';
});

$app->run();

Now I want to use a Sign-in with Twitter, so I will change the application to:

<?php
include __DIR__ . "/../vendor/autoload.php";

$app = new Silex\Application();
$app->register(new Silex\Provider\SessionServiceProvider());

$consumerKey    = "***";
$consumerSecret = "***";

$twitterLoggin = new SilexTwitterLogin($app, 'twitter');
$twitterLoggin->setConsumerKey($consumerKey);
$twitterLoggin->setConsumerSecret($consumerSecret);
$twitterLoggin->registerOnLoggin(function () use ($app, $twitterLoggin) {
    $app['session']->set($twitterLoggin->getSessionId(), [
        'user_id'            => $twitterLoggin->getUserId(),
        'screen_name'        => $twitterLoggin->getScreenName(),
        'oauth_token'        => $twitterLoggin->getOauthToken(),
        'oauth_token_secret' => $twitterLoggin->getOauthTokenSecret()
    ]);
});

$twitterLoggin->mountOn('/login', function () {
    return '<a href="/login/requestToken">login</a>';
});

$app->get('/', function () use ($app){
    return 'Hello ' . $app['session']->get('twitter')['screen_name'];
});

$app->run();

The application will redirects all requests (without the correct session) to the route “/login”. The login page has a simple link to the route: “/login/requestToken” (we can create a fancy template with Twig if we want, indeed). This route redirects the request to Twitter’s login page and after a successful login it will redirects back to the route that we have defined within our Twitter application. The library assumes that this callback’s url is “/login/callbackUrl”. All this default routes can be defined by the user using the proper setters of the class.

When the sign-in is finished the application will trigger the callback defined in registerOnLoggin function and will redirects to the route “/”. This route (called internally “redirectOnSuccess”) is also customizable with a setter.

And that’s all. Library available at github and packagist

{
    "require": {
        "gonzalo123/silex-twitter-login": "dev-master"
    }
}
About these ads

About Gonzalo Ayuso

Web Architect specialized in Open Source technologies. PHP, Python, JQuery, Dojo, PostgreSQL, CouchDB and node.js but always learning.

Posted on March 18, 2013, in php, silex, Technology and tagged , , , , . Bookmark the permalink. 6 Comments.

  1. Hi, i’m using this piece of code in my Silex-application. The redirect to the twitter form is working ok. However, when coming back from twitter i get this error:
    “Client error response [status code] 401 [reason phrase] Unauthorized [url] https://api.twitter.com/oauth/access_token
    How can this be solved?

    • Ensure that you are using the latest version from github. this issue is solved.

      • i’m using the dev-master version using composer. I’m still getting the error. Will continue to investigate…

      • still can’t get it to work… I’m using the dev-master version of guzzle.
        The entire error message is:
        Whoops, looks like something went wrong.

        1/1ClientErrorResponseException: Client error response
        [status code] 401
        [reason phrase] Unauthorized
        [url] https://api.twitter.com/oauth/access_token
        in //vendor/guzzle/guzzle/src/Guzzle/Http/Exception/BadResponseException.php line 46
        at BadResponseException::factory(object(EntityEnclosingRequest), object(Response)) in //vendor/guzzle/guzzle/src/Guzzle/Http/Message/Request.php line 190
        at Request::onRequestError(object(Event))
        at call_user_func(array(‘Guzzle\Http\Message\Request’, ‘onRequestError’), object(Event)) in //vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php line 164
        at EventDispatcher->doDispatch(array(array(‘Guzzle\Http\Message\Request’, ‘onRequestError’)), ‘request.error’, object(Event)) in //vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php line 53
        at EventDispatcher->dispatch(‘request.error’, object(Event)) in //vendor/guzzle/guzzle/src/Guzzle/Http/Message/Request.php line 785
        at Request->processResponse(array(‘handle’ => object(CurlHandle))) in //vendor/guzzle/guzzle/src/Guzzle/Http/Message/Request.php line 472
        at Request->setState(‘complete’, array(‘handle’ => object(CurlHandle))) in //vendor/guzzle/guzzle/src/Guzzle/Http/Message/EntityEnclosingRequest.php line 66
        at EntityEnclosingRequest->setState(‘complete’, array(‘handle’ => object(CurlHandle))) in //vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlMulti.php line 359
        at CurlMulti->processResponse(object(EntityEnclosingRequest), object(CurlHandle), array(‘msg’ => ’1′, ‘result’ => ’0′, ‘handle’ => ‘Resource id #12′)) in //vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlMulti.php line 284
        at CurlMulti->processMessages() in //vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlMulti.php line 245
        at CurlMulti->perform() in //vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlMulti.php line 140
        at CurlMulti->send() in //vendor/guzzle/guzzle/src/Guzzle/Http/Curl/CurlMultiProxy.php line 105
        at CurlMultiProxy->send() in //vendor/guzzle/guzzle/src/Guzzle/Http/Client.php line 396
        at Client->send(object(EntityEnclosingRequest)) in //vendor/guzzle/guzzle/src/Guzzle/Http/Message/Request.php line 263
        at Request->send() in //vendor/gonzalo123/silex-twitter-login/lib/SilexTwitterLogin.php line 108
        at SilexTwitterLogin->{closure}()
        at call_user_func_array(object(Closure), array()) in //vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpKernel.php line 129
        at HttpKernel->handleRaw(object(Request), ’1′) in //vendor/symfony/http-kernel/Symfony/Component/HttpKernel/HttpKernel.php line 73
        at HttpKernel->handle(object(Request), ’1′, true) in //vendor/silex/silex/src/Silex/Application.php line 504
        at Application->handle(object(Request)) in //vendor/silex/silex/src/Silex/Application.php line 481
        at Application->run() in //public_html/index.php line 207

  2. Fixed it, my .htaccess url rewrite didn’t process get-parameters correctly.

    Changing
    RewriteRule (.*) /index.php?param=$1 [L]
    to
    RewriteRule (.*) /index.php?param=$1 [QSA,L]
    fixed the problem.

    • cool! I had a small nightmare when twitter updated the api (that’s because I said to ensure that you are using the last version) and afaik it works now (until the api change again as usual :) )

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 998 other followers

%d bloggers like this: