Skip to content

Instantly share code, notes, and snippets.

@duhaime
Forked from zackrw/Gemfile
Created June 22, 2016 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save duhaime/5228b8afb37ed5ec2060cfdf8042bd12 to your computer and use it in GitHub Desktop.
Save duhaime/5228b8afb37ed5ec2060cfdf8042bd12 to your computer and use it in GitHub Desktop.
Yale CAS and user info with Rails (after security "upgrade" on LDAP)
Based largely on Bay Gross' Gist (https://gist.github.com/2054898), but adapted to not use LDAP (since new security features disable query by netid from external network).
Add or append these files to your Rails app to use Yale CAS Login and get user info.
# app/controllers/application_controller.rb
# Add this before filter to force CAS Authentication on all controllers + actions
before_filter CASClient::Frameworks::Rails::Filter, :unless => :skip_login?
# hack for skip_before_filter with CAS
# overwrite this method (with 'true') in any controller you want to skip CAS authentication
def skip_login?
false
end
#
## Add this block to the bottom of your config/environment.rb file
#
CASClient::Frameworks::Rails::Filter.configure(
:cas_base_url => "https://secure.its.yale.edu/cas/",
:username_session_key => :cas_user,
:extra_attributes_session_key => :cas_extra_attributes
)
#
## Add the rubycas-client gem to your Gemfile and run bundle install
#
gem 'rubycas-client'
gem 'mechanize'
# app/models/user.rb
require 'mechanize'
class User < ActiveRecord::Base
KNOWN_AS = /^\s*Known As:\s*$/i
EMAIL = /^\s*Email Address:\s*$/i
YEAR = /^\s*Class Year:\s*$/i
SCHOOL = /^\s*Division:\s*$/i
COLLEGE = /^\s*Residential College:\s*$/i
LEAD_SPACE = /^\s+/
TRAIL_SPACE = /\s+$/
before_validation :repair
validates_uniqueness_of :email, :message => 'email address conflicts'
validates_uniqueness_of :netid, :message => 'netid conflicts'
def make_cas_browser
browser = Mechanize.new
browser.get( 'https://secure.its.yale.edu/cas/login' )
form = browser.page.forms.first
form.username = *****YOUR_NETID*****
form.password = *****YOUR_PASSWORD*****
form.submit
browser
end
# update a user with the any extra available info from the yale directory
def repair
user_hash = self.get_user
self.merge user_hash
end
def get_user
browser = make_cas_browser
netid = self.netid
user_hash = {}
browser.get("http://directory.yale.edu/phonebook/index.htm?searchString=uid%3D#{netid}")
browser.page.search('tr').each do |tr|
field = tr.at('th').text
value = tr.at('td').text.sub(LEAD_SPACE, '').sub(TRAIL_SPACE, '')
case field
when KNOWN_AS
user_hash[:fname] = value
when EMAIL
user_hash[:email] = value
name = name_from_email(value)
user_hash[:given_name] = name[:first]
user_hash[:lname] = name[:last]
when YEAR
year = value.to_i
user_hash[:year] = year != 0 ? year : nil
when SCHOOL
user_hash[:school] = value
when COLLEGE
user_hash[:college] = value
end
end
# Use the name we got from the email if there is no "Known As" field.
if user_hash[:given_name] && !user_hash[:fname]
user_hash[:fname] = user_hash[:given_name]
end
user_hash
end
def merge(hash) # non-greedy merge for the user
hash.each do |key, val|
self[key] = val unless self[key]
end
end
end
# app/controllers/users_controller.rb
# authentication logic
def login
if session[:current_user] # already logged in
redirect_to '/'
elsif session[:cas_user]
user = User.find_or_create_by_netid( session[:cas_user] )
if user.netid && user.email # reject if we can't find an email
session[:current_user] = user
redirect_to '/'
else
redirect_to '/splash'
end
else # default
redirect_to '/splash'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment