Using Authlogic and Active Directory together for user logins
I just built a Rails app to replace a crotchety old .NET tool (original coding time: spread out over months; Rails: 5-6 hours!). The tool has both public and protected access needs, with the internal users being part of an Active Directory network. I always use authlogic for my authentication needs, but had never needed to deal with AD before. I didn't want to piece together a hack of Apache, mod_ldap, and authlogic's basic auth support, since that just muddies the cleanliness of an otherwise very simple design!
So I found a post about authenticating with Active Directory in Ruby that handled the AD authentication side of things. That wasn't enough for authlogic though, which wants an AR model. I didn't want to make it into a table-less model (and I haven't jumped into Rails3 yet), so I needed another way.
Steve had a post about supporting a sudo-like feature with authlogic that matched my need to a good degree, so I adapted his idea to achieve the following.
First, I saved down the final ActiveDirectoryUser class and put it in app/models/active_directory_user.rb, with no changes.
I created a standard User model for authlogic that looks like this:
class User < ActiveRecord::Base
acts_as_authentic
def self.from_ad(ad_user)
user = User.find_by_login(ad_user.login)
if user.nil?
User.create! ad_user
end
return user
end
endMy UserSession model looks like:
class UserSession < Authlogic::Session::Base
def self.new_from_ad(params)
ad_user = ActiveDirectoryUser.authenticate(params[:login], params[:password])
return nil if ad_user.nil?
@current_user = User.from_ad(ad_user)
@user_session = UserSession.create!(@current_user)
return @user_session
end
endThen in my user_sessions_controller.rb, I have:
class UserSessionsController < ApplicationController
def new
@user_session = UserSession.new
end
def create
@user_session = UserSession.new_from_ad(params[:user_session])
if @user_session.nil?
@user_session = UserSession.new(params[:user_session])
end
if @user_session.save
flash[:notice] = "Login successful!"
redirect_to presentations_url
else
render :action => :new
end
end
def destroy
current_user_session.destroy
flash[:notice] = "Logout successful!"
redirect_back_or_default login_url
end
endAnd that's it! Now I can authenticate my AD users as needed, but still get all the authlogic goodness. Hope his helps some other folks leverage their enterprise network for their new Rails project. Enjoy!
