facebook API authentication in symfony using sfGuard

Posted by Mark on 2007-09-28 in , , - no comments

Updated: The controller code that called the facebook API to insert the users first and last name was not correct. This has been updated.

Leveraging facebooks API to bring you users is a useful technique. As of this date, I haven't seen any plugins to automatically handle logging into an existing symfony application using facebook, so I did some integration work to make it possible. I may roll this up into a plugin at a later date, but time doesn't allow for that at the moment (if you want to do it yourself, then let me know and I'll give you any help I can)

Standard disclaimer applies - I've not yet significantly tested this code and it may eat your hamster.

Requirements

First, install sfGuardPlugin as described in their instructions. You'll also want to create a profile table with a couple of extra fields for facebook. If you're using an XML schema, your table declaration should look like this :

    <table name="sf_guard_user_profile" phpName="sfGuardUserProfile">
      <column name="id" type="integer" autoIncrement="true" primaryKey="true" />
      <column name="user_id" type="integer" required="true" />
      <foreign-key foreignTable="sf_guard_user">
        <reference local="user_id" foreign="id"/>
      </foreign-key>
      <column name="first_name" type="varchar" size="255" />
      <column name="last_name" type="varchar" size="255" />
      <column name="facebook_user_id" type="integer" />
      <column name="facebook_key" type="varchar" size="255" />
    </table>  
  

first_name and last_name are optional. If you decide not to use these, then you'll need to remove lines later on that populate these fields from the facebook API. You could also add other fields that are available from the facebook api for which the field list is available here.

Once sfGuard is installed and working (you should be able to log in as the admin user), you'll need to install the facebook PHP API client and place the PHP files included inside into your projects /lib directory. I also had to rename the facebook.php file Facebook.php otherwise symfonys classloader wouldn't recognise it. Your mileage may vary.

Extending sfGuard to use facebook

In order to extend sfGuard in your application, you need to create a sfGuardAuth module to override settings within the original sfGuardAuth application in the plugin. You can do this with the command line

    symfony init-module <your-application-name-here> sfGuardAuth
  

Once you've done this, remove the executeIndex method from the actions.class.php that is generated and the indexSuccess.php template. You'll need to copy some files from the plugin directly into the same place in your new module directory :

    plugins/sfGuardPlugin/modules/sfGuardAuth/config/security.yml
    plugins/sfGuardPlugin/modules/sfGuardAuth/templates/signinSuccess.php
  

Edit security.yml to add this at the end - this allows people who are not signed in to access the facebooksignin action

    facebooksignin:
      is_secure: off
  

You will also need to add both facebook_api_key and facebook_secret keys to your settings.yml containing your api key and secret.

Now add the following code into your new actions class :

    /**
     * executeFacebooksignin - log in using a facebook account
     *
     * @return void
     * @author Mark Ng
     **/
    public function executeFacebooksignin()
    {
      // force a facebook login
      $facebook = new Facebook(sfConfig::get('sf_facebook_api_key'),sfConfig::get('sf_facebook_secret'));
      $fbUserId = $facebook->require_login();

      $profile = sfGuardUserProfilePeer::retrieveByFacebookUserId($fbUserId);
      // check if a user profile exists with that facebook ID
      if ($profile instanceof sfGuardUserProfile)
      {
        $user = $profile->getSfGuardUser();
      }
      else
      {
        // no user with that facebook account, so make one
        $user = new sfGuardUser();
        $user->setUsername('facebook:'.$fbUserId);
        $user->save();
        $profile = $user->getProfile();
        $profile->setFacebookUserId($fbUserId);
      }
      // update these, as they could have changed and are not immutable
      $profile->setFacebookKey($facebook->api_client->session_key);
      $userinfo = $facebook->api_client->users_getInfo($facebook->user,array('first_name','last_name'));
      $profile->setFirstName($userinfo[0]['first_name']);
      $profile->setLastName($userinfo[0]['last_name']);
      $user->save();
      $profile->save();

      // sign the user in
      $this->getContext()->getUser()->signIn($user);

      $this->redirect('/');
    }
    
  

You may want to change the way that the username is assigned. If your application allows the : character in usernames, someone could possibly cause security mischief. You'll need to find some other way of assigning a facebook user a unique username in your system.

Then add a link to your signinsuccess.php template, to show a link to this action to log in to facebook something like this :

    <?php echo link_to('Sign in with your facebook account', 'sfGuardAuth/facebooksignin') ?>
  

And you should now be able to log in via facebook (after you've set your callback url in your facebook application).

I wrote this article directly after hacking this together for an application I was working on. If you find it doesn't work, it's likely that I've missed something. Please contact me via the contact section of the site and I'll help you fix it (and amend this page).

wedding part 2

Posted by Mark on 2007-08-14 - no comments
My friend Jon Lim has published his photos from our wedding on flickr. Jon got some really good pictures - thanks !

Tigerapex Cars and my bad experience

Posted by Mark on 2007-08-10 - one comment

Updated 13/11/2007: After Richard from tigerapex called me and threatened (and I quote) to "take you for every penny you've got", amongst other threats, I contacted a solicitor who recommended some small changes to this page. The facts remain, unchanged, but some opinions that I hold regarding the integrity of Tigerapex and it's directors have been removed.

In January of this year, I bought a Renault Laguna from Tigerapex in Birmingham. In my past, I have had some bad credit history due to my first attempt at starting my own business. I had previously visited "Yes car finance" and found that they were trying to sell me cars with vastly overinflated prices and huge interest rates, and mainstream car dealerships had problems finding me credit.

Against what should have been my better judgement, I decided to buy the car with all the toys but higher mileage, instead of a more sensible car with lower mileage. I also fell for the "it's all motorway miles" line. I ended up buying the top-of-the-line renault Laguna (the Initiale) from Mark Smith at Tigerapex. At first, I thought I'd made a really good buy. Cosmetically, the car was great, and had all the features I could possibly want.

However, this turned out to be the worst move I could possibly have made. I'm currently having to hire a courtesy car from the garage I have ended up taking the car to be investigated at. During the first 6 months (and 6,000 miles) of having the car, the following things have gone wrong :

  • Water Temperature Sensor
  • Air conditioning compressor
  • Gearbox
  • Clutch
  • Rear Bushes
  • Tie Rods

The warranty only covers the first £500 of the faults. I fixed the first two faults, but the last four are going to cost me over £3000. Since the time I bought the car, I have attempted to contact Tigerapex on the occasions of the first two faults. During this time Tigerapex have :

  • Called me a liar
  • Accused me of threatening them
  • Not answered my calls
  • Not responded to my emails
  • Refused to contribute to the cost of any of the faults

I've learned a couple of lessons from this. It really is a good idea to avoid small car dealers unless you have lots of good personal recommendations about them. The likelihood of you getting screwed over is high. Also, never buy high mileage under the impression that a car has done "motorway miles only" or that a warranty will protect you from any problems with the car - dealers probably see people who buy these lines as easy marks, which, admittedly, I was.

I've put this article up in the hope that anyone thinking about buying a vehicle from Tigerapex who searches for their name will find it. I'd like to make sure that anyone considering purchasing a car from them has the benefit of my experience.

I got married !

Posted by Mark on 2007-08-01 - no comments

Myself and Stacy got married on July 28th at Haywards Heath register office, followed by our reception at the Bluebell Railway. I'll post more about this when I have some more time, but for the time being, the photographs made by the railways photographer are available here. (More photos to follow).

Cut this mans hair for red nose day !

Posted by Mark on 2007-03-15 - no comments

Where I'm currently contracting, Upmystreet.com, our sysadmin has a rather full head of hair - a whole four years of growth. He's pledged that if we get £2,500 for red nose day, he'll let us shave it off. Can anyone help us acheive this noble goal of getting this man to chop his hair raising £2,500 for Red Nose day ? If we succeed, (tentatively) he'll be getting it chopped in the Ha Ha bar near Victoria station (London) on Friday night. If he doesn't get it chopped there, I'll make sure it's recorded to video so you can all watch..

I'm told if you include your address in your pledge, we may be able to claim back gift aid if you're a UK taxpayer.

Update the form below was broken earlier - it should be working now if you want to pledge a donation !

Update Friday 16th March 10:00amWe've only got £920 promised so far. If you want this mans hair to disappear, dig deep !

Update The shaving will now be happening in Uswitch/Upmystreet offices - I'll video it for those of you who have contributed !

Update We cut his hair ! After pictures below - we'll try and get some video up later ... - anyone still wishing to add to the money - please use my Contact form - initial estimates are that £1400 has been raised (and Simon did it anyway !)

Before

After

< earlier posts older posts >