Skip to content

Generating a Rails and PunBB (and DokuWiki) shared cookie

This is another post for how I got something to work in the past week that’s been bugging me for a while. I recently wrote about how to get PHP to render correctly within a Rails app.

This post is about getting single-sign-on to work with a PunBB forum inside your Ruby on Rails application. I wanted to have a user who signs into the Rails app be ‘logged into’ the forum as well. This requires setting the cookie in the same way the PunBB code does it.

I have put this code in the bottom of my application.rb, so that it can be called from anywhere in the Rails app. I would suggest setting the cookie on login and clearing it on logout.

The forum config regex is based on the configuration parser in the PunBB SDK for Rails. It parses your existing PunBB cookie_name and cookie_seed from the PunBB install so you only need to keep that information in one place (PunBB).

The necessary php_serialize.rb file also comes from the /lib directory of the PunBB SDK plugin and is courtesy of Thomas Hurst (also available directly). It should be copied/placed into your own Rails app’s /lib directory and ‘require’d accordingly. The line below ending in \\ indicates a forced linewrap – and should be pulled back into a single line if you copy and paste this code.

  def set_shared_cookie
    # this is the punbb cookie
    # should be called on login from main site
    # the wiki uses the same cookie
    # setting it here allows unified login
    require 'digest/md5'
    forumconfig = get_forum_config_data() # private method at bottom
    # get forumuser info and set cookie
    forumuser = Forumaccount.find_by_username(@current_user.login)
    cookies[forumconfig[:cookie_name]] = {
      :value => PHP.serialize([forumuser.id, \\
         Digest::MD5.hexdigest("#{forumconfig[:cookie_seed]}#{forumuser.password}")]),
      :expires => 1.year.from_now
    }
  end

  def clear_shared_cookie
    # should be called on logout from main site
    require 'digest/md5'
    forumconfig = get_forum_config_data() # private method at bottom
    # set cookie for Guest
    cookies[forumconfig[:cookie_name]] = {
      :value => PHP.serialize([1,Digest::MD5.hexdigest("#{forumconfig[:cookie_seed]}Guest")]),
      :expires => 1.year.from_now
    }
  end

  # Uses regex to parse the php punbb config file
    # ahgsoftware.com/punbb_sdk/
    # make sure the config file exists
    # make sure 'RewriteEngine Off' is in /forum/.htaccess and wiki/.htaccess
  def get_forum_config_data
    config_hash = Hash.new
    c = File.read(File.join(RAILS_ROOT,'public/forum/config.php'))
    c.scan(/\$(\w*)\s*=\s*['"](.*)['"];/).each do |pair|
      config_hash[pair[0].to_sym] = pair[1]
    end
    return config_hash
  end

Of course, keeping your users in sync across the main Rails app and the Forum install is its own trick – and necessary before the above cookie injection will work. I’ve got Theforum and Forumaccount models that are wired to the PunBB database. I keep the usernames and passwords synced whenever users/passwords are created/deleted/updated.

database.yml

theforum_production:
  adapter: mysql
  database: punbb_production
  host: localhost
  username: xxxxxxxxx
  password: xxxxxxxxx

theforum.rb

class Theforum < ActiveRecord::Base
  self.abstract_class = true
  establish_connection "theforum_#{RAILS_ENV}"
end

forumaccount.rb

class Forumaccount < Theforum
  set_table_name :users

  def encrypt_and_save_new_password(password)
    write_attribute("password", self.sha1hashed(password))
    save
  end

  def sync_from_account(account)
    write_attribute("email", account.email)
    forumname = account.prefix+" "+account.first_name+" "+account.last_name
    write_attribute("realname", forumname)
    save
  end

  protected

  def sha1hashed(str)
    Digest::SHA1.hexdigest("#{str}")[0..39]
  end

end

A separate trick was to make DokuWiki look for and pay attention to the PunBB cookie we created at the beginning of the post. I got that for free with the shipping auth options in Dokuwiki. I simply pointed my Dokuwiki install at the PunBB install and the magic was complete.

Success: A login to the Rails app also sets a cookie for PunBB which is fully honored by Dokuwiki.

An additional benefit is now the entire site is under one codebase and can be installed/developed without moving as many pieces around.

Tags: - - - - -

View blog reactions

{ 1 } Comments