Skip to content
Browse files

new auto_register

  • Loading branch information...
1 parent 71bfdc2 commit b9621074a57088e687da7a250def47307337a514 Holden Thomas committed Nov 17, 2009
Showing with 1,917 additions and 2 deletions.
  1. +1 −0 app/models/user.rb
  2. +2 −0 app/models/user_session.rb
  3. +1 −1 config/environment.rb
  4. +1 −1 public/javascripts/openid-jquery.js
  5. +25 −0 vendor/plugins/authlogic_openid/CHANGELOG.rdoc
  6. +20 −0 vendor/plugins/authlogic_openid/MIT-LICENSE
  7. +38 −0 vendor/plugins/authlogic_openid/Manifest.txt
  8. +93 −0 vendor/plugins/authlogic_openid/README.rdoc
  9. +21 −0 vendor/plugins/authlogic_openid/Rakefile
  10. +1 −0 vendor/plugins/authlogic_openid/init.rb
  11. +6 −0 vendor/plugins/authlogic_openid/lib/authlogic_openid.rb
  12. +169 −0 vendor/plugins/authlogic_openid/lib/authlogic_openid/acts_as_authentic.rb
  13. +124 −0 vendor/plugins/authlogic_openid/lib/authlogic_openid/session.rb
  14. +51 −0 vendor/plugins/authlogic_openid/lib/authlogic_openid/version.rb
  15. +1 −0 vendor/plugins/authlogic_openid/rails/init.rb
  16. +105 −0 vendor/plugins/authlogic_openid/test/acts_as_authentic_test.rb
  17. +9 −0 vendor/plugins/authlogic_openid/test/fixtures/users.yml
  18. +35 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/CHANGELOG
  19. +231 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/README
  20. +22 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/Rakefile
  21. +11 −0 ...uthentication/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb
  22. +20 −0 .../test/libs/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb
  23. +26 −0 ...bs/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb
  24. +11 −0 ...nerators/upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb
  25. +18 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/init.rb
  26. +244 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication.rb
  27. +9 −0 ...ugins/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/association.rb
  28. +55 −0 .../plugins/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/db_store.rb
  29. +73 −0 ...s/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/mem_cache_store.rb
  30. +5 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/nonce.rb
  31. +23 −0 ...r/plugins/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/request.rb
  32. +20 −0 ...ins/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb
  33. +30 −0 ...plugins/authlogic_openid/test/libs/open_id_authentication/tasks/open_id_authentication_tasks.rake
  34. +151 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/test/mem_cache_store_test.rb
  35. +32 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/test/normalize_test.rb
  36. +46 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/test/open_id_authentication_test.rb
  37. +14 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/test/status_test.rb
  38. +17 −0 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/test/test_helper.rb
  39. +41 −0 vendor/plugins/authlogic_openid/test/libs/rails_trickery.rb
  40. +3 −0 vendor/plugins/authlogic_openid/test/libs/user.rb
  41. +2 −0 vendor/plugins/authlogic_openid/test/libs/user_session.rb
  42. +32 −0 vendor/plugins/authlogic_openid/test/session_test.rb
  43. +78 −0 vendor/plugins/authlogic_openid/test/test_helper.rb
View
1 app/models/user.rb
@@ -5,6 +5,7 @@ class User < ActiveRecord::Base
c.validate_email_field = false
# fetch email by ax
c.openid_required_fields = [:email,"http://axschema.org/contact/email"]
+ #c.openid_required_fields = [:language, "http://axschema.org/pref/language"]
#c.required_fields = ["http://axschema.org/contact/email"]
# fetch email by sreg
#c.optional_fields = ["email"]
View
2 app/models/user_session.rb
@@ -1,3 +1,5 @@
class UserSession < Authlogic::Session::Base
+ auto_register
logout_on_timeout true
+
end
View
2 config/environment.rb
@@ -26,7 +26,7 @@
# config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net"
# config.gem "aws-s3", :lib => "aws/s3"
config.gem "authlogic"
- config.gem "authlogic-oid", :lib => "authlogic_openid"
+ #config.gem "authlogic-oid", :lib => "authlogic_openid"
# Only load the plugins named here, in the order given. By default, all plugins
# in vendor/plugins are loaded in alphabetical order.
View
2 public/javascripts/openid-jquery.js
@@ -17,7 +17,7 @@ var providers_large = {
aol: {
name: 'AOL',
label: 'Enter your AOL screenname.',
- url: 'http://openid.aol.com/{username}/'
+ url: 'http://openid.aol.com/{username}'
},
openid: {
name: 'OpenID',
View
25 vendor/plugins/authlogic_openid/CHANGELOG.rdoc
@@ -0,0 +1,25 @@
+== 1.0.4 released 2009-5-14
+
+* Only authenticate with OpenID for models when a block is passed.
+* Check for the existence of an openid_identifier field before including the model. Allowing this library to only be activated when present.
+* Change required_field and optional_fields to openid_required_field and openid_optional_fields
+
+== 1.0.3 released 2009-4-3
+
+* Added find_by_openid_identifier config option for AuthlogicOpenid::Session.
+* Set the openid_identifier by the one passed back by the provider in AuthlogicOpenid::ActsAsAuthentic.
+* Added required_fields and optional_fields config options for AuthlogicOpenid::ActsAsAuthentic.
+* Added map_openid_registration, attributes_to_save, and map_saved_attributes methods to customize how attributes are set for AuthlogicOpenid::ActsAsAuthentic.
+* Make authenticating_with_openid? method a little more stringent to avoid trying to double authenticate. Ex: finding a session in the save block during a successful save.
+
+== 1.0.2 released 2009-3-30
+
+* Remove config block in initializer.
+
+== 1.0.1 released 2009-3-30
+
+* Change password validation option when included, and prepend the OpenID module.
+
+== 1.0.0 released 2009-3-30
+
+* Initial release
View
20 vendor/plugins/authlogic_openid/MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 Ben Johnson of Binary Logic (binarylogic.com)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
38 vendor/plugins/authlogic_openid/Manifest.txt
@@ -0,0 +1,38 @@
+CHANGELOG.rdoc
+MIT-LICENSE
+Manifest.txt
+README.rdoc
+Rakefile
+init.rb
+lib/authlogic_openid.rb
+lib/authlogic_openid/acts_as_authentic.rb
+lib/authlogic_openid/session.rb
+lib/authlogic_openid/version.rb
+test/acts_as_authentic_test.rb
+test/fixtures/users.yml
+test/libs/open_id_authentication/CHANGELOG
+test/libs/open_id_authentication/README
+test/libs/open_id_authentication/Rakefile
+test/libs/open_id_authentication/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb
+test/libs/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb
+test/libs/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb
+test/libs/open_id_authentication/generators/upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb
+test/libs/open_id_authentication/init.rb
+test/libs/open_id_authentication/lib/open_id_authentication.rb
+test/libs/open_id_authentication/lib/open_id_authentication/association.rb
+test/libs/open_id_authentication/lib/open_id_authentication/db_store.rb
+test/libs/open_id_authentication/lib/open_id_authentication/mem_cache_store.rb
+test/libs/open_id_authentication/lib/open_id_authentication/nonce.rb
+test/libs/open_id_authentication/lib/open_id_authentication/request.rb
+test/libs/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb
+test/libs/open_id_authentication/tasks/open_id_authentication_tasks.rake
+test/libs/open_id_authentication/test/mem_cache_store_test.rb
+test/libs/open_id_authentication/test/normalize_test.rb
+test/libs/open_id_authentication/test/open_id_authentication_test.rb
+test/libs/open_id_authentication/test/status_test.rb
+test/libs/open_id_authentication/test/test_helper.rb
+test/libs/rails_trickery.rb
+test/libs/user.rb
+test/libs/user_session.rb
+test/session_test.rb
+test/test_helper.rb
View
93 vendor/plugins/authlogic_openid/README.rdoc
@@ -0,0 +1,93 @@
+= Authlogic OpenID
+
+Authlogic OpenID is an extension of the Authlogic library to add OpenID support. Authlogic v2.0 introduced an enhanced API that makes "plugging in" alternate authentication methods as easy as installing a gem.
+
+== Helpful links
+
+* <b>Documentation:</b> http://authlogic-oid.rubyforge.org
+* <b>Authlogic:</b> http://github.com/binarylogic/authlogic
+* <b>Live example:</b> http://authlogicexample.binarylogic.com
+
+== Install and use
+
+=== 1. Make some simple changes to your database:
+
+ class AddUsersOpenidField < ActiveRecord::Migration
+ def self.up
+ add_column :users, :openid_identifier, :string
+ add_index :users, :openid_identifier
+
+ change_column :users, :login, :string, :default => nil, :null => true
+ change_column :users, :crypted_password, :string, :default => nil, :null => true
+ change_column :users, :password_salt, :string, :default => nil, :null => true
+ end
+
+ def self.down
+ remove_column :users, :openid_identifier
+
+ [:login, :crypted_password, :password_salt].each do |field|
+ User.all(:conditions => "#{field} is NULL").each { |user| user.update_attribute(field, "") if user.send(field).nil? }
+ change_column :users, field, :string, :default => "", :null => false
+ end
+ end
+ end
+
+=== 2. Install the openid_authentication plugin
+
+ $ script/plugin install git://github.com/rails/open_id_authentication.git
+ $ rake open_id_authentication:db:create
+
+For more information on how to configure the plugin, checkout it's README: http://github.com/rails/open_id_authentication/tree/master
+
+=== 3. Install the Authlogic Openid gem
+
+ $ sudo gem install authlogic-oid
+
+Now add the gem dependency in your config:
+
+ config.gem "authlogic-oid", :lib => "authlogic_openid"
+
+Or for older version of rails, install it as a plugin:
+
+ $ script/plugin install git://github.com/binarylogic/authlogic_openid.git
+
+=== 4. Make sure you save your objects properly
+
+You only need to save your objects this way if you want the user to authenticate with their OpenID provider.
+
+That being said, you probably want to do this in your controllers. You should do this for BOTH your User objects and UserSession objects (assuming you are authenticating users). It should look something like this:
+
+ @user_session.save do |result|
+ if result
+ flash[:notice] = "Login successful!"
+ redirect_back_or_default account_url
+ else
+ render :action => :new
+ end
+ end
+
+You should save your @user objects this way as well, because you also want the user to verify that they own the OpenID identifier that they supplied.
+
+Notice we are saving with a block. Why? Because we need to redirect the user to their OpenID provider so that they can authenticate. When we do this, we don't want to execute that block of code, because if we do, we will get a DoubleRender error. This lets us skip that entire block and send the user along their way without any problems.
+
+That's it! The rest is taken care of for you.
+
+== Redirecting from the models?
+
+If you are interested, I explain myself below. Regardless, if you don't feel comfortable with the organization of the logic,you can easily do this using the traditional method. As you saw in the setup instructions, this library leverages the open_id_authentication rails plugin. After the user has been authenticated just do this:
+
+ UserSession.create(@user)
+
+It's that simple. For more information there is a great OpenID tutorial at: http://railscasts.com/episodes/68-openid-authentication
+
+Now, here are my thoughts on the subject:
+
+You are probably thinking: "Ben, you can't handle controller responsibilities in models". I agree with you on that comment, but my personal opinion is that these are not controller responsibilities. The fact that OpenID authentication requires a redirect should not effect the location of the logic / code. It's all part of the authentication process, which is the entire purpose of this library. This library is not one big module of code, its a collection of modules that all deal with OpenID authentication. These modules get included wherever it makes sense. That's the whole idea behind modules. To group common logic.
+
+Let's take a step back and look at the traditional method of OpenID authentication in rails. What if you wanted to authenticate with OpenID in multiple controllers in your application (Ex: registration and loggin in)? You would probably pull out the common code into a module and include it in the respective controllers. Even better, you might create a class that elegantly handles this process and then place it in your lib directory. Then, if you really wanted to be slick, you might take it another step further and have your models trigger this class during certain actions. Then what do we have? This exact library, that's exactly what this is.
+
+The last thing I will leave you with, to get you thinking, is... where do sweepers lie in the MVC pattern? Without this, things like caching would be extremely difficult. There is a big difference between misplacing code / logic, and organizing logic into a separate module and hooking it in using the API provided by your models. Especially when the logic needs to be triggered by actions invoked on models.
+
+Regardless, if I still haven't convinced you, I hope this library is of some benefit to you. At the very least an example of how to extend Authlogic.
+
+Copyright (c) 2009 Ben Johnson of [Binary Logic](http://www.binarylogic.com), released under the MIT license
View
21 vendor/plugins/authlogic_openid/Rakefile
@@ -0,0 +1,21 @@
+ENV['RDOCOPT'] = "-S -f html -T hanna"
+
+require "rubygems"
+require "hoe"
+require File.dirname(__FILE__) << "/lib/authlogic_openid/version"
+
+Hoe.new("Authlogic OpenID", AuthlogicOpenid::Version::STRING) do |p|
+ p.name = "authlogic-oid"
+ p.rubyforge_name = "authlogic-oid"
+ p.author = "Ben Johnson of Binary Logic"
+ p.email = 'bjohnson@binarylogic.com'
+ p.summary = "Extension of the Authlogic library to add OpenID support."
+ p.description = "Extension of the Authlogic library to add OpenID support."
+ p.url = "http://github.com/binarylogic/authlogic_openid"
+ p.history_file = "CHANGELOG.rdoc"
+ p.readme_file = "README.rdoc"
+ p.extra_rdoc_files = ["CHANGELOG.rdoc", "README.rdoc"]
+ p.remote_rdoc_dir = ''
+ p.test_globs = ["test/*/test_*.rb", "test/*_test.rb", "test/*/*_test.rb"]
+ p.extra_deps = %w(authlogic)
+end
View
1 vendor/plugins/authlogic_openid/init.rb
@@ -0,0 +1 @@
+require File.dirname(__FILE__) + "/rails/init.rb"
View
6 vendor/plugins/authlogic_openid/lib/authlogic_openid.rb
@@ -0,0 +1,6 @@
+require "authlogic_openid/version"
+require "authlogic_openid/acts_as_authentic"
+require "authlogic_openid/session"
+
+ActiveRecord::Base.send(:include, AuthlogicOpenid::ActsAsAuthentic)
+Authlogic::Session::Base.send(:include, AuthlogicOpenid::Session)
View
169 vendor/plugins/authlogic_openid/lib/authlogic_openid/acts_as_authentic.rb
@@ -0,0 +1,169 @@
+# This module is responsible for adding OpenID functionality to Authlogic. Checkout the README for more info and please
+# see the sub modules for detailed documentation.
+module AuthlogicOpenid
+ # This module is responsible for adding in the OpenID functionality to your models. It hooks itself into the
+ # acts_as_authentic method provided by Authlogic.
+ module ActsAsAuthentic
+ # Adds in the neccesary modules for acts_as_authentic to include and also disabled password validation if
+ # OpenID is being used.
+ def self.included(klass)
+ klass.class_eval do
+ extend Config
+ add_acts_as_authentic_module(Methods, :prepend)
+ end
+ end
+
+ module Config
+ # Some OpenID providers support a lightweight profile exchange protocol, for those that do, you can require
+ # certain fields. This is convenient for new registrations, as it will basically fill out the fields in the
+ # form for them, so they don't have to re-type information already stored with their OpenID account.
+ #
+ # For more info and what fields you can use see: http://openid.net/specs/openid-simple-registration-extension-1_0.html
+ #
+ # * <tt>Default:</tt> []
+ # * <tt>Accepts:</tt> Array of symbols
+ def openid_required_fields(value = nil)
+ rw_config(:openid_required_fields, value, [])
+ end
+ alias_method :openid_required_fields=, :openid_required_fields
+
+ # Same as required_fields, but optional instead.
+ #
+ # * <tt>Default:</tt> []
+ # * <tt>Accepts:</tt> Array of symbols
+ def openid_optional_fields(value = nil)
+ rw_config(:openid_optional_fields, value, [])
+ end
+ alias_method :openid_optional_fields=, :openid_optional_fields
+ end
+
+ module Methods
+ # Set up some simple validations
+ def self.included(klass)
+ return if !klass.column_names.include?("openid_identifier")
+
+ klass.class_eval do
+ validates_uniqueness_of :openid_identifier, :scope => validations_scope, :if => :using_openid?
+ validate :validate_openid
+ validates_length_of_password_field_options validates_length_of_password_field_options.merge(:if => :validate_password_with_openid?)
+ validates_confirmation_of_password_field_options validates_confirmation_of_password_field_options.merge(:if => :validate_password_with_openid?)
+ validates_length_of_password_confirmation_field_options validates_length_of_password_confirmation_field_options.merge(:if => :validate_password_with_openid?)
+ end
+ end
+
+ # Set the openid_identifier field and also resets the persistence_token if this value changes.
+ def openid_identifier=(value)
+ write_attribute(:openid_identifier, value.blank? ? nil : OpenIdAuthentication.normalize_identifier(value))
+ reset_persistence_token if openid_identifier_changed?
+ rescue OpenIdAuthentication::InvalidOpenId => e
+ @openid_error = e.message
+ end
+
+ # This is where all of the magic happens. This is where we hook in and add all of the OpenID sweetness.
+ #
+ # I had to take this approach because when authenticating with OpenID nonces and what not are stored in database
+ # tables. That being said, the whole save process for ActiveRecord is wrapped in a transaction. Trying to authenticate
+ # with OpenID in a transaction is not good because that transaction be get rolled back, thus reversing all of the OpenID
+ # inserts and making OpenID authentication fail every time. So We need to step outside of the transaction and do our OpenID
+ # madness.
+ #
+ # Another advantage of taking this approach is that we can set fields from their OpenID profile before we save the record,
+ # if their OpenID provider supports it.
+ def save(perform_validation = true, &block)
+ return false if perform_validation && block_given? && authenticate_with_openid? && !authenticate_with_openid
+ result = super
+ yield(result) if block_given?
+ result
+ end
+
+ private
+ def authenticate_with_openid
+ @openid_error = nil
+
+ if !openid_complete?
+ session_class.controller.session[:openid_attributes] = attributes_to_save
+ else
+ map_saved_attributes(session_class.controller.session[:openid_attributes])
+ session_class.controller.session[:openid_attributes] = nil
+ end
+
+ options = {}
+ options[:required] = self.class.openid_required_fields
+ options[:optional] = self.class.openid_optional_fields
+ options[:return_to] = session_class.controller.url_for(:for_model => "1")
+
+ session_class.controller.send(:authenticate_with_open_id, openid_identifier, options) do |result, openid_identifier, registration|
+ if result.unsuccessful?
+ @openid_error = result.message
+ else
+ self.openid_identifier = openid_identifier
+ map_openid_registration(registration)
+ end
+
+ return true
+ end
+
+ return false
+ end
+
+ # Override this method to map the OpenID registration fields with fields in your model. See the required_fields and
+ # optional_fields configuration options to enable this feature.
+ #
+ # Basically you will get a hash of values passed as a single argument. Then just map them as you see fit. Check out
+ # the source of this method for an example.
+ def map_openid_registration(registration) # :doc:
+ self.name ||= registration[:fullname] if respond_to?(:name) && !registration[:fullname].blank?
+ self.first_name ||= registration[:fullname].split(" ").first if respond_to?(:first_name) && !registration[:fullname].blank?
+ self.last_name ||= registration[:fullname].split(" ").last if respond_to?(:last_name) && !registration[:last_name].blank?
+ end
+
+ # This method works in conjunction with map_saved_attributes.
+ #
+ # Let's say a user fills out a registration form, provides an OpenID and submits the form. They are then redirected to their
+ # OpenID provider. All is good and they are redirected back. All of those fields they spent time filling out are forgetten
+ # and they have to retype them all. To avoid this, AuthlogicOpenid saves all of these attributes in the session and then
+ # attempts to restore them. See the source for what attributes it saves. If you need to block more attributes, or save
+ # more just override this method and do whatever you want.
+ def attributes_to_save # :doc:
+ attrs_to_save = attributes.clone.delete_if do |k, v|
+ [:id, :password, crypted_password_field, password_salt_field, :persistence_token, :perishable_token, :single_access_token, :login_count,
+ :failed_login_count, :last_request_at, :current_login_at, :last_login_at, :current_login_ip, :last_login_ip, :created_at,
+ :updated_at, :lock_version].include?(k.to_sym)
+ end
+ attrs_to_save.merge!(:password => password, :password_confirmation => password_confirmation)
+ end
+
+ # This method works in conjunction with attributes_to_save. See that method for a description of the why these methods exist.
+ #
+ # If the default behavior of this method is not sufficient for you because you have attr_protected or attr_accessible then
+ # override this method and set them individually. Maybe something like this would be good:
+ #
+ # attrs.each do |key, value|
+ # send("#{key}=", value)
+ # end
+ def map_saved_attributes(attrs) # :doc:
+ self.attributes = attrs
+ end
+
+ def validate_openid
+ errors.add(:openid_identifier, "had the following error: #{@openid_error}") if @openid_error
+ end
+
+ def using_openid?
+ respond_to?(:openid_identifier) && !openid_identifier.blank?
+ end
+
+ def openid_complete?
+ session_class.controller.params[:open_id_complete] && session_class.controller.params[:for_model]
+ end
+
+ def authenticate_with_openid?
+ session_class.activated? && ((using_openid? && openid_identifier_changed?) || openid_complete?)
+ end
+
+ def validate_password_with_openid?
+ !using_openid? && require_password?
+ end
+ end
+ end
+end
View
124 vendor/plugins/authlogic_openid/lib/authlogic_openid/session.rb
@@ -0,0 +1,124 @@
+module AuthlogicOpenid
+ # 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.class_eval do
+ extend Config
+ include Methods
+ end
+ end
+
+ module Config
+ # 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.
+ #
+ # * <tt>Default:</tt> :find_by_openid_identifier
+ # * <tt>Accepts:</tt> 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 Methods
+ 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(&block)
+ block = nil if !openid_identifier.blank?
+ super(&block)
+ 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 = controller.params[:remember_me] == "true" if controller.params.key?(:remember_me)
+ 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
+
+ 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
+
+ if ! attempted_record.save
+ errors.add(:openid_identifier, "error auto-registering new openid account")
+ end
+ return
+ else
+ errors.add(:openid_identifier, "did not match any users in our database, have you set up your account to use OpenID?")
+ return
+ end
+ end
+ end
+ end
+
+ def validate_openid_error
+ errors.add(:openid_identifier, @openid_error) if @openid_error
+ end
+ end
+ end
+end
View
51 vendor/plugins/authlogic_openid/lib/authlogic_openid/version.rb
@@ -0,0 +1,51 @@
+module AuthlogicOpenid
+ # A class for describing the current version of a library. The version
+ # consists of three parts: the +major+ number, the +minor+ number, and the
+ # +tiny+ (or +patch+) number.
+ class Version
+ include Comparable
+
+ # A convenience method for instantiating a new Version instance with the
+ # given +major+, +minor+, and +tiny+ components.
+ def self.[](major, minor, tiny)
+ new(major, minor, tiny)
+ end
+
+ attr_reader :major, :minor, :tiny
+
+ # Create a new Version object with the given components.
+ def initialize(major, minor, tiny)
+ @major, @minor, @tiny = major, minor, tiny
+ end
+
+ # Compare this version to the given +version+ object.
+ def <=>(version)
+ to_i <=> version.to_i
+ end
+
+ # Converts this version object to a string, where each of the three
+ # version components are joined by the '.' character. E.g., 2.0.0.
+ def to_s
+ @to_s ||= [@major, @minor, @tiny].join(".")
+ end
+
+ # Converts this version to a canonical integer that may be compared
+ # against other version objects.
+ def to_i
+ @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
+ end
+
+ def to_a
+ [@major, @minor, @tiny]
+ end
+
+ MAJOR = 1
+ MINOR = 0
+ TINY = 4
+
+ # The current version as a Version instance
+ CURRENT = new(MAJOR, MINOR, TINY)
+ # The current version as a String
+ STRING = CURRENT.to_s
+ end
+end
View
1 vendor/plugins/authlogic_openid/rails/init.rb
@@ -0,0 +1 @@
+require "authlogic_openid"
View
105 vendor/plugins/authlogic_openid/test/acts_as_authentic_test.rb
@@ -0,0 +1,105 @@
+require File.dirname(__FILE__) + '/test_helper.rb'
+
+class ActsAsAuthenticTest < ActiveSupport::TestCase
+ def test_included
+ assert User.send(:acts_as_authentic_modules).include?(AuthlogicOpenid::ActsAsAuthentic::Methods)
+ assert_equal :validate_password_with_openid?, User.validates_length_of_password_field_options[:if]
+ assert_equal :validate_password_with_openid?, User.validates_confirmation_of_password_field_options[:if]
+ assert_equal :validate_password_with_openid?, User.validates_length_of_password_confirmation_field_options[:if]
+ end
+
+ def test_password_not_required_on_create
+ user = User.new
+ user.login = "sweet"
+ user.email = "a@a.com"
+ user.openid_identifier = "https://me.yahoo.com/a/9W0FJjRj0o981TMSs0vqVxPdmMUVOQ--"
+ assert !user.save {} # because we are redirecting, the user was NOT saved
+ assert redirecting_to_yahoo?
+ end
+
+ def test_password_required_on_create
+ user = User.new
+ user.login = "sweet"
+ user.email = "a@a.com"
+ assert !user.save
+ assert user.errors.on(:password)
+ assert user.errors.on(:password_confirmation)
+ end
+
+ def test_password_not_required_on_update
+ ben = users(:ben)
+ assert_nil ben.crypted_password
+ assert ben.save
+ end
+
+ def test_password_required_on_update
+ ben = users(:ben)
+ ben.openid_identifier = nil
+ assert_nil ben.crypted_password
+ assert !ben.save
+ assert ben.errors.on(:password)
+ assert ben.errors.on(:password_confirmation)
+ end
+
+ def test_validates_uniqueness_of_openid_identifier
+ u = User.new(:openid_identifier => "bens_identifier")
+ assert !u.valid?
+ assert u.errors.on(:openid_identifier)
+ end
+
+ def test_setting_openid_identifier_changed_persistence_token
+ ben = users(:ben)
+ old_persistence_token = ben.persistence_token
+ ben.openid_identifier = "new"
+ assert_not_equal old_persistence_token, ben.persistence_token
+ end
+
+ def test_invalid_openid_identifier
+ u = User.new(:openid_identifier => "%")
+ assert !u.valid?
+ assert u.errors.on(:openid_identifier)
+ end
+
+ def test_blank_openid_identifer_gets_set_to_nil
+ u = User.new(:openid_identifier => "")
+ assert_nil u.openid_identifier
+ end
+
+ def test_updating_with_openid
+ ben = users(:ben)
+ ben.openid_identifier = "https://me.yahoo.com/a/9W0FJjRj0o981TMSs0vqVxPdmMUVOQ--"
+ assert !ben.save {} # because we are redirecting
+ assert redirecting_to_yahoo?
+ end
+
+ def test_updating_without_openid
+ ben = users(:ben)
+ ben.openid_identifier = nil
+ ben.password = "test"
+ ben.password_confirmation = "test"
+ assert ben.save
+ assert !redirecting_to_yahoo?
+ end
+
+ def test_updating_without_validation
+ ben = users(:ben)
+ ben.openid_identifier = "https://me.yahoo.com/a/9W0FJjRj0o981TMSs0vqVxPdmMUVOQ--"
+ assert ben.save(false)
+ assert !redirecting_to_yahoo?
+ end
+
+ def test_updating_without_a_block
+ ben = users(:ben)
+ ben.openid_identifier = "https://me.yahoo.com/a/9W0FJjRj0o981TMSs0vqVxPdmMUVOQ--"
+ assert ben.save
+ ben.reload
+ assert_equal "https://me.yahoo.com/a/9W0FJjRj0o981TMSs0vqVxPdmMUVOQ--", ben.openid_identifier
+ end
+
+ def test_updating_while_not_activated
+ UserSession.controller = nil
+ ben = users(:ben)
+ ben.openid_identifier = "https://me.yahoo.com/a/9W0FJjRj0o981TMSs0vqVxPdmMUVOQ--"
+ assert ben.save {}
+ end
+end
View
9 vendor/plugins/authlogic_openid/test/fixtures/users.yml
@@ -0,0 +1,9 @@
+ben:
+ login: bjohnson
+ persistence_token: 6cde0674657a8a313ce952df979de2830309aa4c11ca65805dd00bfdc65dbcc2f5e36718660a1d2e68c1a08c276d996763985d2f06fd3d076eb7bc4d97b1e317
+ single_access_token: <%= Authlogic::Random.friendly_token %>
+ perishable_token: <%= Authlogic::Random.friendly_token %>
+ openid_identifier: bens_identifier
+ email: bjohnson@binarylogic.com
+ first_name: Ben
+ last_name: Johnson
View
35 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/CHANGELOG
@@ -0,0 +1,35 @@
+* Fake HTTP method from OpenID server since they only support a GET. Eliminates the need to set an extra route to match the server's reply. [Josh Peek]
+
+* OpenID 2.0 recommends that forms should use the field name "openid_identifier" rather than "openid_url" [Josh Peek]
+
+* Return open_id_response.display_identifier to the application instead of .endpoints.claimed_id. [nbibler]
+
+* Add Timeout protection [Rick]
+
+* An invalid identity url passed through authenticate_with_open_id will no longer raise an InvalidOpenId exception. Instead it will return Result[:missing] to the completion block.
+
+* Allow a return_to option to be used instead of the requested url [Josh Peek]
+
+* Updated plugin to use Ruby OpenID 2.x.x [Josh Peek]
+
+* Tied plugin to ruby-openid 1.1.4 gem until we can make it compatible with 2.x [DHH]
+
+* Use URI instead of regexps to normalize the URL and gain free, better matching #8136 [dkubb]
+
+* Allow -'s in #normalize_url [Rick]
+
+* remove instance of mattr_accessor, it was breaking tests since they don't load ActiveSupport. Fix Timeout test [Rick]
+
+* Throw a InvalidOpenId exception instead of just a RuntimeError when the URL can't be normalized [DHH]
+
+* Just use the path for the return URL, so extra query parameters don't interfere [DHH]
+
+* Added a new default database-backed store after experiencing trouble with the filestore on NFS. The file store is still available as an option [DHH]
+
+* Added normalize_url and applied it to all operations going through the plugin [DHH]
+
+* Removed open_id? as the idea of using the same input box for both OpenID and username has died -- use using_open_id? instead (which checks for the presence of params[:openid_url] by default) [DHH]
+
+* Added OpenIdAuthentication::Result to make it easier to deal with default situations where you don't care to do something particular for each error state [DHH]
+
+* Stop relying on root_url being defined, we can just grab the current url instead [DHH]
View
231 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/README
@@ -0,0 +1,231 @@
+OpenIdAuthentication
+====================
+
+Provides a thin wrapper around the excellent ruby-openid gem from JanRan. Be sure to install that first:
+
+ gem install ruby-openid
+
+To understand what OpenID is about and how it works, it helps to read the documentation for lib/openid/consumer.rb
+from that gem.
+
+The specification used is http://openid.net/specs/openid-authentication-2_0.html.
+
+
+Prerequisites
+=============
+
+OpenID authentication uses the session, so be sure that you haven't turned that off. It also relies on a number of
+database tables to store the authentication keys. So you'll have to run the migration to create these before you get started:
+
+ rake open_id_authentication:db:create
+
+Or, use the included generators to install or upgrade:
+
+ ./script/generate open_id_authentication_tables MigrationName
+ ./script/generate upgrade_open_id_authentication_tables MigrationName
+
+Alternatively, you can use the file-based store, which just relies on on tmp/openids being present in RAILS_ROOT. But be aware that this store only works if you have a single application server. And it's not safe to use across NFS. It's recommended that you use the database store if at all possible. To use the file-based store, you'll also have to add this line to your config/environment.rb:
+
+ OpenIdAuthentication.store = :file
+
+This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations.
+If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb.
+
+The plugin also expects to find a root_url method that points to the home page of your site. You can accomplish this by using a root route in config/routes.rb:
+
+ map.root :controller => 'articles'
+
+This plugin relies on Rails Edge revision 6317 or newer.
+
+
+Example
+=======
+
+This example is just to meant to demonstrate how you could use OpenID authentication. You might well want to add
+salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point,
+not a destination.
+
+Note that the User model referenced in the simple example below has an 'identity_url' attribute. You will want to add the same or similar field to whatever
+model you are using for authentication.
+
+Also of note is the following code block used in the example below:
+
+ authenticate_with_open_id do |result, identity_url|
+ ...
+ end
+
+In the above code block, 'identity_url' will need to match user.identity_url exactly. 'identity_url' will be a string in the form of 'http://example.com' -
+If you are storing just 'example.com' with your user, the lookup will fail.
+
+There is a handy method in this plugin called 'normalize_url' that will help with validating OpenID URLs.
+
+ OpenIdAuthentication.normalize_url(user.identity_url)
+
+The above will return a standardized version of the OpenID URL - the above called with 'example.com' will return 'http://example.com/'
+It will also raise an InvalidOpenId exception if the URL is determined to not be valid.
+Use the above code in your User model and validate OpenID URLs before saving them.
+
+config/routes.rb
+
+ map.root :controller => 'articles'
+ map.resource :session
+
+
+app/views/sessions/new.erb
+
+ <% form_tag(session_url) do %>
+ <p>
+ <label for="name">Username:</label>
+ <%= text_field_tag "name" %>
+ </p>
+
+ <p>
+ <label for="password">Password:</label>
+ <%= password_field_tag %>
+ </p>
+
+ <p>
+ ...or use:
+ </p>
+
+ <p>
+ <label for="openid_identifier">OpenID:</label>
+ <%= text_field_tag "openid_identifier" %>
+ </p>
+
+ <p>
+ <%= submit_tag 'Sign in', :disable_with => "Signing in&hellip;" %>
+ </p>
+ <% end %>
+
+app/controllers/sessions_controller.rb
+ class SessionsController < ApplicationController
+ def create
+ if using_open_id?
+ open_id_authentication
+ else
+ password_authentication(params[:name], params[:password])
+ end
+ end
+
+
+ protected
+ def password_authentication(name, password)
+ if @current_user = @account.users.authenticate(params[:name], params[:password])
+ successful_login
+ else
+ failed_login "Sorry, that username/password doesn't work"
+ end
+ end
+
+ def open_id_authentication
+ authenticate_with_open_id do |result, identity_url|
+ if result.successful?
+ if @current_user = @account.users.find_by_identity_url(identity_url)
+ successful_login
+ else
+ failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
+ end
+ else
+ failed_login result.message
+ end
+ end
+ end
+
+
+ private
+ def successful_login
+ session[:user_id] = @current_user.id
+ redirect_to(root_url)
+ end
+
+ def failed_login(message)
+ flash[:error] = message
+ redirect_to(new_session_url)
+ end
+ end
+
+
+
+If you're fine with the result messages above and don't need individual logic on a per-failure basis,
+you can collapse the case into a mere boolean:
+
+ def open_id_authentication
+ authenticate_with_open_id do |result, identity_url|
+ if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url)
+ successful_login
+ else
+ failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})")
+ end
+ end
+ end
+
+
+Simple Registration OpenID Extension
+====================================
+
+Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension
+
+You can support it in your app by changing #open_id_authentication
+
+ def open_id_authentication(identity_url)
+ # Pass optional :required and :optional keys to specify what sreg fields you want.
+ # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
+ authenticate_with_open_id(identity_url,
+ :required => [ :nickname, :email ],
+ :optional => :fullname) do |result, identity_url, registration|
+ case result.status
+ when :missing
+ failed_login "Sorry, the OpenID server couldn't be found"
+ when :invalid
+ failed_login "Sorry, but this does not appear to be a valid OpenID"
+ when :canceled
+ failed_login "OpenID verification was canceled"
+ when :failed
+ failed_login "Sorry, the OpenID verification failed"
+ when :successful
+ if @current_user = @account.users.find_by_identity_url(identity_url)
+ assign_registration_attributes!(registration)
+
+ if current_user.save
+ successful_login
+ else
+ failed_login "Your OpenID profile registration failed: " +
+ @current_user.errors.full_messages.to_sentence
+ end
+ else
+ failed_login "Sorry, no user by that identity URL exists"
+ end
+ end
+ end
+ end
+
+ # registration is a hash containing the valid sreg keys given above
+ # use this to map them to fields of your user model
+ def assign_registration_attributes!(registration)
+ model_to_registration_mapping.each do |model_attribute, registration_attribute|
+ unless registration[registration_attribute].blank?
+ @current_user.send("#{model_attribute}=", registration[registration_attribute])
+ end
+ end
+ end
+
+ def model_to_registration_mapping
+ { :login => 'nickname', :email => 'email', :display_name => 'fullname' }
+ end
+
+Attribute Exchange OpenID Extension
+===================================
+
+Some OpenID providers also support the OpenID AX (attribute exchange) protocol for exchanging identity information between endpoints. See more: http://openid.net/specs/openid-attribute-exchange-1_0.html
+
+Accessing AX data is very similar to the Simple Registration process, described above -- just add the URI identifier for the AX field to your :optional or :required parameters. For example:
+
+ authenticate_with_open_id(identity_url,
+ :required => [ :email, 'http://schema.openid.net/birthDate' ]) do |result, identity_url, registration|
+
+This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate'
+
+
+
+Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
View
22 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/Rakefile
@@ -0,0 +1,22 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the open_id_authentication plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the open_id_authentication plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'OpenIdAuthentication'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
View
11 ...ation/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb
@@ -0,0 +1,11 @@
+class OpenIdAuthenticationTablesGenerator < Rails::Generator::NamedBase
+ def initialize(runtime_args, runtime_options = {})
+ super
+ end
+
+ def manifest
+ record do |m|
+ m.migration_template 'migration.rb', 'db/migrate'
+ end
+ end
+end
View
20 ...bs/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb
@@ -0,0 +1,20 @@
+class <%= class_name %> < ActiveRecord::Migration
+ def self.up
+ create_table :open_id_authentication_associations, :force => true do |t|
+ t.integer :issued, :lifetime
+ t.string :handle, :assoc_type
+ t.binary :server_url, :secret
+ end
+
+ create_table :open_id_authentication_nonces, :force => true do |t|
+ t.integer :timestamp, :null => false
+ t.string :server_url, :null => true
+ t.string :salt, :null => false
+ end
+ end
+
+ def self.down
+ drop_table :open_id_authentication_associations
+ drop_table :open_id_authentication_nonces
+ end
+end
View
26 ...id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb
@@ -0,0 +1,26 @@
+class <%= class_name %> < ActiveRecord::Migration
+ def self.up
+ drop_table :open_id_authentication_settings
+ drop_table :open_id_authentication_nonces
+
+ create_table :open_id_authentication_nonces, :force => true do |t|
+ t.integer :timestamp, :null => false
+ t.string :server_url, :null => true
+ t.string :salt, :null => false
+ end
+ end
+
+ def self.down
+ drop_table :open_id_authentication_nonces
+
+ create_table :open_id_authentication_nonces, :force => true do |t|
+ t.integer :created
+ t.string :nonce
+ end
+
+ create_table :open_id_authentication_settings, :force => true do |t|
+ t.string :setting
+ t.binary :value
+ end
+ end
+end
View
11 .../upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb
@@ -0,0 +1,11 @@
+class UpgradeOpenIdAuthenticationTablesGenerator < Rails::Generator::NamedBase
+ def initialize(runtime_args, runtime_options = {})
+ super
+ end
+
+ def manifest
+ record do |m|
+ m.migration_template 'migration.rb', 'db/migrate'
+ end
+ end
+end
View
18 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/init.rb
@@ -0,0 +1,18 @@
+if config.respond_to?(:gems)
+ config.gem 'ruby-openid', :lib => 'openid', :version => '>=2.0.4'
+else
+ begin
+ require 'openid'
+ rescue LoadError
+ begin
+ gem 'ruby-openid', '>=2.0.4'
+ rescue Gem::LoadError
+ puts "Install the ruby-openid gem to enable OpenID support"
+ end
+ end
+end
+
+config.to_prepare do
+ OpenID::Util.logger = Rails.logger
+ ActionController::Base.send :include, OpenIdAuthentication
+end
View
244 ...r/plugins/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication.rb
@@ -0,0 +1,244 @@
+require 'uri'
+require 'openid/extensions/sreg'
+require 'openid/extensions/ax'
+require 'openid/store/filesystem'
+
+require File.dirname(__FILE__) + '/open_id_authentication/association'
+require File.dirname(__FILE__) + '/open_id_authentication/nonce'
+require File.dirname(__FILE__) + '/open_id_authentication/db_store'
+require File.dirname(__FILE__) + '/open_id_authentication/mem_cache_store'
+require File.dirname(__FILE__) + '/open_id_authentication/request'
+require File.dirname(__FILE__) + '/open_id_authentication/timeout_fixes' if OpenID::VERSION == "2.0.4"
+
+module OpenIdAuthentication
+ OPEN_ID_AUTHENTICATION_DIR = RAILS_ROOT + "/tmp/openids"
+
+ def self.store
+ @@store
+ end
+
+ def self.store=(*store_option)
+ store, *parameters = *([ store_option ].flatten)
+
+ @@store = case store
+ when :db
+ OpenIdAuthentication::DbStore.new
+ when :mem_cache
+ OpenIdAuthentication::MemCacheStore.new(*parameters)
+ when :file
+ OpenID::Store::Filesystem.new(OPEN_ID_AUTHENTICATION_DIR)
+ else
+ raise "Unknown store: #{store}"
+ end
+ end
+
+ self.store = :db
+
+ class InvalidOpenId < StandardError
+ end
+
+ class Result
+ ERROR_MESSAGES = {
+ :missing => "Sorry, the OpenID server couldn't be found",
+ :invalid => "Sorry, but this does not appear to be a valid OpenID",
+ :canceled => "OpenID verification was canceled",
+ :failed => "OpenID verification failed",
+ :setup_needed => "OpenID verification needs setup"
+ }
+
+ def self.[](code)
+ new(code)
+ end
+
+ def initialize(code)
+ @code = code
+ end
+
+ def status
+ @code
+ end
+
+ ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } }
+
+ def successful?
+ @code == :successful
+ end
+
+ def unsuccessful?
+ ERROR_MESSAGES.keys.include?(@code)
+ end
+
+ def message
+ ERROR_MESSAGES[@code]
+ end
+ end
+
+ # normalizes an OpenID according to http://openid.net/specs/openid-authentication-2_0.html#normalization
+ def self.normalize_identifier(identifier)
+ # clean up whitespace
+ identifier = identifier.to_s.strip
+
+ # if an XRI has a prefix, strip it.
+ identifier.gsub!(/xri:\/\//i, '')
+
+ # dodge XRIs -- TODO: validate, don't just skip.
+ unless ['=', '@', '+', '$', '!', '('].include?(identifier.at(0))
+ # does it begin with http? if not, add it.
+ identifier = "http://#{identifier}" unless identifier =~ /^http/i
+
+ # strip any fragments
+ identifier.gsub!(/\#(.*)$/, '')
+
+ begin
+ uri = URI.parse(identifier)
+ uri.scheme = uri.scheme.downcase # URI should do this
+ identifier = uri.normalize.to_s
+ rescue URI::InvalidURIError
+ raise InvalidOpenId.new("#{identifier} is not an OpenID identifier")
+ end
+ end
+
+ return identifier
+ end
+
+ # deprecated for OpenID 2.0, where not all OpenIDs are URLs
+ def self.normalize_url(url)
+ ActiveSupport::Deprecation.warn "normalize_url has been deprecated, use normalize_identifier instead"
+ self.normalize_identifier(url)
+ end
+
+ protected
+ def normalize_url(url)
+ OpenIdAuthentication.normalize_url(url)
+ end
+
+ def normalize_identifier(url)
+ OpenIdAuthentication.normalize_identifier(url)
+ end
+
+ # The parameter name of "openid_identifier" is used rather than the Rails convention "open_id_identifier"
+ # because that's what the specification dictates in order to get browser auto-complete working across sites
+ def using_open_id?(identity_url = nil) #:doc:
+ identity_url ||= params[:openid_identifier] || params[:openid_url]
+ !identity_url.blank? || params[:open_id_complete]
+ end
+
+ def authenticate_with_open_id(identity_url = nil, options = {}, &block) #:doc:
+ identity_url ||= params[:openid_identifier] || params[:openid_url]
+
+ if params[:open_id_complete].nil?
+ begin_open_id_authentication(identity_url, options, &block)
+ else
+ complete_open_id_authentication(&block)
+ end
+ end
+
+ private
+ def begin_open_id_authentication(identity_url, options = {})
+ identity_url = normalize_identifier(identity_url)
+ return_to = options.delete(:return_to)
+ method = options.delete(:method)
+
+ options[:required] ||= [] # reduces validation later
+ options[:optional] ||= []
+
+ open_id_request = open_id_consumer.begin(identity_url)
+ add_simple_registration_fields(open_id_request, options)
+ add_ax_fields(open_id_request, options)
+
+ redirect_to(open_id_redirect_url(open_id_request, return_to, method))
+ rescue OpenIdAuthentication::InvalidOpenId => e
+ yield Result[:invalid], identity_url, nil
+ rescue OpenID::OpenIDError, Timeout::Error => e
+ logger.error("[OPENID] #{e}")
+ yield Result[:missing], identity_url, nil
+ end
+
+ def complete_open_id_authentication
+ params_with_path = params.reject { |key, value| request.path_parameters[key] }
+ params_with_path.delete(:format)
+ open_id_response = timeout_protection_from_identity_server { open_id_consumer.complete(params_with_path, requested_url) }
+ identity_url = normalize_identifier(open_id_response.display_identifier) if open_id_response.display_identifier
+
+ case open_id_response.status
+ when OpenID::Consumer::SUCCESS
+ profile_data = {}
+
+ # merge the SReg data and the AX data into a single hash of profile data
+ [ OpenID::SReg::Response, OpenID::AX::FetchResponse ].each do |data_response|
+ if data_response.from_success_response( open_id_response )
+ profile_data.merge! data_response.from_success_response( open_id_response ).data
+ end
+ end
+
+ yield Result[:successful], identity_url, profile_data
+ when OpenID::Consumer::CANCEL
+ yield Result[:canceled], identity_url, nil
+ when OpenID::Consumer::FAILURE
+ yield Result[:failed], identity_url, nil
+ when OpenID::Consumer::SETUP_NEEDED
+ yield Result[:setup_needed], open_id_response.setup_url, nil
+ end
+ end
+
+ def open_id_consumer
+ OpenID::Consumer.new(session, OpenIdAuthentication.store)
+ end
+
+ def add_simple_registration_fields(open_id_request, fields)
+ sreg_request = OpenID::SReg::Request.new
+
+ # filter out AX identifiers (URIs)
+ required_fields = fields[:required].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact
+ optional_fields = fields[:optional].collect { |f| f.to_s unless f =~ /^https?:\/\// }.compact
+
+ sreg_request.request_fields(required_fields, true) unless required_fields.blank?
+ sreg_request.request_fields(optional_fields, false) unless optional_fields.blank?
+ sreg_request.policy_url = fields[:policy_url] if fields[:policy_url]
+ open_id_request.add_extension(sreg_request)
+ end
+
+ def add_ax_fields( open_id_request, fields )
+ ax_request = OpenID::AX::FetchRequest.new
+
+ # look through the :required and :optional fields for URIs (AX identifiers)
+ fields[:required].each do |f|
+ next unless f =~ /^https?:\/\//
+ ax_request.add( OpenID::AX::AttrInfo.new( f, nil, true ) )
+ end
+
+ fields[:optional].each do |f|
+ next unless f =~ /^https?:\/\//
+ ax_request.add( OpenID::AX::AttrInfo.new( f, nil, false ) )
+ end
+
+ open_id_request.add_extension( ax_request )
+ end
+
+ def open_id_redirect_url(open_id_request, return_to = nil, method = nil)
+ open_id_request.return_to_args['_method'] = (method || request.method).to_s
+ open_id_request.return_to_args['open_id_complete'] = '1'
+ open_id_request.redirect_url(root_url, return_to || requested_url)
+ end
+
+ def requested_url
+ relative_url_root = self.class.respond_to?(:relative_url_root) ?
+ self.class.relative_url_root.to_s :
+ request.relative_url_root
+ "#{request.protocol}#{request.host_with_port}#{ActionController::Base.relative_url_root}#{request.path}"
+ end
+
+ def timeout_protection_from_identity_server
+ yield
+ rescue Timeout::Error
+ Class.new do
+ def status
+ OpenID::FAILURE
+ end
+
+ def msg
+ "Identity server timed out"
+ end
+ end.new
+ end
+end
View
9 ...thlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/association.rb
@@ -0,0 +1,9 @@
+module OpenIdAuthentication
+ class Association < ActiveRecord::Base
+ set_table_name :open_id_authentication_associations
+
+ def from_record
+ OpenID::Association.new(handle, secret, issued, lifetime, assoc_type)
+ end
+ end
+end
View
55 .../authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/db_store.rb
@@ -0,0 +1,55 @@
+require 'openid/store/interface'
+
+module OpenIdAuthentication
+ class DbStore < OpenID::Store::Interface
+ def self.cleanup_nonces
+ now = Time.now.to_i
+ Nonce.delete_all(["timestamp > ? OR timestamp < ?", now + OpenID::Nonce.skew, now - OpenID::Nonce.skew])
+ end
+
+ def self.cleanup_associations
+ now = Time.now.to_i
+ Association.delete_all(['issued + lifetime > ?',now])
+ end
+
+ def store_association(server_url, assoc)
+ remove_association(server_url, assoc.handle)
+ Association.create(:server_url => server_url,
+ :handle => assoc.handle,
+ :secret => assoc.secret,
+ :issued => assoc.issued,
+ :lifetime => assoc.lifetime,
+ :assoc_type => assoc.assoc_type)
+ end
+
+ def get_association(server_url, handle = nil)
+ assocs = if handle.blank?
+ Association.find_all_by_server_url(server_url)
+ else
+ Association.find_all_by_server_url_and_handle(server_url, handle)
+ end
+
+ assocs.reverse.each do |assoc|
+ a = assoc.from_record
+ if a.expires_in == 0
+ assoc.destroy
+ else
+ return a
+ end
+ end if assocs.any?
+
+ return nil
+ end
+
+ def remove_association(server_url, handle)
+ Association.delete_all(['server_url = ? AND handle = ?', server_url, handle]) > 0
+ end
+
+ def use_nonce(server_url, timestamp, salt)
+ return false if Nonce.find_by_server_url_and_timestamp_and_salt(server_url, timestamp, salt)
+ return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
+ Nonce.create(:server_url => server_url, :timestamp => timestamp, :salt => salt)
+ return true
+ end
+ end
+end
View
73 ...gic_openid/test/libs/open_id_authentication/lib/open_id_authentication/mem_cache_store.rb
@@ -0,0 +1,73 @@
+require 'digest/sha1'
+require 'openid/store/interface'
+
+module OpenIdAuthentication
+ class MemCacheStore < OpenID::Store::Interface
+ def initialize(*addresses)
+ @connection = ActiveSupport::Cache::MemCacheStore.new(addresses)
+ end
+
+ def store_association(server_url, assoc)
+ server_key = association_server_key(server_url)
+ assoc_key = association_key(server_url, assoc.handle)
+
+ assocs = @connection.read(server_key) || {}
+ assocs[assoc.issued] = assoc_key
+
+ @connection.write(server_key, assocs)
+ @connection.write(assoc_key, assoc, :expires_in => assoc.lifetime)
+ end
+
+ def get_association(server_url, handle = nil)
+ if handle
+ @connection.read(association_key(server_url, handle))
+ else
+ server_key = association_server_key(server_url)
+ assocs = @connection.read(server_key)
+ return if assocs.nil?
+
+ last_key = assocs[assocs.keys.sort.last]
+ @connection.read(last_key)
+ end
+ end
+
+ def remove_association(server_url, handle)
+ server_key = association_server_key(server_url)
+ assoc_key = association_key(server_url, handle)
+ assocs = @connection.read(server_key)
+
+ return false unless assocs && assocs.has_value?(assoc_key)
+
+ assocs = assocs.delete_if { |key, value| value == assoc_key }
+
+ @connection.write(server_key, assocs)
+ @connection.delete(assoc_key)
+
+ return true
+ end
+
+ def use_nonce(server_url, timestamp, salt)
+ return false if @connection.read(nonce_key(server_url, salt))
+ return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
+ @connection.write(nonce_key(server_url, salt), timestamp, :expires_in => OpenID::Nonce.skew)
+ return true
+ end
+
+ private
+ def association_key(server_url, handle = nil)
+ "openid_association_#{digest(server_url)}_#{digest(handle)}"
+ end
+
+ def association_server_key(server_url)
+ "openid_association_server_#{digest(server_url)}"
+ end
+
+ def nonce_key(server_url, salt)
+ "openid_nonce_#{digest(server_url)}_#{digest(salt)}"
+ end
+
+ def digest(text)
+ Digest::SHA1.hexdigest(text)
+ end
+ end
+end
View
5 ...ins/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/nonce.rb
@@ -0,0 +1,5 @@
+module OpenIdAuthentication
+ class Nonce < ActiveRecord::Base
+ set_table_name :open_id_authentication_nonces
+ end
+end
View
23 ...s/authlogic_openid/test/libs/open_id_authentication/lib/open_id_authentication/request.rb
@@ -0,0 +1,23 @@
+module OpenIdAuthentication
+ module Request
+ def self.included(base)
+ base.alias_method_chain :request_method, :openid
+ end
+
+ def request_method_with_openid
+ if !parameters[:_method].blank? && parameters[:open_id_complete] == '1'
+ parameters[:_method].to_sym
+ else
+ request_method_without_openid
+ end
+ end
+ end
+end
+
+# In Rails 2.3, the request object has been renamed
+# from AbstractRequest to Request
+if defined? ActionController::Request
+ ActionController::Request.send :include, OpenIdAuthentication::Request
+else
+ ActionController::AbstractRequest.send :include, OpenIdAuthentication::Request
+end
View
20 ...logic_openid/test/libs/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb
@@ -0,0 +1,20 @@
+# http://trac.openidenabled.com/trac/ticket/156
+module OpenID
+ @@timeout_threshold = 20
+
+ def self.timeout_threshold
+ @@timeout_threshold
+ end
+
+ def self.timeout_threshold=(value)
+ @@timeout_threshold = value
+ end
+
+ class StandardFetcher
+ def make_http(uri)
+ http = @proxy.new(uri.host, uri.port)
+ http.read_timeout = http.open_timeout = OpenID.timeout_threshold
+ http
+ end
+ end
+end
View
30 ...authlogic_openid/test/libs/open_id_authentication/tasks/open_id_authentication_tasks.rake
@@ -0,0 +1,30 @@
+namespace :open_id_authentication do
+ namespace :db do
+ desc "Creates authentication tables for use with OpenIdAuthentication"
+ task :create => :environment do
+ generate_migration(["open_id_authentication_tables", "add_open_id_authentication_tables"])
+ end
+
+ desc "Upgrade authentication tables from ruby-openid 1.x.x to 2.x.x"
+ task :upgrade => :environment do
+ generate_migration(["upgrade_open_id_authentication_tables", "upgrade_open_id_authentication_tables"])
+ end
+
+ def generate_migration(args)
+ require 'rails_generator'
+ require 'rails_generator/scripts/generate'
+
+ if ActiveRecord::Base.connection.supports_migrations?
+ Rails::Generator::Scripts::Generate.new.run(args)
+ else
+ raise "Task unavailable to this database (no migration support)"
+ end
+ end
+
+ desc "Clear the authentication tables"
+ task :clear => :environment do
+ OpenIdAuthentication::DbStore.cleanup_nonces
+ OpenIdAuthentication::DbStore.cleanup_associations
+ end
+ end
+end
View
151 ...or/plugins/authlogic_openid/test/libs/open_id_authentication/test/mem_cache_store_test.rb
@@ -0,0 +1,151 @@
+require File.dirname(__FILE__) + '/test_helper'
+require File.dirname(__FILE__) + '/../lib/open_id_authentication/mem_cache_store'
+
+# Mock MemCacheStore with MemoryStore for testing
+class OpenIdAuthentication::MemCacheStore < OpenID::Store::Interface
+ def initialize(*addresses)
+ @connection = ActiveSupport::Cache::MemoryStore.new
+ end
+end
+
+class MemCacheStoreTest < Test::Unit::TestCase
+ ALLOWED_HANDLE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
+
+ def setup
+ @store = OpenIdAuthentication::MemCacheStore.new
+ end
+
+ def test_store
+ server_url = "http://www.myopenid.com/openid"
+ assoc = gen_assoc(0)
+
+ # Make sure that a missing association returns no result
+ assert_retrieve(server_url)
+
+ # Check that after storage, getting returns the same result
+ @store.store_association(server_url, assoc)
+ assert_retrieve(server_url, nil, assoc)
+
+ # more than once
+ assert_retrieve(server_url, nil, assoc)
+
+ # Storing more than once has no ill effect
+ @store.store_association(server_url, assoc)
+ assert_retrieve(server_url, nil, assoc)
+
+ # Removing an association that does not exist returns not present
+ assert_remove(server_url, assoc.handle + 'x', false)
+
+ # Removing an association that does not exist returns not present
+ assert_remove(server_url + 'x', assoc.handle, false)
+
+ # Removing an association that is present returns present
+ assert_remove(server_url, assoc.handle, true)
+
+ # but not present on subsequent calls
+ assert_remove(server_url, assoc.handle, false)
+
+ # Put assoc back in the store
+ @store.store_association(server_url, assoc)
+
+ # More recent and expires after assoc
+ assoc2 = gen_assoc(1)
+ @store.store_association(server_url, assoc2)
+
+ # After storing an association with a different handle, but the
+ # same server_url, the handle with the later expiration is returned.
+ assert_retrieve(server_url, nil, assoc2)
+
+ # We can still retrieve the older association
+ assert_retrieve(server_url, assoc.handle, assoc)
+
+ # Plus we can retrieve the association with the later expiration
+ # explicitly
+ assert_retrieve(server_url, assoc2.handle, assoc2)
+
+ # More recent, and expires earlier than assoc2 or assoc. Make sure
+ # that we're picking the one with the latest issued date and not
+ # taking into account the expiration.
+ assoc3 = gen_assoc(2, 100)
+ @store.store_association(server_url, assoc3)
+
+ assert_retrieve(server_url, nil, assoc3)
+ assert_retrieve(server_url, assoc.handle, assoc)
+ assert_retrieve(server_url, assoc2.handle, assoc2)
+ assert_retrieve(server_url, assoc3.handle, assoc3)
+
+ assert_remove(server_url, assoc2.handle, true)
+
+ assert_retrieve(server_url, nil, assoc3)
+ assert_retrieve(server_url, assoc.handle, assoc)
+ assert_retrieve(server_url, assoc2.handle, nil)
+ assert_retrieve(server_url, assoc3.handle, assoc3)
+
+ assert_remove(server_url, assoc2.handle, false)
+ assert_remove(server_url, assoc3.handle, true)
+
+ assert_retrieve(server_url, nil, assoc)
+ assert_retrieve(server_url, assoc.handle, assoc)
+ assert_retrieve(server_url, assoc2.handle, nil)
+ assert_retrieve(server_url, assoc3.handle, nil)
+
+ assert_remove(server_url, assoc2.handle, false)
+ assert_remove(server_url, assoc.handle, true)
+ assert_remove(server_url, assoc3.handle, false)
+
+ assert_retrieve(server_url, nil, nil)
+ assert_retrieve(server_url, assoc.handle, nil)
+ assert_retrieve(server_url, assoc2.handle, nil)
+ assert_retrieve(server_url, assoc3.handle, nil)
+
+ assert_remove(server_url, assoc2.handle, false)
+ assert_remove(server_url, assoc.handle, false)
+ assert_remove(server_url, assoc3.handle, false)
+ end
+
+ def test_nonce
+ server_url = "http://www.myopenid.com/openid"
+
+ [server_url, ''].each do |url|
+ nonce1 = OpenID::Nonce::mk_nonce
+
+ assert_nonce(nonce1, true, url, "#{url}: nonce allowed by default")
+ assert_nonce(nonce1, false, url, "#{url}: nonce not allowed twice")
+ assert_nonce(nonce1, false, url, "#{url}: nonce not allowed third time")
+
+ # old nonces shouldn't pass
+ old_nonce = OpenID::Nonce::mk_nonce(3600)
+ assert_nonce(old_nonce, false, url, "Old nonce #{old_nonce.inspect} passed")
+ end
+ end
+
+ private
+ def gen_assoc(issued, lifetime = 600)
+ secret = OpenID::CryptUtil.random_string(20, nil)
+ handle = OpenID::CryptUtil.random_string(128, ALLOWED_HANDLE)
+ OpenID::Association.new(handle, secret, Time.now + issued, lifetime, 'HMAC-SHA1')
+ end
+
+ def assert_retrieve(url, handle = nil, expected = nil)
+ assoc = @store.get_association(url, handle)
+
+ if expected.nil?
+ assert_nil(assoc)
+ else
+ assert_equal(expected, assoc)
+ assert_equal(expected.handle, assoc.handle)
+ assert_equal(expected.secret, assoc.secret)
+ end
+ end
+
+ def assert_remove(url, handle, expected)
+ present = @store.remove_association(url, handle)
+ assert_equal(expected, present)
+ end
+
+ def assert_nonce(nonce, expected, server_url, msg = "")
+ stamp, salt = OpenID::Nonce::split_nonce(nonce)
+ actual = @store.use_nonce(server_url, stamp, salt)
+ assert_equal(expected, actual, msg)
+ end
+end
View
32 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/test/normalize_test.rb
@@ -0,0 +1,32 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class NormalizeTest < Test::Unit::TestCase
+ include OpenIdAuthentication
+
+ NORMALIZATIONS = {
+ "openid.aol.com/nextangler" => "http://openid.aol.com/nextangler",
+ "http://openid.aol.com/nextangler" => "http://openid.aol.com/nextangler",
+ "https://openid.aol.com/nextangler" => "https://openid.aol.com/nextangler",
+ "HTTP://OPENID.AOL.COM/NEXTANGLER" => "http://openid.aol.com/NEXTANGLER",
+ "HTTPS://OPENID.AOL.COM/NEXTANGLER" => "https://openid.aol.com/NEXTANGLER",
+ "loudthinking.com" => "http://loudthinking.com/",
+ "http://loudthinking.com" => "http://loudthinking.com/",
+ "http://loudthinking.com:80" => "http://loudthinking.com/",
+ "https://loudthinking.com:443" => "https://loudthinking.com/",
+ "http://loudthinking.com:8080" => "http://loudthinking.com:8080/",
+ "techno-weenie.net" => "http://techno-weenie.net/",
+ "http://techno-weenie.net" => "http://techno-weenie.net/",
+ "http://techno-weenie.net " => "http://techno-weenie.net/",
+ "=name" => "=name"
+ }
+
+ def test_normalizations
+ NORMALIZATIONS.each do |from, to|
+ assert_equal to, normalize_identifier(from)
+ end
+ end
+
+ def test_broken_open_id
+ assert_raises(InvalidOpenId) { normalize_identifier(nil) }
+ end
+end
View
46 ...ins/authlogic_openid/test/libs/open_id_authentication/test/open_id_authentication_test.rb
@@ -0,0 +1,46 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class OpenIdAuthenticationTest < Test::Unit::TestCase
+ def setup
+ @controller = Class.new do
+ include OpenIdAuthentication
+ def params() {} end
+ end.new
+ end
+
+ def test_authentication_should_fail_when_the_identity_server_is_missing
+ open_id_consumer = mock()
+ open_id_consumer.expects(:begin).raises(OpenID::OpenIDError)
+ @controller.expects(:open_id_consumer).returns(open_id_consumer)
+ @controller.expects(:logger).returns(mock(:error => true))
+
+ @controller.send(:authenticate_with_open_id, "http://someone.example.com") do |result, identity_url|
+ assert result.missing?
+ assert_equal "Sorry, the OpenID server couldn't be found", result.message
+ end
+ end
+
+ def test_authentication_should_be_invalid_when_the_identity_url_is_invalid
+ @controller.send(:authenticate_with_open_id, "!") do |result, identity_url|
+ assert result.invalid?, "Result expected to be invalid but was not"
+ assert_equal "Sorry, but this does not appear to be a valid OpenID", result.message
+ end
+ end
+
+ def test_authentication_should_fail_when_the_identity_server_times_out
+ open_id_consumer = mock()
+ open_id_consumer.expects(:begin).raises(Timeout::Error, "Identity Server took too long.")
+ @controller.expects(:open_id_consumer).returns(open_id_consumer)
+ @controller.expects(:logger).returns(mock(:error => true))
+
+ @controller.send(:authenticate_with_open_id, "http://someone.example.com") do |result, identity_url|
+ assert result.missing?
+ assert_equal "Sorry, the OpenID server couldn't be found", result.message
+ end
+ end
+
+ def test_authentication_should_begin_when_the_identity_server_is_present
+ @controller.expects(:begin_open_id_authentication)
+ @controller.send(:authenticate_with_open_id, "http://someone.example.com")
+ end
+end
View
14 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/test/status_test.rb
@@ -0,0 +1,14 @@
+require File.dirname(__FILE__) + '/test_helper'
+
+class StatusTest < Test::Unit::TestCase
+ include OpenIdAuthentication
+
+ def test_state_conditional
+ assert Result[:missing].missing?
+ assert Result[:missing].unsuccessful?
+ assert !Result[:missing].successful?
+
+ assert Result[:successful].successful?
+ assert !Result[:successful].unsuccessful?
+ end
+end
View
17 vendor/plugins/authlogic_openid/test/libs/open_id_authentication/test/test_helper.rb
@@ -0,0 +1,17 @@
+require 'test/unit'
+require 'rubygems'
+
+gem 'activesupport'
+require 'active_support'
+
+gem 'actionpack'
+require 'action_controller'
+
+gem 'mocha'
+require 'mocha'
+
+gem 'ruby-openid'
+require 'openid'
+
+RAILS_ROOT = File.dirname(__FILE__) unless defined? RAILS_ROOT
+require File.dirname(__FILE__) + "/../lib/open_id_authentication"
View
41 vendor/plugins/authlogic_openid/test/libs/rails_trickery.rb
@@ -0,0 +1,41 @@
+# The only reason I am doing all of this non sense is becuase the openid_authentication requires that
+# these constants be present. The only other alternative is to use an entire rails application for testing
+# which is a little too overboard for this, I think.
+
+RAILS_ROOT = ''
+
+class ActionController < Authlogic::TestCase::MockController
+ class Request < Authlogic::TestCase::MockRequest
+ def request_method
+ ""
+ end
+ end
+
+ def root_url
+ ''
+ end
+
+ def request
+ return @request if defined?(@request)
+ super
+ # Rails does some crazy s#!t with the "method" method. If I don't do this I get a "wrong arguments (0 for 1) error"
+ @request.class.class_eval do
+ def method
+ nil
+ end
+ end
+ @request
+ end
+
+ def url_for(*args)
+ ''
+ end
+
+ def redirecting_to
+ @redirect_to
+ end
+
+ def redirect_to(*args)
+ @redirect_to = args
+ end
+end
View
3 vendor/plugins/authlogic_openid/test/libs/user.rb
@@ -0,0 +1,3 @@
+class User < ActiveRecord::Base
+ acts_as_authentic
+end
View
2 vendor/plugins/authlogic_openid/test/libs/user_session.rb
@@ -0,0 +1,2 @@
+class UserSession < Authlogic::Session::Base
+end
View
32 vendor/plugins/authlogic_openid/test/session_test.rb
@@ -0,0 +1,32 @@
+require File.dirname(__FILE__) + '/test_helper.rb'
+
+class SessionTest < ActiveSupport::TestCase
+ def test_openid_identifier
+ session = UserSession.new
+ assert session.respond_to?(:openid_identifier)
+ session.openid_identifier = "test"
+ assert_equal "http://test/", session.openid_identifier
+ end
+
+ def test_validate_openid_error
+ session = UserSession.new
+ session.openid_identifier = "yes"
+ session.openid_identifier = "%"
+ assert_nil session.openid_identifier
+ assert !session.save
+ assert session.errors.on(:openid_identifier)
+ end
+
+ def test_validate_by_nil_openid_identifier
+ session = UserSession.new
+ assert !session.save
+ assert !redirecting_to_yahoo?
+ end
+
+ def test_validate_by_correct_openid_identifier
+ session = UserSession.new
+ session.openid_identifier = "https://me.yahoo.com/a/9W0FJjRj0o981TMSs0vqVxPdmMUVOQ--"
+ assert !session.save
+ assert redirecting_to_yahoo?
+ end
+end
View
78 vendor/plugins/authlogic_openid/test/test_helper.rb
@@ -0,0 +1,78 @@
+require "test/unit"
+require "rubygems"
+require "ruby-debug"
+require "active_record"
+
+ActiveRecord::Schema.verbose = false
+ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
+ActiveRecord::Base.configurations = true
+ActiveRecord::Schema.define(:version => 1) do
+ create_table :open_id_authentication_associations, :force => true do |t|
+ t.integer :issued, :lifetime
+ t.string :handle, :assoc_type
+ t.binary :server_url, :secret
+ end
+
+ create_table :open_id_authentication_nonces, :force => true do |t|
+ t.integer :timestamp, :null => false
+ t.string :server_url, :null => true
+ t.string :salt, :null => false
+ end
+
+ create_table :users do |t|
+ t.datetime :created_at
+ t.datetime :updated_at
+ t.integer :lock_version, :default => 0
+ t.string :login
+ t.string :crypted_password
+ t.string :password_salt
+ t.string :persistence_token
+ t.string :single_access_token
+ t.string :perishable_token
+ t.string :openid_identifier
+ t.string :email
+ t.string :first_name
+ t.string :last_name
+ t.integer :login_count, :default => 0, :null => false
+ t.integer :failed_login_count, :default => 0, :null => false
+ t.datetime :last_request_at
+ t.datetime :current_login_at
+ t.datetime :last_login_at
+ t.string :current_login_ip
+ t.string :last_login_ip
+ end
+end
+
+require "active_record/fixtures"
+require "openid"
+Rails = true # to trick authlogic into loading the rails adapter
+require File.dirname(__FILE__) + "/../../authlogic/lib/authlogic"
+require File.dirname(__FILE__) + "/../../authlogic/lib/authlogic/test_case"
+#require File.dirname(__FILE__) + "/libs/rails_trickery"
+require File.dirname(__FILE__) + '/libs/open_id_authentication/lib/open_id_authentication'
+require File.dirname(__FILE__) + '/../lib/authlogic_openid' unless defined?(AuthlogicOpenid)
+require File.dirname(__FILE__) + '/libs/user'
+require File.dirname(__FILE__) + '/libs/user_session'
+
+class ActiveSupport::TestCase
+ include ActiveRecord::TestFixtures
+ self.fixture_path = File.dirname(__FILE__) + "/fixtures"
+ self.use_transactional_fixtures = false
+ self.use_instantiated_fixtures = false
+ self.pre_loaded_fixtures = false
+ fixtures :all
+ setup :activate_authlogic
+
+ private
+ def activate_authlogic
+ Authlogic::Session::Base.controller = controller
+ end
+
+ def controller
+ @controller ||= Authlogic::ControllerAdapters::RailsAdapter.new(ActionController.new)
+ end
+
+ def redirecting_to_yahoo?
+ controller.redirecting_to.to_s =~ /^https:\/\/open.login.yahooapis.com\/openid\/op\/auth/
+ end
+end

0 comments on commit b962107

Please sign in to comment.
Something went wrong with that request. Please try again.