module AuthlogicCrowdRest module Session def self.included(klass) klass.class_eval do extend Config include Methods end end module Config # The URL of your crowd rest API. Should be # something like https://localhost:8095/crowd/rest # # * Default: nil # * Accepts: String def crowd_base_url(value = nil) rw_config(:crowd_base_url, value) end alias_method :crowd_base_url=, :crowd_base_url # The name in crowd for your application # # * Default: nil # * Accepts: String def crowd_application_name(value = nil) rw_config(:crowd_application_name, value) end alias_method :crowd_application_name=, :crowd_application_name # The password in crowd for your application # # * Default: nil # * Accepts: String def crowd_application_password(value = nil) rw_config(:crowd_application_password, value) end alias_method :crowd_application_password=, :crowd_application_password # Once Crowd authentication has succeeded we need to find the user in the database. By default this just calls the # find_by_crowd_login method provided by ActiveRecord. If you have a more advanced set up and need to find users # differently specify your own method and define your logic in there. # # For example, if you allow users to store multiple crowd logins with their account, you might do something like: # # class User < ActiveRecord::Base # def self.find_by_crowd_login(login) # first(:conditions => ["#{CrowdLogin.table_name}.login = ?", login], :join => :crowd_logins) # end # end # # * Default: :find_by_crowd_login # * Accepts: Symbol def find_by_crowd_login_method(value = nil) rw_config(:find_by_crowd_login_method, value, :find_by_crowd_login) end alias_method :find_by_crowd_login_method=, :find_by_crowd_login_method end module Methods def self.included(klass) klass.class_eval do validate :validate_by_crowd_rest, :if => :authenticating_with_crowd_rest? attr_accessor :crowd_login attr_accessor :crowd_password end end # Hooks into credentials so that you can pass an :ldap_login and :ldap_password key. # Hooks into credentials to print out meaningful credentials for LDAP authentication. def credentials if authenticating_with_crowd_rest? details = {} details[:crowd_login] = crowd_login details[:crowd_password] = "" details else super end end def credentials=(value) super values = value.is_a?(Array) ? value : [value] hash = values.first.is_a?(Hash) ? values.first.with_indifferent_access : nil if !hash.nil? self.crowd_login = hash[:crowd_login] if hash.key?(:crowd_login) self.crowd_password = hash[:crowd_password] if hash.key?(:crowd_password) end end private def authenticating_with_crowd_rest? !(crowd_base_url.blank? || crowd_application_name.blank? || crowd_application_password.blank?) end def validate_by_crowd_rest self.invalid_password = false errors.add(:crowd_login, I18n.t('error_messages.crowd_login_blank', :default => "can not be blank")) if crowd_login.blank? errors.add(:crowd_password, I18n.t('error_messages.crowd_password_blank', :default => "can not be blank")) if crowd_password.blank? return if errors.count > 0 self.attempted_record = search_for_record(find_by_crowd_login_method, crowd_login) if attempted_record.blank? generalize_credentials_error_messages? ? add_general_credentials_error : errors.add("crowd_login", I18n.t('error_messages.crowd_login_not_found', :default => "is not valid")) return end if !(send( :verify_crowd_password, attempted_record)) self.invalid_password = true generalize_credentials_error_messages? ? add_general_credentials_error : errors.add("crowd_password", I18n.t('error_messages.crowd_password_invalid', :default => "is not valid")) return end end def verify_crowd_password(attempted_record) require 'net/http' require 'net/https' uri = URI.parse(send("crowd_base_url") + "/rest/usermanagement/latest/authentication") begin http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = uri.scheme == "https" http.start {|http| req = Net::HTTP::Post.new(uri.path + "?" + "username=#{crowd_login}") req.basic_auth send("crowd_application_name"), send("crowd_application_password") req.body="#{crowd_password}" req.add_field 'Content-Type', 'text/xml' resp, data = http.request(req) resp.code.to_i == 200 } rescue Interrupt errors.add(password_field, I18n.t('error_messages.crowd_password_timeout', :default=>"Timeout occurred when connecting to crowd")) end end def crowd_application_password self.class.crowd_application_password end def crowd_application_name self.class.crowd_application_name end def crowd_base_url self.class.crowd_base_url end def find_by_crowd_login_method self.class.find_by_crowd_login_method end end end end