module AuthlogicConnect::Openid # This module is responsible for adding all of the OpenID goodness to the Authlogic::Session::Base class. module Session # Add a simple openid_identifier attribute and some validations for the field. def self.included(klass) klass.extend ClassMethods klass.class_eval do include InstanceMethods end end module ClassMethods # What method should we call to find a record by the openid_identifier? # This is useful if you want to store multiple openid_identifiers for a single record. # You could do something like: # # class User < ActiveRecord::Base # def self.find_by_openid_identifier(identifier) # user.first(:conditions => {:openid_identifiers => {:identifier => identifier}}) # end # end # # Obviously the above depends on what you are calling your assocition, etc. But you get the point. # # * Default: :find_by_openid_identifier # * Accepts: Symbol def find_by_openid_identifier_method(value = nil) rw_config(:find_by_openid_identifier_method, value, :find_by_openid_identifier) end alias_method :find_by_openid_identifier_method=, :find_by_openid_identifier_method # Add this in your Session object to Auto Register a new user using openid via sreg def auto_register(value=true) auto_register_value(value) end def auto_register_value(value=nil) rw_config(:auto_register,value,false) end alias_method :auto_register=,:auto_register end module InstanceMethods def self.included(klass) klass.class_eval do attr_reader :openid_identifier validate :validate_openid_error validate :validate_by_openid, :if => :authenticating_with_openid? end end # Hooks into credentials so that you can pass an :openid_identifier key. def credentials=(value) super values = value.is_a?(Array) ? value : [value] hash = values.first.is_a?(Hash) ? values.first.with_indifferent_access : nil self.openid_identifier = hash[:openid_identifier] if !hash.nil? && hash.key?(:openid_identifier) end def openid_identifier=(value) @openid_identifier = value.blank? ? nil : OpenIdAuthentication.normalize_identifier(value) @openid_error = nil rescue OpenIdAuthentication::InvalidOpenId => e @openid_identifier = nil @openid_error = e.message end # Cleaers out the block if we are authenticating with OpenID, so that we can redirect without a DoubleRender # error. def save_with_openid(&block) block = nil if !openid_identifier.blank? return block.nil? end private def authenticating_with_openid? attempted_record.nil? && errors.empty? && (!openid_identifier.blank? || (controller.params[:open_id_complete] && controller.params[:for_session])) end def find_by_openid_identifier_method self.class.find_by_openid_identifier_method end def find_by_openid_identifier_method self.class.find_by_openid_identifier_method end def auto_register? self.class.auto_register_value end def validate_by_openid self.remember_me = auth_params[:remember_me] == "true" if auth_params.key?(:remember_me) self.attempted_record = klass.send(find_by_openid_identifier_method, openid_identifier) if !attempted_record if auto_register? self.attempted_record = klass.new :openid_identifier => openid_identifier attempted_record.save do |result| if result true else false end end else errors.add(:openid_identifier, "did not match any users in our database, have you set up your account to use OpenID?") end return end controller.send(:authenticate_with_open_id, openid_identifier, :return_to => controller.url_for(:for_session => "1", :remember_me => remember_me?)) do |result, openid_identifier| if result.unsuccessful? errors.add_to_base(result.message) return end end end def validate_openid_error errors.add(:openid_identifier, @openid_error) if @openid_error end end end end