beast rev 2066
[beast-modified.git] / vendor / plugins / open_id_authentication / README
blob125961f63b09d9bbffc34f092cf96031ca9e9e64
1 OpenIdAuthentication
2 ====================
4 Provides a thin wrapper around the excellent ruby-openid gem from JanRan. Be sure to install that first:
6   gem install ruby-openid
8 To understand what OpenID is about and how it works, it helps to read the documentation for lib/openid/consumer.rb
9 from that gem.
11 The specification used is http://openid.net/specs/openid-authentication-1_1.html (not the 2.0 draft).
14 Prerequisites
15 =============
17 OpenID authentication uses the session, so be sure that you haven't turned that off. It also relies on a number of
18 database tables to store the authentication keys. So you'll have to run the migration to create these before you get started:
20   rake open_id_authentication:db:create
22 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:
24   OpenIdAuthentication.store = :file
26 This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations.
27 If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb. 
29 This plugin relies on Rails Edge revision 6317 or newer.
32 Example
33 =======
35 This example is just to meant to demonstrate how you could use OpenID authentication. You'll might well want to add
36 salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point,
37 not a destination.
39 config/routes.rb
41   map.open_id_complete 'session', :controller => "sessions", :action => "create", :requirements => { :method => :get }
42   map.resource :session
45 app/views/sessions/new.erb
47   <% form_tag(session_url) do %>
48     <p>
49       <label for="name">Username:</label>
50       <%= text_field_tag "name" %>
51     </p>
53     <p>
54       <label for="password">Password:</label>
55       <%= password_field_tag %>
56     </p>
58     <p>
59       ...or use:
60     </p>
62     <p>
63       <label for="openid_url">OpenID:</label>
64       <%= text_field_tag "openid_url" %>
65     </p>
67     <p>
68       <%= submit_tag 'Sign in', :disable_with => "Signing in&hellip;" %>
69     </p>
70   <% end %>
72 app/controllers/sessions_controller.rb
73   class SessionsController < ApplicationController
74     def create
75       if using_open_id?
76         open_id_authentication
77       else
78         password_authentication(params[:name], params[:password])
79       end
80     end
83     protected
84       def password_authentication(name, password)
85         if @current_user = @account.users.authenticate(params[:name], params[:password])
86           successful_login
87         else
88           failed_login "Sorry, that username/password doesn't work"
89         end
90       end
92       def open_id_authentication
93         authenticate_with_open_id do |result, identity_url|
94           if result.successful?
95             if @current_user = @account.users.find_by_identity_url(identity_url)
96               successful_login
97             else
98               failed_login "Sorry, no user by that identity URL exists (#{identity_url})")
99             end
100           else
101             failed_login result.message
102           end
103         end
104       end
105     
106     
107     private
108       def successful_login
109         session[:user_id] = @current_user.id
110         redirect_to(root_url)
111       end
113       def failed_login(message)
114         flash[:error] = message
115         redirect_to(new_session_url)
116       end
117   end
121 If you're fine with the result messages above and don't need individual logic on a per-failure basis,
122 you can collapse the case into a mere boolean:
124     def open_id_authentication
125       authenticate_with_open_id do |result, identity_url|
126         if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url)
127           successful_login
128         else
129           failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})")
130         end
131       end
132     end
135 Simple Registration OpenID Extension
136 ====================================
138 Some OpenID Providers support this lightweight profile exchange protocol.  See more: http://www.openidenabled.com/openid/simple-registration-extension
140 You can support it in your app by changing #open_id_authentication
142       def open_id_authentication(identity_url)
143         # Pass optional :required and :optional keys to specify what sreg fields you want.
144         # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
145         authenticate_with_open_id(identity_url, 
146             :required => [ :nickname, :email ],
147             :optional => :fullname) do |status, identity_url, registration|
148           case status
149           when :missing
150             failed_login "Sorry, the OpenID server couldn't be found"
151           when :canceled
152             failed_login "OpenID verification was canceled"
153           when :failed
154             failed_login "Sorry, the OpenID verification failed"
155           when :successful
156             if @current_user = @account.users.find_by_identity_url(identity_url)
157               assign_registration_attributes!(registration)
159               if current_user.save
160                 successful_login
161               else
162                 failed_login "Your OpenID profile registration failed: " +
163                   @current_user.errors.full_messages.to_sentence
164               end
165             else
166               failed_login "Sorry, no user by that identity URL exists"
167             end
168           end
169         end
170       end
171       
172       # registration is a hash containing the valid sreg keys given above
173       # use this to map them to fields of your user model
174       def assign_registration_attributes!(registration)
175         model_to_registration_mapping.each do |model_attribute, registration_attribute|
176           unless registration[registration_attribute].blank?
177             @current_user.send("#{model_attribute}=", registration[registration_attribute])
178           end
179         end
180       end
182       def model_to_registration_mapping
183         { :login => 'nickname', :email => 'email', :display_name => 'fullname' }
184       end
187 Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license