Friday, March 02, 2007

FTGU - Rails on Windows - Single Sign On (SSO)

The name of the example rails application throughout this tutorial is "myapp", and there are several assumptions I make. You already have your project deployed to a production Windows Server running IIS and have a setup similar to the one I outline in my previous post on how to deploy Rails to Windows & IIS.
This example shows how to set up an intranet site to have integrated Windows domain Single Sign On (SSO).
Versions I Used

Windows Server 2003
IIS 6.0
Rails 1.2.2
Ruby 1.8.5

ISAPI_Rewrite

I use the full version in my setup. The cost was $99 (and definitely worth it).
I assume your app is already running and you have already configured ISAPI Rewrite
Integrated Windows Authentication

Open Internet Information Services (IIS) Manager
Open (local computer) and right click on "Web Sites". Go to 'Properties'.
In the "Directory Security" tab under "Authentication and access control" click on the "Edit" button.
Uncheck "Enable anonymous access", and check "Integrated Windows Authentication".
Open the "Services" Control Panel under "Administrative Tools".
Restart "IIS Admin Service", and answer "Yes" at the prompt.

ON MACHINES ACCESSING MYAPP:
* Internet Explorer: Early versions always enabled NTLM authentication.

Recent versions have NTLM authentication enabled only for computers in the "Intranet" Zone.
So you need to add the URL of your site to the Intranet Zone or Local Sites, and make sure Automatic Logon is enabled for that zone.
Otherwise you might try enabling auto logon globally but this is generally a very bad idea for security reasons.

This option can be found via Tools > Internet Options > Security > Custom Level > User Authentication > Logon
Set it to: Automatic logon with current username and password.

* Firefox: All URLs which support NTLM must explicitly be added to the network.automatic-ntlm-auth.trusted-uris preference.***

This option is not exposed via the Firefox UI, but can be found in about:config (type "about:config" into the URL feild in Firefox and hit enter).
Modify the preference to be the following string:
http://127.0.0.1/myapp (except make it a real URL, of course)

*** The Firefox fix for SSO hasn't worked quite right for me yet. But I stopped trying a while ago, so YMMV.

You need to download ldap_auth.
Extract it, and put the ldap_auth.rb file in the lib directory at the root of your project.

In your application controller:

class ApplicationController < ActionController::Base
include ConnectionHelper
end

Create a new file: app/helpers/connection_helper.rb

module ConnectionHelper
require 'ldap_auth'
def verify_membership
#LDAP connection info
host = 'MYLDAPSERVER01' #Your ldap server
dn = 'OU=Users,DC=mycompany,DC=local' #This works for me, but the dn may vary based on your LDAP structure and configuration
#Credentials of the user we are trying to authenticate
debug = false
if debug
session[:user_name] = 'DEV_TEST'
session[:group] = 'sgn1'
session[:admin] = 'admin'
return true
elsif session[:user_name] #already logged in? If you remove this they re-login (albeit transparently) on each trip to the server.
return true
else
account_name = 'username'
password = 'password'
connection = ''
unless LDAP::Auth.authenticate("#{account_name}@mycompany.local", password, dn, host) do |auth_obj|
groups = get_group_memberships(auth_obj)
if !groups.nil?
for group in groups
if group.to_s == 'Some_group_name_1'
my_group = 'sgn1'
break
elsif group.to_s == 'Some_group_name_2'
my_group = 'sgn2'
break
elsif group.to_s == 'Some_group_name_3'
my_group = 'sgn3'
break
elsif group.to_s == 'Admin_Group1'
session[:admin] = 'admin'
end
end
if !my_group.nil?
session[:group] = my_group
end
end
end
end
end
end

def get_group_memberships(auth_obj)
groups = nil
user_name = request.env["HTTP_X_ISRW_PROXY_AUTH_USER"]
if !user_name.nil?
session[:user_name] = user_name.from(4)
groups = auth_obj.groups_for(session[:user_name], 'sAMAccountName', 'memberOf')
end
return groups
end

end


And you're done. People will automatically be logged in when visiting your site.
You could put some hotness like this in your layout:

Welcome <%=session[:user_name]%>. <%if !session[:admin].nil?%>Logged in as <%=session[:admin]%> Admin<%elsif !session[:group].nil?%>Logged in as member of <%=session[:group]%> group<%else%>Insufficient access rights<%end%>.
<%if !session[:admin].nil?%>
<%=link_to("Switch to Admin Console >>", :controller=>'admin')%>
<%end%>


Suggestions? Please leave a comment!

5 hashings:

Peyton Family said...

Pete- I taged you in my latest blog entry to post 8 Unknown facts about yourself. It would be fun! I hope you and Mindee are doing well, and enjoying married life!! =)

Zimm said...

okay, newlywed...post!

Galtzo said...

Yeah... I'll get around to that soon! I've been developing new websites non-stop for weeks now (and trying to be a good husband at the same time as well).

Galtzo said...

I guess I just want to pay off my debt and retire, so I am working my keester off.

On a side note: I like the word keester. So I guess you could say I am a keester fan!

Galtzo said...

OK... you twisted my arm.

This blog began on Monday, September 27, 2004.
Hits since 2/20/2007:
free hit counters
free hit counters