Perl – Stay N Alive

Twitter – TIMTOWTDI

IMG_1366I love Twitter for its variety.  In many ways it’s a lot like my favorite programming language Perl, whose mantra is “There is more than one way to do it.”  Some people choose the messy, spaghetti code way, while others choose nicely formatted, object-oriented way, even taking it to the extent of protecting it further with libraries like Moose.  On the web I can do basic, old-style CGI, or take it as far as a full MVC structured framework using Catalyst (if you don’t know anything about what these are that’s okay – just know that they’re good, and well structured).  Perl has both a good and bad reputation because of this, and I like it that way.  I like it the same way I like Twitter – there’s more than one way to do it.

That’s why I get so bugged when I see so many people trying to tell me how to write my Twitter stream.  Some say I have to have multiple accounts to organize the data.  Others say I can’t run ads and my content can’t be promotional in any way.  Funny thing is most of those people are promoting something of their own, whether they admit it or not. Personally that doesn’t matter to me.

What matters to me is that I can use Twitter the way I want to.  I can write everything in one stream if I want to, or I can run ads if I want to (which actually, I just signed up for ad.ly yesterday to see what it was all about – no one has purchased anything yet though so no worries there, if there ever were any in the first place).  I can be profane if I like (but generally I prefer not to, just like real life).  I can even retweet the way I like to.  The cool thing about Social Media is we all have our own purposes and our own ways of doing things and when we do such we use the best tools for the job.  The great thing about Twitter is that it allows us to do such.  I use Twitter the way I use Perl, however I want to and what works for me – and I get criticized in the same manner.  There will always be a critic of the way you use Social Media, just like there is always a critic of how I write Perl.

And I’m okay with that.

The fact of the matter is I’m interesting because I’m ME.  Hopefully you follow me because of that.  If I advertise it’s going to because that’s something I think will help pay for me to be me, and it will always be some sort of reflection of myself.  If I don’t advertise it’s because I don’t think that’s necessary.  If I separate my content into multiple accounts it’s because I want you to find out different bits of information about me in different ways.  If I keep it all in one stream that’s because I think that’s the best way of learning who I am.  If I retweet it’s for my own reasons, not anyone else’s.

I think we get way too caught up in what we think is the best way that works for us, and thinking others should do the same.  What works for me will not always work for you or the next guy.  What works for Chris Pirillo or what works for Chris Brogan will not always work for Robert Scoble or Leo Laporte or someone else.  We are all unique, and that’s what makes Social Media a beautiful thing.  Social Media is all about how you receive, not about how other people give.  Receive well, and you will give much.  Social Media is all about ME. And you. And him. And her. It’s about connecting Individuals, which individuals are not the same.

And if you don’t like that concept, I’m okay if you unfollow me.  After all, there’s always more than one way to do it.

There’s More Than One Way to Store a Password – PerlMonks Hacked

nirvana-smells-like-teen-52041Hackers are in a state of Nirvana as it would appear they hit the gold mine of programmer passwords in a hack of the popular Perl forums and resource site, PerlMonks.com yesterday.  The hack claims to have gained access to the database of more than 50,000 passwords, which insanely were stored in plain text in the database for anyone to see.  The hackers subsequently published the list to several mirrored servers (I can’t find a link to verify, but it’s not something I would publish anyway), along with the following statement:

“There is a really simple reason we owned PerlMonks: we couldn’t resist more than 50,000 unencrypted programmer passwords.

That’s right, unhashed. Just sitting in the database. From which they save convenient backups for us.

Believe it or not, there is actually debate at perlmonks about whether or not this is a good idea. Let’s just settle the argument right now and say it was an idea that children with mental disabilities would be smart enough to scoff at. We considered patching this for you but we were just too busy and lazy. I’m sure you can figure it out yourselves.

This isn’t a bad set of passwords, either. Programmers have access to interesting things. These Perl guys are alright, just a little dumb apparently. A lot of them reuse. You can explore them yourselves, I really do not want to point out anyone in particular.

In case you guys are worried, we did NOT backdoor dozens of your public Perl projects. Honest. Why would we want to do that?

Not worth our time ;)”

It’s unclear exactly who, and how many were compromised, but the site is recommending all who have previously had accounts on PerlMonks.com to change their passwords immediately.  In addition, one of the worlds largest repositories of open source code, the CPAN network, has also recommended that its authors change their passwords, as evidently somehow the two sites are connected.

As a Perl developer, and CPAN author, this is a bit concerning.  First, it would be one issue if this were just some random group of people whose passwords had been hacked, but this is a database of tens of thousands of developers, probably most with root access to the machines they write code on, and according to the hackers, many using passwords that are being re-used elsewhere.  These are the passwords of developers like Chromatic, Brian D Foy, Andy Lester, engineers at major corporations and government entities, and more.  The hackers couldn’t have picked a worse server to crack and expose.

I’m baffled at what the PerlMonks developers and admins were thinking storing their passwords in plain-text, something that, in my own opinion is amateurish, and should have some sort of repercussions at their lack of responsibility in handling their users passwords.  This is something that not only has been in Perl since version 1.0, but has also been integrated natively in almost every database environment on the planet.  That said, there is no privacy policy that I can see on the PerlMonks website, so maybe the users should have paid better attention.  I don’t expect the PerlMonks admins to say that, though. I’m ashamed as a Perl developer, and this gives a huge black eye to the entire Perl community.  It only gives further validation to the rest of the world’s claims that Perl is for messy code.

I hope the PerlMonks developers and admins can make right of this situation and not only fix their database, but make amends with the community, and the rest of the world, whose trust they just violated. After this, I’m seriously considering switching to another language for my next project.

Making WWW::Facebook::API Facebook Connect Ready

FacebookI’m going to get geeky on you here again.  I’ve been working on a few things with SocialToo to enable Facebook Connect on the site – more on that to come.  What I’ve been surprised by though is that this long after the launch of Facebook Connect the main Perl libraries for Facebook, WWW::Facebook::API, still do not support Facebook Connect.  The main difference between making API calls from a native Facebook app and a third-party Facebook Connect app is that in the native app, you verify the signature via the URI parameters, via parameters that begin with “fb_sig_”.  In Facebook Connect, those variables are set in Cookies by the Facebook Client-side Javascript libraries, and begin with your applications API key, so they’d start something like “(api key)_”, and come from the cookies instead of the URI.  You can read more about that here.

So for full compatibility in your preferred Facebook API libraries, both the URI parameters have to be checked along with the Cookies in the event the developer is trying to connect from a third-party website.  In the PHP libraries this is already done for you.  Surprisingly, Perl has not yet implemented this.

So I got to work on it, and through a couple simple lines of code added to WWW::Facebook::API::Canvas I was able to make get_fb_params check your cookies when the URI parameters are not presence.  I’ve submitted the patch to the library’s owner, Clayton Scott, but in case you want to integrate it sooner you can apply it to the 0.4.14 version of Canvas.pm by downloading this patch.

I hope you’re able to get as much out of this as I am – please let me know if you see any potential bugs with the changes.

Social Coding: How to Code Twitter’s OAuth Using Net::OAuth and Perl

OAuthFor the non-developers in my readership, I’m going to get a little geeky on you here. So you can either tune this one out, or pass it onto your IT staff for use in their applications. I promise much more on the “Social” side here shortly. Or, maybe you’ll learn a little Perl.

For those not in the loop, my company, SocialToo.com codes in Perl, a powerful language that gives me the ability to abstract what I need at a very high level, or get down to the nitty-gritty if needed to in order to improve speed or communicate with other core Unix libraries and tools. To me, it’s a very powerful and important language that enables me to get done what I need to do without having to hire developers that know multiple languages. It’s also an amazing scripting language, and powers many of the scripts we run on the backend of SocialToo.

One of Perl’s weaknesses however is that it has never been very strong in the marketing department. For this reason, it is some times (and some times not) one of the last on the priority list for companies like Twitter when developing libraries to integrate with their API. Fortunately it has a very strong group of developers contributing to its very unique directory of open source libraries, CPAN.

Recently we launched a beta OAuth implementation on our Forgot Password page on SocialToo, which uses Twitter OAuth to identify a user and allow them to change their password based on their Twitter authentication. Fortunately with Twitter, we were able to use Net::OAuth, Perl’s OAuth libraries on CPAN, to connect with Twitter’s OAuth implementation. There were some tricks, so I’d like to share that here. It’s my hope that maybe at some point I can package this up at a much higher level to make the process even easier for Perl developers to use Twitter’s OAuth to authenticate.

Perl and OAuth – the basics

First of all, you need to understand the basic flow of the Twitter OAuth process. There are official OAuth terms for this (consumer, service provider, etc.) supposedly to make understanding the process easier, but for our purposes those terms really don’t matter. If you really want to learn more about that stuff, go over to OAuth.net and take the tutorials. What matters is that you get the Access Token you need, which you can use any time later to make requests to Twitter, such as authenticating the user, getting the user’s timeline, their profile info, friends, followers, and more. The entire goal of Twitter OAuth from a development standpoint is to get that Access Token. So here are some basic terms you need to know:

Token – a string of hashed data given to you as a unique ID to identify your application, and the user trying to use your application by Twitter. See below for the types of tokens you’ll need to get from Twitter and when.

Request Token – The token you get from Twitter before redirecting the user to authenticate with Twitter. If the user’s authentication is successful, Twitter creates an access token which identifies the user and associates them with your application. You can then access that access token later by sending another request after the user has authenticated with the request token and the request token secret key (defined below).

Request Token Secret – A string of hashed text, which only you (the developer) will ever see or use. You retrieve this when you get your Request Token, and will need to pass it with your request token when you request to get an access token. Consider this your password when trying to get an access token. Your Request Token is your ID for Twitter to identify your request with to verify the user authenticated successfully and your application has permission to access Twitter.

Access Token – Once you have your Request Token, your Request Token secret, and the user has authenticated successfully, and assuming your application has been given permission by Twitter to access the Twitter API, you can then make a request to Twitter to get your Access Token. You send Twitter your Request Token and your Request Token Secret, and the response returns your Access Token and an Access Token Secret Key for access to the Twitter API. This is a permanent key at the moment that you can use any time later. Store this in your database or a file or elsewhere once the user has authenticated and you’ll be able to authenticate on their behalf from that point on (assuming you have set your app up to do such on Twitter.com). After you have your Access Token, you can make requests to Twitter, via Net::OAuth, which perform any of the methods found via the API by sending Twitter your Access Token and Access Token Secret with the request. Use JSON::Any to parse the resulting JSON returned.

Access Token Secret – The secret key to pass with an Access Token when making API calls to Twitter. Consider this the password that goes along with the ID, which is the Access Token. Twitter looks up the Access Token ID, verifies the user is authenticated, and then checks that you also have a valid Access Token Secret Key. If both are correct and valid Twitter will send back the data you need to access the Twitter API.

Twitter Consumer Key – The unique ID of your application as identified by Twitter – you can get this in your OAuth set up on Twitter. You use this when asking for your Request Token.

Twitter Consumer Key Secret – The “password” to go with your Twitter Consumer Key when asking for your Request Token from Twitter. Twitter looks up your application by it’s ID (Consumer Key), and verifies it’s you by checking your Consumer Key Secret.

Flow of a Simple Twitter OAuth App in Perl

To understand what we’re doing, you’ll need to understand the order of things you’ll need to do in order to fully access the Twitter API through OAuth. This Flow, in plain english, should outline that process, and from here you should be able to adapt the code I provide for any use:

  1. Send a GET request to http://twitter.com/oauth/request_token asking for a request token from Twitter, and passing your appropriate Consumer Key and Consumer Key Secret to identify your application.
  2. If Twitter identifies the Application as legit (and isn’t down), parse out the request token and request token secret from the content of the returned page by Twitter. Here you’ll want to store that request token and request token secret somewhere, as you’ll need to access it again after the user returns back to your site from Twitter.
  3. Redirect to http://twitter.com/oauth/authorize, appending “?oauth_token=YOUR_REQUEST_TOKEN_GOES_HERE” to the URL, replacing YOUR_REQUEST_TOKEN_GOES_HERE with the request token you just got from Twitter. There is no need to send the Request Token secret at this point – this is simply to identify that you have received a request token from Twitter, and so Twitter can identify the user’s authentication (successful or not) with that Request Token.
  4. The user authenticates on Twitter (if not already authenticated through Twitter – if they want to authenticate through a different user they can do so here as well by logging out and re-authenticating).
  5. The user is given the option to “Allow” or “Deny” the request by the Application to access their account information on Twitter.
  6. Twitter then redirects back to the Callback URL you set up in your OAuth set up on Twitter.com – you’ll want to note this so you can write code at the location Twitter redirects to that gets the response token.
  7. Your Callback URL takes the Request Token from earlier, and Request Token Secret from earlier, and sends them to http://twitter.com/oauth/access_token to try and get an Access token. Twitter verifies that the user has authenticated successfully, that they have allowed your application to access their account, and that your Application is valid. If so, you’re returned a successful response from Twitter.
  8. You’ll want to parse out the Access Token, and Access Token Secret from the returned page, and store them somewhere with that user so you can access Twitter on their behalf later. Or, do something right then and there! You have all you need now to use the Twitter API for that user under OAuth.
  9. At this time is when I would authenticate the user if needed, making an OAuth request to access http://twitter.com/account/verify_credentials.json. To do so just send the request via Net::OAuth, along with that user’s Access Key and Access Key Secret (which hopefully you can retrieve from somewhere since you stored it somewhere earlier), and Twitter returns the data back as JSON-formatted data (or XML if you specified verify_credentials.xml) you can then parse out as necessary. You can do the same with any method in the Twitter API.

Example Code

Alright, now onto the juicy details. Assuming you’ve already set up an OAuth Twitter App under your settings tab on Twitter.com, and have your Consumer Key and Secret, you should be set to go. You’ll need to install Perl’s Net::OAuth (and any dependencies) via:

perl -MCPAN -e "install Net::OAuth"

Now, let’s get the Request Token. To do so, I’ve created a simple OAuth Accessor method to do all my OAuth handling. I use Catalyst as my MVC Framework, so all the $c and $self references refer back to the Catalyst environment. I’ll leave that up to you to figure out, or you could always try out Catalyst! So first, let’s set up this method:

=head2 oauth_request

Sends a generic request to the specified url

=cut

sub oauth_request : Private {

my $self = shift;
my $c = shift;
my $i = {
'type' => '',
'url' => '',
'extra_params' => {},
'token' => '',
'token_secret' => '',
'method' => 'GET',
@_,
};

my $request = Net::OAuth->request($i->{'type'})->new(
consumer_key => $c->config->{'twitter_consumer_key'},
consumer_secret => $c->config->{'twitter_consumer_secret'},
token => $i->{'token'},
token_secret => $i->{'token_secret'},
request_url => $i->{'url'},
request_method => $i->{'method'},
signature_method => 'HMAC-SHA1',
timestamp => time,
nonce => join('', rand_chars(size=>16, set=>'alphanumeric')),
extra_params => $i->{'extra_params'},
);

$request->sign;
$c->log->debug("URL: ".$request->to_url);

$c->log->debug("Request: ".Dumper($request));

my $ua = LWP::UserAgent->new;
my $response = '';
if ($i->{'method'} eq 'GET') {
$response = $ua->get($request->to_url);
}
else {
$response = $ua->post($request->to_url);
}
$c->log->debug("Response: ".Dumper($response));

return $response;

}

Basically, all this does is create a new Net::OAuth request object, signs it, and then sends it via a GET or POST request (via LWP) back to the specified URL. This method will handle all our OAuth requests. You’ll need to modify it to match your environment and configuration variables (like the consumer key and secret).

The token and token_secret variables can be either a request token, or access token (and secret), or neither. You won’t need to pass either when you’re trying to get your request token obviously. “type” will define what type of request it is you’re making – it can be either “request token” (to ask for a request token), “access token” (to ask for an access token), or “protected resource” (when accessing private data for a user from the Twitter API on their behalf). The “url” variable specifies the Twitter URL to request, based on the type of the request. You can get these from your OAuth settings page for your app on Twitter.com. Dont’ worry about the rest – that’s all used to generate the signature sent to Twitter with all the data you just gave it.

Now that we have that, we can make our requests to Twitter.  We’ll need to start with getting our Request Token.  We’re of course assuming this is the user’s first time authenticating through your App.  Here’s how we’ll do that using the above method:


$c->log->debug("getting request token...");

my $res = $self->oauth_request($c,
'url'       => $c->config->{'twitter_request_url'},
'type'      => "request token",
);

$c->user_session->{'oauth_redirect_url'} = uri_escape($c->req->param("redirect_url"));

if ($res->is_success) {
my $response = Net::OAuth->response('request token')->from_post_body($res->content);
if (defined $response->token) {
$c->user_session->{'request_token'} = $response->token;
$c->user_session->{'request_token_secret'} = $response->token_secret;
my $auth_url = $c->config->{'twitter_authorize_token_url'}."?oauth_token=" . $response->token;
$c->res->redirect($auth_url);
$c->detach;
return;
}
}
else {
$c->log->fatal("Something went wrong.");
# expire request tokens each time they are used
$c->user_session->{'request_token'} = '';
$c->user_session->{'request_token_secret'} = '';
}

In this example, we ask for a simple request token from Twitter to the request token URL we were given by Twitter in our OAuth settings. In this particular example (it may not be needed by yours), we allow the user to pass a redirect URL to our application via a “redirect_url” parameter in the URL. We store that in the session for later use so we can pass the user onto somewhere else if needed. You could store this in a cookie, a session, a file, or database – it’s up to you, and won’t be necessary if you never need to redirect the user later.

Assuming your app has been authorized to connect to Twitter with the Consumer Key specified, you should get a successful (200 OK) response back from Twitter. You’ll then need to parse out the Request Token and Request Token Secret keys from the response. You can do so by passing the returned content through Net::OAuth->response(‘request token’)->from_post_body() as specified.

Once you’ve got that token and a secret key for it, you’ll want to store it somewhere for later use. Twitter doesn’t give it back to your app later, so you’ll need to put it somewhere. In this example we store it in the Catalyst Session for the particular user’s session. You could store them in a cookie, session, file, or database, but you’ll need to put them somewhere. You’ll need this later.

Finally, we need to redirect the user to authenticate and authorize your App on Twitter. You send them to the authorize URL Twitter gives you in your App settings page when you set up OAuth, and append, “?oauth_token=”, followed by the Request Token you just received. Also note the error checking we do – don’t forget to cover your bases!

The user will get sent to Twitter, authenticate, and authorize your App. Finally Twitter will redirect the user back to your callback URL that you specified in your App’s settings when you set up OAuth on Twitter.com. In that URL’s logic, you’ll need to do something like the following:


$c->log->debug("request_token: ".$c->user_session->{'request_token'});
$c->log->debug("request_token_secret: ".$c->user_session->{'request_token_secret'});

my $res = $self->oauth_request($c,
'url' => $c->config->{'twitter_access_token_url'},
 'type' => "access token",
'token' => $c->user_session->{'request_token'},
'token_secret' => $c->user_session->{'request_token_secret'},
);

if ($res->is_success) {
my $response = Net::OAuth->response('access token')->from_post_body($res->content);
$c->user_session->{'access_token'} = $response->token;
$c->user_session->{'access_token_secret'} = $response->token_secret;

$c->log->debug("redirect_url: ".$c->user_session->{'oauth_redirect_url'});
$c->res->redirect(uri_unescape($c->user_session->{'oauth_redirect_url'}));
}
else {
$c->log->fatal("Could not get an Access Token: " . $res->as_string);
}

# expire request tokens each time they are used
$c->user_session->{'request_token'} = '';
$c->user_session->{'request_token_secret'} = '';

At our callback URL, our main goal now is to get that Access Token. We’re assuming the user has authenticated and approved the app. We know the request token and request token secret, but do not yet have an Access Token for the user. Let’s hope you stored the Request Token and Request Token Secret for that user somewhere. You’ll need it here.

To get the Access Token, you’ll need to send an access token request to Twitter, to the URL specified in your settings where you set up OAuth for your App on Twitter.com. In addition, you’ll want to pass into it the Request Token, and Request Token Secret we stored earlier. In this case we stored it in the session, but you’ll need to retrieve it from wherever you stored it earlier.

If your request is successful, you’ll then need to parse the Access Token and Access Token secret from Twitter by passing the returned content to the Net::OAuth->response(‘access token’)->from_post_body() method. You can then get your Access Token and Access Token Secret from the returned response, as shown in the example. You’ll then want to store those somewhere, often some place permanent to be accessed later on behalf of the user. In our specific case, since this is just a forgot password form, we only need to store it in the session for access later, which we do in the example.

Now, remember that redirect_url parameter we passed and stored in the session? Now we can retrieve that, and redirect the user wherever you intended them to go after starting the authentication process. In this case, we’ll probably pass them onto the Forgot password page for authentication verification and identification of the user. The code on the forgot password page will look something like this:


=head2 verify_credentials

Verifies the user's Twitter credentials and returns a user hashref if successful

=cut

sub verify_credentials : Private {

my ($self, $c) = @_;

if (!$c->user_session->{'access_token'}) {
return q{Access token must be retrieved from Twitter before we can run verify_credentials.};
}

my $response = $self->oauth_request($c,
'url' => 'http://twitter.com/account/verify_credentials.json',
'token' => $c->user_session->{'access_token'},
'token_secret' => $c->user_session->{'access_token_secret'},
'type' => "protected resource",
);

my $retval = '';
if ($response->is_success) {
$retval = eval { JSON::Any->jsonToObj( $response->content ) };
if ( !defined $retval ) {
return q{Twitter returned success but parsing of the response failed: }.$response->content;
}
}
else {
return $response->code;
}

return $retval;

}

In this example we simply send a protected resource request to Twitter’s verify_credentials call. We parse out the returned JSON response, and voila, we have an authenticated user and all their information! This particular method will return the full user’s data if they are authenticated. We can then use that on the forgot password form to identify who the user is, if they’re a SocialToo user, and it will work regardless if we even have their Twitter username correct, because it relies on the Twitter user id.

So, the final full code you’ll want to use will look something like this (again, I’m using the Catalyst framework):


=head2 authenticate_twitter

Redirects to Twitter to get OAuth Token

=cut

sub authenticate_twitter : Local {

my ($self, $c) = @_;

#This ensures we only run the following code the first time they authenticate - pass it ?init=1 in the "sign in to Twitter" link
unless ($c->user_session->{'request_token'} && $c->user_session->{'request_token_secret'} && !$c->req->param('init')) {
$c->log->debug("getting request token...");

my $res = $self->oauth_request($c,
'url' => $c->config->{'twitter_request_url'},
'type' => "request token",
);

$c->user_session->{'oauth_redirect_url'} = uri_escape($c->req->param("redirect_url"));

if ($res->is_success) {
my $response = Net::OAuth->response('request token')->from_post_body($res->content);
if (defined $response->token) {
$c->user_session->{'request_token'} = $response->token;
$c->user_session->{'request_token_secret'} = $response->token_secret;
my $auth_url = $c->config->{'twitter_authorize_token_url'}."?oauth_token=" . $response->token;
$c->res->redirect($auth_url);
$c->detach;
return;
}
}
else {
$c->log->fatal("Something went wrong.");
# expire request tokens each time they are used
$c->user_session->{'request_token'} = '';
$c->user_session->{'request_token_secret'} = '';
}
}
else {
$c->log->debug("request_token: ".$c->user_session->{'request_token'});
$c->log->debug("request_token_secret: ".$c->user_session->{'request_token_secret'});

my $res = $self->oauth_request($c,
'url' => $c->config->{'twitter_access_token_url'},
 'type' => "access token",
'token' => $c->user_session->{'request_token'},
'token_secret' => $c->user_session->{'request_token_secret'},
);

if ($res->is_success) {
my $response = Net::OAuth->response('access token')->from_post_body($res->content);
$c->user_session->{'access_token'} = $response->token;
$c->user_session->{'access_token_secret'} = $response->token_secret;

$c->log->debug("redirect_url: ".$c->user_session->{'oauth_redirect_url'});
$c->res->redirect(uri_unescape($c->user_session->{'oauth_redirect_url'}));
}
else {
$c->log->fatal("Could not get an Access Token: " . $res->as_string);
}

# expire request tokens each time they are used
$c->user_session->{'request_token'} = '';
$c->user_session->{'request_token_secret'} = '';
}

}

=head2 oauth_request

Sends a generic request to the specified url

=cut

sub oauth_request : Private {

my $self = shift;
my $c = shift;
my $i = {
'type' => '',
'url' => '',
'extra_params' => {},
'token' => '',
'token_secret' => '',
'method' => 'GET',
@_,
};

my $request = Net::OAuth->request($i->{'type'})->new(
consumer_key => $c->config->{'twitter_consumer_key'},
consumer_secret => $c->config->{'twitter_consumer_secret'},
token => $i->{'token'},
token_secret => $i->{'token_secret'},
request_url => $i->{'url'},
request_method => $i->{'method'},
signature_method => 'HMAC-SHA1',
timestamp => time,
nonce => join('', rand_chars(size=>16, set=>'alphanumeric')),
extra_params => $i->{'extra_params'},
);

$request->sign;
$c->log->debug("URL: ".$request->to_url);

$c->log->debug("Request: ".Dumper($request));

my $ua = LWP::UserAgent->new;
my $response = '';
if ($i->{'method'} eq 'GET') {
$response = $ua->get($request->to_url);
}
else {
$response = $ua->post($request->to_url);
}
$c->log->debug("Response: ".Dumper($response));

return $response;

}

=head2 verify_credentials

Verifies the user's Twitter credentials and returns a user hashref if successful

=cut

sub verify_credentials : Private {

my ($self, $c) = @_;

if (!$c->user_session->{'access_token'}) {
return q{Access token must be retrieved from Twitter before we can run verify_credentials.};
}

my $response = $self->oauth_request($c,
'url' => 'http://twitter.com/account/verify_credentials.json',
'token' => $c->user_session->{'access_token'},
'token_secret' => $c->user_session->{'access_token_secret'},
'type' => "protected resource",
);

my $retval = '';
if ($response->is_success) {
$retval = eval { JSON::Any->jsonToObj( $response->content ) };
if ( !defined $retval ) {
return q{Twitter returned success but parsing of the response failed: }.$response->content;
}
}
else {
return $response->code;
}

return $retval;

}

To run it, you’ll (assuming this is Catalyst) point your “Sign in With Twitter” link to /authenticate_twitter?init=1&redirect_url=http://yourdomain.com/forgot on your domain. Note that “init=1” identifies the user is not yet authenticated. That gets the request token, and redirects the user to Twitter to authenticate. Twitter then sends the user back to /authenticate_twitter on your domain. You detect that the request_token session variable has been set along with the secret key, so then run the code to get an access token. You get the access token from Twitter, store that in the session, and then redirect the user to http://yourdomain.com/forgot (identified by the redirect_url parameter in your original sign in link). http://yourdomain.com/forgot accesses the verify_credentials() method above, which takes the user session variable with the access token, verifies the user’s Twitter credentials, and returns user data for the individual. You can then display user data appropriately, and in this case allow the user to reset their password because you have officially confirmed it is them.

SocialToo Forgot Password Form

Like on Socialtoo, your forgot password form, or other OAuth instance will have a “Sign in With Twitter” link like this one that points to code similar to what I featured.

If you want to learn more, the documentation is pretty scarce at the moment. Hopefully myself or someone else will put together a much more abstract set of libraries targeting the Twitter platform soon surrounding this. I do recommend checking out OAuth.net and understanding the OAuth protocol a little more, along with the Net::OAuth documentation. Hopefully many more of you can share your experiences in the comments, or in your own blogs as you come across new experiences with Twitter’s OAuth in a Perl environment.

UPDATE: Looks like someone already has added an abstraction layer around all this. To simplify things even further, check out Net::Twitter::OAuth. It might be helpful to read this first anyway so you know what’s going on there.

Automatic Data Compression With DBIx::Class::CompressColumns

UPDATE: You can now get the DBIx::Class::CompressColumns module on CPAN here or via CPAN command-line shell.

Too Many PeopleI’m going to get geeky on you for a minute, but you should find this interesting.  One of the challenges I’ve had with SocialToo recently has been the massive Social Graph data we’ve had to story and process and track. We cache a lot of the data so we don’t have to hit Twitter’s servers as often, and also to enable us to track new follows and unfollows regularly on behalf of our users.

If you are a SocialToo user you may have noticed that your data hasn’t been as accurate lately as it should.  The reason for that is we have had a) 20,000+ users all wanting to auto-follow or have their follower base tracked, and b) all 20,000+ of those users have anywhere from 100 to near 1 million followers that we have to store and process.  It’s not an easy task!  And our database, set up in a relational manner of followers to users, just wasn’t cutting it in regards to being able to retrieve and process so many followers at a time.

So I took a cue from Bret Taylor and FriendFeed, who talks about how they denormalized their database, and now reference “bags” of data that they can then process in their code.  I went for a hybrid model, and with each user entry I now have a single column on that table we reference, in BLOB format, which contains all the social graph data for that user.  In Perl, I simply create a hash structure of the data, freeze it, and then store it in the database in our social graph column.  To retrieve it, we pull it from the database, thaw it, and we have an entire social graph we can play around with and do with as we please.

The issue I was running into however is that plain text, stored in a single column, for a user with 1 million followers, gets to be quite a large amount of data we need to pull through the pipes.  I needed an easy way to compress the data before inserting into the database, storing it in binary format, and decompress.  I also wanted it to be automatic, so no coder would ever have to worry about this extra step – it would just happen magically.

So today I’m releasing DBIx::Class::CompressColumns for all you Perl coders out there.  What this module does is it sits on top of Perl’s DBIx::Class database abstraction libraries and allows you to monitor a single column.  Any inserts or updates into that column get compressed in Zlib format, and any selects/get_column calls to that data (you must use get_column) get de-compressed, meaning you don’t have to worry at all about that extra step, the data is a significantly smaller footprint, and your throughput is much less, causing much less load on the database.  For one-million followers, I measured just 4 Megabytes in space taken that has to go in and out of MySQL.

Approaching Graph optimization in this manner has significantly sped up our processes, and I’m already seeing huge benefits from it.  There is much less load on the database, it’s much faster to retrieve and process the data, and we’re getting through our users’ followers much faster now.

The module namespace is currently being applied for on CPAN at the moment, and I’ll post a link there as soon as it is approved, but for now you can download the Makefile-compatible gzipped library here.  I hope some of you find this useful, and please feel free to modify or send me any updates or bugs you think I missed!

The link for the download is http://socialtoo.com/DBIx-Class-CompressColumns-0.01000.tar.gz

Oh, and TMTOWTDI so please if you have better ways of approaching this I’d love to hear your ideas!

Photo courtesy rp72

Developers Bailing on Twitter

whale.pngI’ve been following various development mailing lists lately, and I’m seeing a trend of developers starting to bail on Twitter. This is a scary thought, because when the developers bail, so will the users. It all started with a conversation on the Twitter Developers’ mailing list with the subject, “Shame” by a developer named, “nath“, in which he said,

“Well, twitters always down or unusable due to the speed; the api’s
keep breaking and are down just as often; the groups now packed full
of spam which is littering my inbox.

“It’s a real shame to see such a great app crumble and die like this :(“

Alex Payne, a developer for Twitter, responded by saying,

We own Twitter’s speed a stability; my our metrics, it’s been pretty
solid over the last few days.

We do not, however, own spam prevention for this group. That’s up to
Google, and if it’s a hard problem for them, I’d imagine it’d be a
hard problem for anyone.

I go through and clear out spammy posts, but time they reach my inbox,
they’ve reached everyone else’s as well. There’s just not much I can
do about it. Please make use of Google’s “report as spam” features.

After which another developer that goes by “rlanskyresponded:

Sorry, but I have to agree with the original author, it is a shame
that the service and the API are so unreliable. The potential for the
services that could be built on an API like the one offered by twitter
are endless. They really are.

Statements like this:

> my our metrics, it’s been pretty solid over the last few days.

don’t do much to boost my confidence. When you make an API available,
you are essentially saying to the world, “here’s our service, come and
build something great on top of it.” You can’t build anything of any
real value or widespread use on something that “has been *pretty
solid* over the last couple days (emphasis mine) .” You just can’t.
You need something that is rock solid all the time.

I’m not trying to start a flame war or bash twitter at all. Like I
said, I think it is a shame because the potential is so great. The
idea is great, the acceptance is great, the use is great, the
possibilities are awesome. But they just can’t be fulfilled given the
reliability of the service as it is today; try to build something on
top of the API that will see wide-spread use and you’ll find that when
you push the gas, the wheels fall off the car… at least that’s been
my experience. It’s been *extremely* frustrating and disappointing.

Peace.

After following a few threads on the Perl development library for Twitter, Net::Twitter, I recently found out that Net::Twitter’s original maintainer too has jumped ship. He has handed it over to a new maintainer, but developments like this are not a good sign for Twitter! It is very clear that frustration amongst Twitter developers has hit a maximum level and I fully expect to see this only increase in the short term.

At the same time, developers like Kee Hinckley are giving advice to Twitter, and they are graciously accepting it seems. Some great tips are being given on ways to enhance the API, and I even suggested they do a public bug tracker which they seemed to like. Twitter clearly doesn’t seem to have enough expertise in-house, although they do keep saying they are hiring. Their jobs page doesn’t seem to have any upper-management positions though which I think is really what they need right now.

I’m very worried for Twitter. As more developers jump ship and work on other platforms such as Plurk and FriendFeed (which really isn’t a direct competitor to Twitter), this great tool is going to be left in the dust with no new development and large networks of people moving elsewhere. Twitter’s largest traffic comes from the API itself, and as that traffic dies down, so will Twitter. Imagine, for instance, if Seesmic were to stop development on Twhirl due to the costs associated with keeping up with API flaws? That would be quite a chunk of Twitter’s users being forced over to the other Twhirl clients, FriendFeed and Seesmic itself – it’s such an easy transition were Twitter support to be dropped! What happens when Twhirl begins supporting Plurk?

Twitter needs to do something, and they need to do it fast. I agree they need to get their infrastructure in place, but before even doing that they really need to put every hack possible in place to keep the API up, keep it working, and work with the developers to ensure they are staying happy. A large revolution is about to take place, and I’m afraid it won’t be pretty.

UPDATE: See the little FriendFeed box below? Click “show” and join the discussion on FriendFeed about this right on my blog! Subscribe to my updates here.

Facebook Announces F8 In the Middle of OSCON, Coincidence?

l11204705797_2531.pngJust yesterday, Facebook announced their second F8 conference, to occur July 23, 2008. This Developer-targeted event is said to possibly include some major announcements, including the new Profile redesign, more information about the fbOpen platform, and most significantly, possibly the launch of their E-Commerce platform. What hasn’t been announced or shared however is the odd timing of the event.

The event occurs right smack dab in the middle of O’Reilly’s Open Source Convention, scheduled to occur for about the past year now from July 21 through July 25. This conference is known as an essential “Mecca” for Open Source developers around the globe, and has presentations from such players as Google, MySQL, Sun, Meebo, and even SixApart. Everyone who is a developer (unless you solely develop for Microsoft) or Sysadmin will be at this conference.

As a developer, this is tough news to hear that Facebook will make me choose between OSCON and them. Frankly, I would by default choose OSCON if I were any smart developer, as I would get more. So why isn’t Facebook just joining OSCON and doing an “F8” track there? Do they really want to tick off Open Source developers? You better bet that OpenSocial will have a presence there. If Facebook really wanted to target the Open Source crowd, as they have “claimed” to do with their fbOpen Platform and a few other contributions back to the community, they would try to have a presence at this conference and not interrupt it as they are currently doing. I was actually going to go to OSCON to promote my FBML Essentials book to potential Facebook developers for O’Reilly. Now I’m forced with a decision. I’ve contacted Facebook with no response, and I’m getting a little frustrated as a Social Media developer. Which conference will you choose?

New Series: Social Coding

I’ve been contemplating for awhile now a good way to share what I know about Social Software Development and helping business owners, marketers, and developers learn how to set up their own social apps. Especially for developers, I know there are many out there looking for howtos and ways to learn more about starting their own App, promoting it, and getting it off the ground. As the author of FBML Essentials, I feel I am well suited for the task so in the next few days I’m going to start doing howtos and overviews on how you can get your own Apps together. If you’re “the business type”, I may get a little technical on you, but I do recommend you keep watching and forward these onto your IT personell – your CIO, CTO, and the like should read these so they can learn what’s possible to integrate into your existing environments. I’ll also try to throw in a little goodie here and there for “the business type”.

So, I’ve created a new category to the right, “Social Coding” – if you want to track just that, click on the category name and add it to your RSS. I’ve also started a new FriendFeed Room where those involved or that want to get involved in Social Coding can discuss, learn, and talk with each other. You can subscribe to that here.

Let’s start by going over the types of sites I could cover. Here are just a few – let me know if you have a particular interest in learning about how to code for any one in particular:

  • Facebook
  • OpenSocial
  • Google Friend Connect
  • Twitter
  • FriendFeed
  • Pligg
  • Digg
  • LinkedIn
  • MySpace
  • WordPress
  • MoveableType
  • Google App Engine
  • Bungee Connect

Stay tuned! I’ll keep posting news and other rants as we go forward – I’ll just be adding in some good howtos at the same time. Oh, and if you’re a developer and would like to do a howto in your preferred language for us, contact me – I’d love to let you do a guest post.

Utah Startup Series: Bungee Labs

logo_bungeelabs-flat_md.png(Sorry it’s been awhile since my last blog – it took me several days to figure out how to get my Flip video imported and exported to and from iMovie. To make a long story short, if you want to export from iMovie and have both picture and sound, you must import your source as something other than MP4 or AVI.)

This is the first article in my “Utah Startup Series“. Starting today I will be circling Utah to find the best and most innovative startups in Utah, and featuring them here on Stay N’ Alive. If you have a hot startup (early to even late stage) and would like to demo for me what your product can do, please contact me – if I have the time and like your idea I’d love to come out and take a look at it!

While at Web 2.0 Expo I had the opportunity to meet with Bungee Labs, a local, well funded Utah company who had “Platform as a Service” down before Google even started thinking about their App Engine. In our meeting they demoed their Bungee Connect “IDE” (written entirely on the web). You can see the video below.

My thoughts – you have to see this stuff in person to understand the full ramifications of what they’re doing. One of the cool things about their service vs. Google’s is they actually integrate with Amazon’s EC2 service (which was announced during Web 2.0 Expo), so you can actually host your other stuff on Amazon’s EC2 platform with the same licensing as your Bungee Connect account. Their licensing structure is very appealing as well – Bungee only charges based on the number of registered user sessions using their platform, not traffic, not bandwidth. If I understand correctly, it’s all based on the number of users actively using your application on their platform. For Facebook and Social Media developers this is appealing, as most Applications are rated based on Application use, not number of users or traffic. With Bungee you only pay for the users that actively use your system.

Overall, the guys at Bungee were Rockstars at Web 2.0 Expo. With their announcements about EC2 integration, flexible licensing terms, features on TechCrunch, EWeek magazine, and a dozen other publications, you can bet Google has a watchful eye on them. Ironically, it was interesting seeing Kevin Marx, head guy over the OpenSocial (and other) efforts at their party on Thursday evening.

Bungee will be presenting at our Social Media Developers meeting this coming Tuesday, showing us a simple “Hello World” example on how to build a Facebook App using their platform. Follow me on Twitter and if we can stream it live you can watch it via my Ustream channel. After demo I may just write my own Facebook App to try out their system – it should be interesting.

Bungee Connect Demo – Web 2.0 Expo from Jesse Stay on Vimeo.

Why I Hate the Twitter Syntax

history76156-thumb.pngI have disliked the Twitter syntax since I’ve been on it (you can find me via @JesseStay on Twitter – go ahead and follow me!). As a long-time IRC user, everything seems backwards! I have often referred to Twitter as “IRC 2.0”. I’m not sure I can fully embrace that concept though.

For those unfamiliar with IRC, it predates even instant messaging. It brought out the original concept of a “chatroom”, and exists even today on various servers throughout the world. Ustream.tv currently uses it for its users’ channel chatrooms. It is the home for almost any “live” activity of any open source project (log into irc.freenode.net to see – I’m often in #utah there, as well as recently #codeaway). Traditions have been established, and virtual friendships have been bonded. In many ways it could have been the original concept of a “social network”, the first concept of linking friends together in a single place on the internet.

I was at a Perl conference just last year, and was happy to see the #YAPC chatroom in irc.perl.org open during the banquet. We had a ton of fun with that! Now, just this year, when I go to conferences, I see speakers leaving up Twitter, and answering questions via Twitter. The two seem to be serving similar purposes, in different ways.

That’s why I was astonished when I got on Twitter for the first time, and started seeing public messages directed to individuals with “@” signs in front of them! Is there a source for that that I’m not aware of? I know of no known documentation that Twitter themselves created to establish that tradition. In IRC you simply type “username:”, and then your message, and it gets highlighted in that user’s chat window in most IRC clients. Better yet, I can start typing the username and it tab-completes. You can’t do that in Twitter. That tradition and method has been around for years, yet Twitter seems to break the mold for some reason.

IRC also supports commands – I can type “/nick newnickname”, and it switches my username, automatically! It’s a basic standard that all clients support, open, and available for all to use. Twitter I have to go entirely to their website to do anything, and it’s extremely limited in what you can do. To direct message someone on Twitter, I have to type, “dm username message”. In IRC it’s just a simple command, like all other commands, and I can always type, “/help” if I don’t know what the commands available are. I simply type, “/msg username message”, and it messages the user, and again, it tab-completes the username!

Why couldn’t Twitter just use the IRC standard in their platform, and then expand upon it to improve the IRC standard and bring it to a mobile world? By all means many of their scalability issues may have been taken care of had they done so. Not just that, but they would now be able to support groups, and less development would be needed to manage their platform. Twitter says they have an open API – I question that openness. It’s not based on much of an open standard, and IMO, it’s causing them problems now because of it.

Looking to start a project? Always look at the open solutions that are out there first, then build upon them – you’ll have much fewer headaches if you do.

(Photo courtesy GapingVoid.com)