Accessing DragonflyCMS cookies in Rails

At work, we run two DragonflyCMS sites (soon to become Nexos). As I do not do much in php except hack, when I was tasked with writing an application which used the authentication token generated by the DragonflyCMS site, I decided to do it in Ruby/Ruby on Rails. This posed a bit of a question. How do I check authentication and get the username out of a PHP based application?

The Rails Wiki had a good article on checking authentication vs a phpBB site, and that gave me the springboard that I needed.

I created a user, group, user_group and session model as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class User < ActiveRecord::Base

  establish_connection(
  :adapter => "mysql",
  :host => "localhost",
  :database => "dbname",
  :username => "username",
  :password => "somepassword")
  
  has_many                  :session
  has_many                  :group
  set_table_name            :cms_users 
  set_primary_key           :user_id

end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Group < ActiveRecord::Base

  establish_connection(
  :adapter => "mysql",
  :host => "localhost",
  :database => "dbname",
  :username => "username",
  :password => "somepassword")
  
    set_table_name          :cms_bbgroups
    belongs_to              :user
    set_primary_key         :group_id

end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class User_Group < ActiveRecord::Base

  establish_connection(
  :adapter => "mysql",
  :host => "localhost",
  :database => "dbname",
  :username => "username",
  :password => "somepassword")
  
  has_many                    :group
  belongs_to                  :user
  set_table_name              :cms_bbuser_group
  set_primary_key             :group_id

end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Sessions < ActiveRecord::Base

    establish_connection(
    :adapter => "mysql",
    :host => "localhost",
    :database => "dbname",
    :username => "someuser",
    :password => "otherpassword")
    
    belongs_to                  :user
    set_table_name              :cms_session
    set_primary_key             :uname
  
 end

This allows us to connect to the DragonflyCMS database, and get information about the users, groups and sessions. I pulled this directly from the wonderful wiki article.

As per the wiki, I set up a before filter in my application.rb – but I had to modify it quite a bit..

1
2
3
4
5
   before_filter :has_session

   def has_session()

      if session[:user_id].nil?

We have run the before filter and started the module to check the authentication. One of the things that I decided to do differently was check to see if we already had a session or not. It seemed to me that we could save some time by bypassing all of the work below if we already had the session set up. Now, we are read in the cookie:

1
         sid = Base64.decode64(cookies[:my_login]).split(':')

DragonflyCMS uses base64 encoding for it’s cookies, and also uses a ‘:’ as a field delimiter. So, we read the cookie in, decode it, and split it. We know that the user ID is the first field in the cookie, so we can do this:

1
2
3
        t = User.find_by_user_id(sid[0])

        if s = Sessions.find_by_uname(t.username)

We take the user ID out of the cookie, and cross reference it with the Users model to insure that the user really exists in the DragonflyCMS system. We then check if the username has a active session in the sessions table, and presto! we have a live user who is authenticated vs the dragonfly system.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
            if Person.find_by_name(t.username)
               session[:user_id] = Person.find_by_name(t.username).id
               session[:username] = t.username
            else
               @person = Person.new(:name => t.username)
               if @person.save
                  flash[:notice] = "Welcome to Application, " + @person.name + "! Please take the time to fill
in all of the required information."
                  redirect_to :controller => 'people', :action => 'edit', :id => @person.id
               else
                  #If we are here, it's a major WTF
                  flash[:notice] = "Some strange error occured. Perhaps you had chocolate chips in your cookies?"
                  render :controller => 'welcome', :action => 'index'

               end
            end

That huge chunk of code does a lot of stuff!

First, since we have a live user, we want to check to see if they have logged into our application before. I have a model called ‘Person’ which contains some information about the user that this application needs.

If they have not logged in before, we build them a new person object, and dump them into their edit page so they can fill out all of the neato little fields.

If they have logged in before, we create the session information in Rails which will allow us to authenticate them vs various models and functions as we need to.

1
2
3
4
5
         else
            session[:user_id] = nil
         end
      end
   end

If all else fails, we make the session information read Nil, so that next time a page loads or what have you, we check again to make sure that the have not logged in elsewhere.

I also have been thinking about ways of increasing security. DragonflyCMS records the IP address of the session’s user – it would be trivial to cross check that as well to insure that the cookie is not forged. As this application resides on an intranet, I have not implemented that level of cross-checking yet, but probably will in the future.