require 'els_token/module_inheritable_attributes' require 'els_token/els_user' require 'net/http' require 'uri' module ElsToken RootCA = "#{File.dirname(__FILE__)}/../cert/AOLMemberCA" def self.included(base) base.extend ClassMethods base.send :include, ElsToken::ModuleInheritableAttributes base.send :mattr_inheritable, :els_options base.instance_variable_set("@els_options", {}) end module ClassMethods # els_config expects a nice hash telling # it if it will have a fake user (handy for dev) # and the url of the openAM REST API. # { faker => { user => 'username', # :environments => ['dev','test'] }, # uri => 'https://openam.url' } # # class MyController # include ElsToken # els_config options_hash # end def els_config(options = {}) @els_options = options end end # authenticates against ELS and returns the user token def authenticate(username,password) begin response = els_http_request("/authenticate","uri=realm=aolcorporate&username=#{username}&password=#{password}") if response.code.eql? "200" # return the token response.body.chomp.sub(/token\.id=/,"") else raise response.error! end rescue Net::HTTPExceptions => e1 raise e1, "token retrieval failed for #{username}" rescue Exception => e # Do not expect these. Wrapping the exception so # as to not reveal the passed in password raise e, "unable to fetch token for #{username}" end end def is_token_valid?(token) response = els_http_request("/isTokenValid","tokenid=#{token}") if response.code.eql? "200" true else false end end #extract the token from the rack cookie def is_cookie_token_valid? return true if fake_it? token = cookies[self.class.els_options['cookie']] if token.nil? || !is_token_valid?(token) false else true end end # obtain a full ElsIdentity object def get_token_identity(token) response = els_http_request("/attributes","subjectid=#{token}") if response.code.eql? "200" ElsIdentity.new(response.body) else response.error! end end # When used inside a rack environment # will attempt to retrieve the user token # from the session cookie and return a full # identity def get_identity return fake_id if fake_it? begin if is_cookie_token_valid? get_token_identity cookies[self.class.els_options['cookie']] else raise "token is invalid" end rescue Exception => e raise e end end def method_missing(m, *args, &block) puts "Drop the crack pipe - There is no method called #{m}" end private def els_http_request(url_base_extension, query_string) uri = URI.parse(self.class.els_options['uri'] + url_base_extension) uri.query=query_string http = Net::HTTP.new(uri.host,uri.port) http.use_ssl = true # Override the default CA if option is # passed in if rootca = self.class.els_options[:cert] if File.exist? rootca http.ca_file = rootca elsif Dir.exist? rootca http.ca.path = rootca else # throw - if option passed in we are not # going to attempt to use the default cert raise "${rootca} cannot be found" end else http.ca_file = RootCA end http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.verify_depth = 5 request = Net::HTTP::Get.new(uri.request_uri) http.request(request) end def fake_it? self.class.els_options.has_key? 'faker' end def fake_id unless @fake_id id = ElsIdentity.new id.instance_variable_set("@roles",self.class.els_options['faker']['roles']) id.instance_variable_set("@mail",self.class.els_options['faker']['mail']) id.instance_variable_set("@last_name",self.class.els_options['faker']['last_name']) id.instance_variable_set("@first_name",self.class.els_options['faker']['first_name']) id.instance_variable_set("@uac",self.class.els_options['faker']['uac']) id.instance_variable_set("@dn",self.class.els_options['faker']['dn']) id.instance_variable_set("@common_name",self.class.els_options['faker']['common_name']) id.instance_variable_set("@employee_number",self.class.els_options['faker']['employee_number']) id.instance_variable_set("@display_name",self.class.els_options['faker']['display_name']) id.instance_variable_set("@token_id",self.class.els_options['faker']['token_id']) @fake_id = id end @fake_id end end