=head1 Socialize with FBConnect =head2 FBWhat? According to Facebook, "Facebook Connect is a powerful set of APIs for developers that lets users bring their identity and connections everywhere." The idea is quite similar to OAuth or Yahoo's BBauth, but with a Facebook flavor. You can read more technical stuff about it here: L Why would you need it? The simple scenario: you can use it like a bizarro OpenID, until Facebook becomes an OpenID provider :) Some of you will just want this: "Allow people to authenticate on my website using their Facebook account." But once the user is authenticated, your Catalyst app may also access the Facebook API using your user's credentials. Assuming she gives you permission, you can do all kinds of tricks, like getting the list of friends, avatar, and more. =head2 I want it, what now? Just use L. Once authenticated, this will give you the Facebook user identifier and a session key you can later use with L. First of all, you need to signup as a developer and get an I, a I, and an I. You'll need these to use Facebook Connect in Catalyst. Do your thing at L and come back with the info. Then you need to install L from CPAN. It depends on L, L, L and L =head1 Setting it up First, set up your Catalyst application. You should be familiar with authentication realms by now; if not, take a look at L. If you use the FBConnect credential to authenticate, you don't even need a database in your app. But most of the time you'll want to associate the Facebook user with a local user, and allow users to also authenticate the standard, password-based way. That's why we'll need two realms, C and C. package MyApp; __PACKAGE__->config( 'authentication' => { default_realm => 'facebook', realms => { facebook => { credential => { class => 'FBConnect', api_key => 'my_api_key', secret => 'my_secret', app_name => 'my_app_name', } }, dbic => { credential => { class => 'Password', password_type => 'none', }, store => { class => 'DBIx::Class', user_class => 'DB::User', id_field => 'user_id' } } } } ); The user table should have some columns for holding the external credential info, if you want to associate the two. We're using C to hold the Facebook uid. If you're using multiple external authentication systems (like OpenID or OAuth) it would be a good idea to specify the source for this particular credential in ( C ). package MyApp::Schema::Result::User; use strict; use warnings; use base 'DBIx::Class'; __PACKAGE__->table( 'users' ); __PACKAGE__->add_columns( user_id => { data_type => 'integer', is_auto_increment => 1, }, email => { data_type => 'varchar', is_nullable => 1 }, password => { data_type => 'varchar', is_nullable => 1 }, credential_identifier => { data_type => 'varchar', is_nullable => 1 }, credential_source => { data_type => 'varchar', is_nullable => 1 }, ); __PACKAGE__->set_primary_key( 'user_id' ); __PACKAGE__->add_unique_constraint( [ qw/ credential_identifier credential_source / ] ); 1; =head2 The login action The logic is simple: the first time you call C<< $c->authenticate >> for the C realm, the user will be redirected to the Facebook login page. Once she manages to authenticate there, she will be sent back by Facebook to our application (in the same action), but accompanied by an C. When C is called this time, the user is authenticated and C<< $c->user >> is created with the session information. All this logic is abstracted away inside the credential. Once she's authenticated with FBConnect, she'll either register or login (hence L) in our internal user database. After that we'll just use the familiar API to reauthenticate the user in the C realm. sub login : Path('/login/facebook') { my ($self, $c) = @_; if( $c->authenticate( {}, 'facebook' ) ) { my $user = $c->model('DB::User')->find_or_create( { credential_identifier => $c->user->session_uid, credential_source => 'facebook', } ); $c->authenticate( { credential_identifier => $user->credential_identifier, credential_source => 'facebook' }, 'dbic' ) or die "Login failed"; } } =head2 Connect an existing user You can also assign a Facebook account to an already existing account: sub assign : Path('/assign/facebook') { my ($self, $c) = @_; my $user = $c->user if $c->user_in_realm('dbic'); if( $c->authenticate( {}, 'facebook' ) ) { $user->update( { credential_identifier => $c->user->session_uid, credential_source => 'facebook', } ); $c->authenticate( { credential_identifier => $user->credential_identifier, credential_source => 'facebook' }, 'dbic' ) or die "Login failed"; } } =head2 Use the Facebook API All the work above gets you the uid from Facebook. This can be used later on with L. Here's some example code to actually use L: my $client = WWW::Facebook::API->new( desktop => 0, api_key => 'my_api_key' secret => 'my_secret' ); #get user info my $response = $client->users->get_info( uids => $c->user->credential_identifier, fields => [ qw/about_me quotes/ ] ); # get user's friends my $friends = $client->friends->get( uid => $c->user->credential_identifier ); More about this can be found in the L docs, enjoy :) =head1 AUTHOR Cosmin Budrica =head3 COPYRIGHT Copyright 2009 Sinapticode - L