Sunday, November 20, 2011

Twitter @Anywhere and PHP Symfony. Implementing login action

While playing with the Twitter @Anywhere and PHP Symfony I have implemented "Sign in with Twitter" method for RoundTeam app (http://roundteam.co).

How it was done:

Creating a placeholder to represent "Sign in with Twitter" button.
mainpageSuccess.php:
<span id="login" class="twit_login">Sign in with Twitter</span>
I am not going to describe CSS part here.

Enabling Twitter connection using @Anywhere
javascript (rt.js):
$(document).ready(function() {
    twttr.anywhere(function(T) {
        $("#login").bind('click', function () {
            T.signIn();
        });
    }
Now when user clicks on "Sign in with Twitter" button he will be prompted to login using Twitter credentials. On this step "twitter_anywhere_identity" cookie is created (more details about this cookie and how to interpret it on server side see here: https://dev.twitter.com/docs/anywhere/welcome).

Okay, now we need to notify server that login has happened.
Here is one of the ways to implement this using PHP Symfony:

routing.yml
rt_get_user:
  url: /rt/user
  param: {module: connect, action: user}

action.class.php (for module "connect"):
public function executeUser(sfWebRequest $request) {
$cookie = $request->getCookie('twitter_anywhere_identity');
$this->logMessage('got auth request');
if ($cookie) {
$twitter_data = explode(':', $cookie);
$userId = $twitter_data[0];
$secret = $twitter_data[1];
$calculatedSecret = sha1($userId.RoundTeam_auth::SECRET);

if ($secret === $calculatedSecret) {
$this->logMessage('secret verified');
$userJson = $request->getParameter('user');
if ($userJson) {
$this->logMessage('user found!');
$user = json_decode($userJson);

$this->data = $user;

$this->logMessage($userJson);

$screenName = $this->data->screenName;
if (TeamTable::getInstance()->exists($screenName) == false) {
$this->logMessage('authenticated: '.$screenName);
$this->getUser()->signIn($this->data);
} else {
$this->logMessage('Failed to login using team: '.$this->$screenName, 'err');
}
} else {
$this->logMessage('user not found');
}
}
}
$this->redirect('@rt');
}

The last step is to post user data to server and reload page:

T.bind("authComplete", function (e, user) {
        post('rt/user', {user: JSON.stringify(user)}, function(response) {
        location.reload();
    });
});

That's it. Now user may login using his twitter credentials without leaving the round-team.com page. User data is passed to server and server authenticates user to enter.

It means that user stays logged in on both client side and server side. That said when you implement logout don't forget to log out user from server side:
$this->getUser()->setAuthenticated(false);
and client side:
twttr.anywhere.signOut();

Complete js code listing may be found on http://round-team.com

No comments:

Post a Comment