diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86339a0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.gem \ No newline at end of file diff --git a/CONTRIBUTION_GUIDELINES.md b/CONTRIBUTION_GUIDELINES.md new file mode 100644 index 0000000..b45014c --- /dev/null +++ b/CONTRIBUTION_GUIDELINES.md @@ -0,0 +1,8 @@ +Contributing to open_id_authentication: + +1. Fork the [official repository](http://github.com/Velir/open_id_authentication/tree/master). +2. Make your changes in a topic branch. +3. Send a pull request. + +Notes: +* Please don't update the Gem version. \ No newline at end of file diff --git a/README b/README.md similarity index 76% rename from README rename to README.md index fe2b37e..c429540 100644 --- a/README +++ b/README.md @@ -12,26 +12,26 @@ 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. 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 + 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' + root :to => "articles#index" 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, @@ -42,16 +42,16 @@ 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 + 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) + 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. @@ -59,49 +59,53 @@ Use the above code in your User model and validate OpenID URLs before saving the config/routes.rb - map.root :controller => 'articles' - map.resource :session - + #config/routes.rb + root :to => "articles#index" + resource :session app/views/sessions/new.erb - <% form_tag(session_url) do %> -

- - <%= text_field_tag "name" %> -

+ #app/views/sessions/new.erb + <% form_tag(session_url) do %> +

+ + <%= text_field_tag "name" %> +

-

- - <%= password_field_tag %> -

+

+ + <%= password_field_tag %> +

-

- ...or use: -

+

+ +

-

- - <%= text_field_tag "openid_identifier" %> -

+

+ + <%= text_field_tag "openid_identifier" %> +

+ +

+ <%= submit_tag 'Sign in', :disable_with => "Signing in…" %> +

+ <% end %> -

- <%= submit_tag 'Sign in', :disable_with => "Signing in…" %> -

- <% 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]) + + #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 - end - protected + protected def password_authentication(name, password) if @current_user = @account.users.authenticate(params[:name], params[:password]) successful_login @@ -125,7 +129,7 @@ app/controllers/sessions_controller.rb end - private + private def successful_login session[:user_id] = @current_user.id redirect_to(root_url) @@ -135,7 +139,7 @@ app/controllers/sessions_controller.rb flash[:error] = message redirect_to(new_session_url) end - end + end @@ -154,7 +158,7 @@ you can collapse the case into a mere boolean: Simple Registration OpenID Extension -==================================== +------------------------------------ Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension @@ -162,7 +166,8 @@ 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. + # 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| @@ -207,17 +212,31 @@ You can support it in your app by changing #open_id_authentication 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| + authenticate_with_open_id(identity_url, + :required => [ :email, 'http://schema.openid.net/birthDate' ]) do + |result, identity_url, registration, ax| + +This would provide the sreg data for :email via registration, and the AX data for http://schema.openid.net/birthDate via ax. + +Contributing +------------ + +Please see the [contribution guidelines](http://github.com/Velir/open_id_authentication/blob/master/CONTRIBUTION_GUIDELINES.md). + +Credits +------- -This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate' +open_id_authentication was written by David Heinemeier Hansson with a number of other [contributors](https://github.com/Velir/open_id_authentication/contributors). +open_id_authentication maintenance is funded by [Velir](http://velir.com). -Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license \ No newline at end of file +License +------- +Copyright (c) 2007-2011 David Heinemeier Hansson, released under the MIT license \ No newline at end of file diff --git a/init.rb b/init.rb index 84ec11f..40a6629 100644 --- a/init.rb +++ b/init.rb @@ -8,5 +8,5 @@ config.after_initialize do OpenID::Util.logger = Rails.logger - ActionController::Base.send :include, OpenIdAuthentication + ActionController::Base.send :include, OpenIdAuthentication::ControllerMethods end diff --git a/lib/open_id_authentication.rb b/lib/open_id_authentication.rb index b355049..4ce7f10 100644 --- a/lib/open_id_authentication.rb +++ b/lib/open_id_authentication.rb @@ -37,6 +37,21 @@ def self.store=(*store_option) self.store = nil + if Rails.version >= '3' + class Railtie < ::Rails::Railtie + config.app_middleware.use OpenIdAuthentication + + config.after_initialize do + OpenID::Util.logger = Rails.logger + end + + ActiveSupport.on_load :action_controller do + ActionController::Base.send :include, ControllerMethods + #ActionController::Base.extend ControllerMethods + end + end + end + class Result ERROR_MESSAGES = { :missing => "Sorry, the OpenID server couldn't be found", @@ -73,56 +88,59 @@ def message end end - protected - # 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?(identifier = nil) #:doc: - identifier ||= open_id_identifier - !identifier.blank? || request.env[Rack::OpenID::RESPONSE] - end + module ControllerMethods + protected + # 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?(identifier = nil) #:doc: + identifier ||= open_id_identifier + !identifier.blank? || request.env[Rack::OpenID::RESPONSE] + end - def authenticate_with_open_id(identifier = nil, options = {}, &block) #:doc: - identifier ||= open_id_identifier + def authenticate_with_open_id(identifier = nil, options = {}, &block) #:doc: + identifier ||= open_id_identifier - if request.env[Rack::OpenID::RESPONSE] - complete_open_id_authentication(&block) - else - begin_open_id_authentication(identifier, options, &block) + if request.env[Rack::OpenID::RESPONSE] + complete_open_id_authentication(&block) + else + begin_open_id_authentication(identifier, options, &block) + end end - end - private - def open_id_identifier - params[:openid_identifier] || params[:openid_url] - end + private + def open_id_identifier + params[:openid_identifier] || params[:openid_url] + end - def begin_open_id_authentication(identifier, options = {}) - options[:identifier] = identifier - value = Rack::OpenID.build_header(options) - response.headers[Rack::OpenID::AUTHENTICATE_HEADER] = value - head :unauthorized - end + def begin_open_id_authentication(identifier, options = {}) + options[:identifier] = identifier + value = Rack::OpenID.build_header(options) + response.headers[Rack::OpenID::AUTHENTICATE_HEADER] = value + head :unauthorized + end - def complete_open_id_authentication - response = request.env[Rack::OpenID::RESPONSE] - identifier = response.display_identifier - - case response.status - when OpenID::Consumer::SUCCESS - yield Result[:successful], identifier, - OpenID::SReg::Response.from_success_response(response) - when :missing - yield Result[:missing], identifier, nil - when :invalid - yield Result[:invalid], identifier, nil - when OpenID::Consumer::CANCEL - yield Result[:canceled], identifier, nil - when OpenID::Consumer::FAILURE - yield Result[:failed], identifier, nil - when OpenID::Consumer::SETUP_NEEDED - yield Result[:setup_needed], response.setup_url, nil + def complete_open_id_authentication + response = request.env[Rack::OpenID::RESPONSE] + identifier = response.display_identifier + + case response.status + when OpenID::Consumer::SUCCESS + yield Result[:successful], identifier, + OpenID::SReg::Response.from_success_response(response), + OpenID::AX::FetchResponse.from_success_response(response) + when :missing + yield Result[:missing], identifier, nil + when :invalid + yield Result[:invalid], identifier, nil + when OpenID::Consumer::CANCEL + yield Result[:canceled], identifier, nil + when OpenID::Consumer::FAILURE + yield Result[:failed], identifier, nil + when OpenID::Consumer::SETUP_NEEDED + yield Result[:setup_needed], response.setup_url, nil + end end - end + end end diff --git a/lib/open_id_authentication/version.rb b/lib/open_id_authentication/version.rb new file mode 100644 index 0000000..dbc9750 --- /dev/null +++ b/lib/open_id_authentication/version.rb @@ -0,0 +1,4 @@ +module OpenIdAuthentication + VERSION = "1.0.0" +end + \ No newline at end of file diff --git a/open_id_authentication.gemspec b/open_id_authentication.gemspec new file mode 100644 index 0000000..553b43e --- /dev/null +++ b/open_id_authentication.gemspec @@ -0,0 +1,32 @@ +$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib') +require 'open_id_authentication/version' +Gem::Specification.new do |s| + s.name = %q{open_id_authentication} + s.version = OpenIdAuthentication::VERSION + s.summary = %q{open_id_authentication provides a thin wrapper around the excellent rack-openid + gem.} + s.description = %q{open_id_authentication provides a thin wrapper around the excellent rack-openid + gem.} + + s.files = Dir['[A-Z]*', 'lib/**/*.rb'] + s.require_path = 'lib' + + s.authors = ["Patrick Robertson"] + s.email = %q{patrick.robertson@velir.com} + s.homepage = "https://github.com/Velir/open_id_authentication" + + s.platform = Gem::Platform::RUBY + s.rubygems_version = %q{1.2.0} + + if s.respond_to? :specification_version then + s.specification_version = 3 + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, ["~> 1.3"]) + else + s.add_dependency(%q, ["~> 1.3"]) + end + else + s.add_dependency(%q, ["~> 1.3"]) + end +end \ No newline at end of file