How to Handle Facebook App Uninstalls with RFacebook

Posted on February 20, 2008

I posted the following here—but thought I’d solicit other feedback via blog as well.

As of this writing, the rfacebook plugin does not seem to provide a way to handle uninstalls (easily).

Is there a method I’m not aware of? Or does one handle it pretty much how I’ve done below?

In this example, to handle uninstalls in your rails app we will use the post-remove URL of ‘foo.yourapp.com/uninstalled’.

In your application.rb, you probably have something like:

  before_filter :require_facebook_install
  before_filter :require_facebook_login

Change your application.rb to something like:

  before_filter :require_facebook_install, :except => [:uninstalled]
  before_filter :require_facebook_login, :except => [:uninstalled]

  # Before Filter on *only* the 'uninstalled' method
  before_filter :verify_uninstall_signature, :only => [:uninstalled]

  # Note: it's important this method is *above* the 'protected' definition, since it needs to be called directly
  def uninstalled
    @fb_uid = params[:fb_sig_user]
    # From here on it will be app specific -- given the facebook uid, destroy the user, like...
    @user = User.find_by_fb_uid(@fb_uid)
    @user.destroy if @user
    render :nothing => true; return
  end

  protected
   ...

Next, in your ‘protected’ section, add the following method which roughly corresponds to the PHP / pseudocode:

  def verify_uninstall_signature
    signature = ''
    keys = params.keys.sort
    keys.each do |key|
      next if key == 'fb_sig'
      next unless key.include?('fb_sig')
      key_name = key.gsub('fb_sig_', '')
      signature += key_name
      signature += '='
      signature += params[key]
    end
    signature += FACEBOOK['secret']
    calculated_sig = Digest::MD5.hexdigest(signature)
    #logger.info "\nUNINSTALL :: Signature (fb_sig param from facebook) :: #{params[:fb_sig]}" 
    #logger.info "\nUNINSTALL :: Signature String (pre-hash) :: #{signature}" 
    #logger.info "\nUNINSTALL :: MD5 Hashed Sig :: #{calculated_sig}" 
    if calculated_sig != params[:fb_sig]
      #logger.warn "\n\nUNINSTALL :: WARNING :: expected signatures did not match\n\n" 
      return false
    else
      #logger.warn "\n\nUNINSTALL :: SUCCESS!! Signatures matched.\n" 
    end
    return true
  end

This might be handy to add to ‘rfacebook’, but it sounds like the state of that project is in flux.

Also, you might have to add this entry to your config/routes.rb file:

  map.connect 'uninstalled', :controller => 'application', :action => 'uninstalled'

Happy uninstalling! :)

Comments
  1. Jim JonesFebruary 20, 2008 @ 01:37 PM

    Installation on the Facebook app platform leaves a lot to be desired. Here’s the issue:

    It appears that for whatever reason, when a user uninstalls your app, the uninstall procedure doesn’t get called. I don’t know if it’s Facebook that isn’t calling the uninstall url all the time or maybe there’s a server gliche where the app is unavailable at the time FB calls the uninstallation. Whatever the case, you’re going to end up with users in your system that you think are valid, but Facebook has them marked inactive users.

    This creates a problem; if you have any sort of app that displays comments, etc from other users, if you try to get the profile data for that user (a user for which you think is valid), you’ll receive an exception from Facebook stating there’s an invalid session id.

    I haven’t found an elegant way of handling this. The user’s data doesn’t appear to be requested until the user specific fields are referenced in the view. Do I catch an exception in the view (ugh)? Right now I have an internal flag for each user marking whether they are “active” or not. I have a process that parses my log files looking for invalid session id errors and if it finds one, it looks for the user id and marks that user as inactive.

    Maybe there is a simpler solution that I have overlooked? I am willing to to look retarded in front of the entire world to find out.

    Jim