Mercurial > hg > soundsoftware-site
comparison vendor/plugins/open_id_authentication/.svn/text-base/README.svn-base @ 0:513646585e45
* Import Redmine trunk SVN rev 3859
author | Chris Cannam |
---|---|
date | Fri, 23 Jul 2010 15:52:44 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:513646585e45 |
---|---|
1 OpenIdAuthentication | |
2 ==================== | |
3 | |
4 Provides a thin wrapper around the excellent ruby-openid gem from JanRan. Be sure to install that first: | |
5 | |
6 gem install ruby-openid | |
7 | |
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. | |
10 | |
11 The specification used is http://openid.net/specs/openid-authentication-2_0.html. | |
12 | |
13 | |
14 Prerequisites | |
15 ============= | |
16 | |
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: | |
19 | |
20 rake open_id_authentication:db:create | |
21 | |
22 Or, use the included generators to install or upgrade: | |
23 | |
24 ./script/generate open_id_authentication_tables MigrationName | |
25 ./script/generate upgrade_open_id_authentication_tables MigrationName | |
26 | |
27 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: | |
28 | |
29 OpenIdAuthentication.store = :file | |
30 | |
31 This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations. | |
32 If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb. | |
33 | |
34 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: | |
35 | |
36 map.root :controller => 'articles' | |
37 | |
38 This plugin relies on Rails Edge revision 6317 or newer. | |
39 | |
40 | |
41 Example | |
42 ======= | |
43 | |
44 This example is just to meant to demonstrate how you could use OpenID authentication. You might well want to add | |
45 salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point, | |
46 not a destination. | |
47 | |
48 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 | |
49 model you are using for authentication. | |
50 | |
51 Also of note is the following code block used in the example below: | |
52 | |
53 authenticate_with_open_id do |result, identity_url| | |
54 ... | |
55 end | |
56 | |
57 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' - | |
58 If you are storing just 'example.com' with your user, the lookup will fail. | |
59 | |
60 There is a handy method in this plugin called 'normalize_url' that will help with validating OpenID URLs. | |
61 | |
62 OpenIdAuthentication.normalize_url(user.identity_url) | |
63 | |
64 The above will return a standardized version of the OpenID URL - the above called with 'example.com' will return 'http://example.com/' | |
65 It will also raise an InvalidOpenId exception if the URL is determined to not be valid. | |
66 Use the above code in your User model and validate OpenID URLs before saving them. | |
67 | |
68 config/routes.rb | |
69 | |
70 map.root :controller => 'articles' | |
71 map.resource :session | |
72 | |
73 | |
74 app/views/sessions/new.erb | |
75 | |
76 <% form_tag(session_url) do %> | |
77 <p> | |
78 <label for="name">Username:</label> | |
79 <%= text_field_tag "name" %> | |
80 </p> | |
81 | |
82 <p> | |
83 <label for="password">Password:</label> | |
84 <%= password_field_tag %> | |
85 </p> | |
86 | |
87 <p> | |
88 ...or use: | |
89 </p> | |
90 | |
91 <p> | |
92 <label for="openid_identifier">OpenID:</label> | |
93 <%= text_field_tag "openid_identifier" %> | |
94 </p> | |
95 | |
96 <p> | |
97 <%= submit_tag 'Sign in', :disable_with => "Signing in…" %> | |
98 </p> | |
99 <% end %> | |
100 | |
101 app/controllers/sessions_controller.rb | |
102 class SessionsController < ApplicationController | |
103 def create | |
104 if using_open_id? | |
105 open_id_authentication | |
106 else | |
107 password_authentication(params[:name], params[:password]) | |
108 end | |
109 end | |
110 | |
111 | |
112 protected | |
113 def password_authentication(name, password) | |
114 if @current_user = @account.users.authenticate(params[:name], params[:password]) | |
115 successful_login | |
116 else | |
117 failed_login "Sorry, that username/password doesn't work" | |
118 end | |
119 end | |
120 | |
121 def open_id_authentication | |
122 authenticate_with_open_id do |result, identity_url| | |
123 if result.successful? | |
124 if @current_user = @account.users.find_by_identity_url(identity_url) | |
125 successful_login | |
126 else | |
127 failed_login "Sorry, no user by that identity URL exists (#{identity_url})" | |
128 end | |
129 else | |
130 failed_login result.message | |
131 end | |
132 end | |
133 end | |
134 | |
135 | |
136 private | |
137 def successful_login | |
138 session[:user_id] = @current_user.id | |
139 redirect_to(root_url) | |
140 end | |
141 | |
142 def failed_login(message) | |
143 flash[:error] = message | |
144 redirect_to(new_session_url) | |
145 end | |
146 end | |
147 | |
148 | |
149 | |
150 If you're fine with the result messages above and don't need individual logic on a per-failure basis, | |
151 you can collapse the case into a mere boolean: | |
152 | |
153 def open_id_authentication | |
154 authenticate_with_open_id do |result, identity_url| | |
155 if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url) | |
156 successful_login | |
157 else | |
158 failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})") | |
159 end | |
160 end | |
161 end | |
162 | |
163 | |
164 Simple Registration OpenID Extension | |
165 ==================================== | |
166 | |
167 Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension | |
168 | |
169 You can support it in your app by changing #open_id_authentication | |
170 | |
171 def open_id_authentication(identity_url) | |
172 # Pass optional :required and :optional keys to specify what sreg fields you want. | |
173 # Be sure to yield registration, a third argument in the #authenticate_with_open_id block. | |
174 authenticate_with_open_id(identity_url, | |
175 :required => [ :nickname, :email ], | |
176 :optional => :fullname) do |result, identity_url, registration| | |
177 case result.status | |
178 when :missing | |
179 failed_login "Sorry, the OpenID server couldn't be found" | |
180 when :invalid | |
181 failed_login "Sorry, but this does not appear to be a valid OpenID" | |
182 when :canceled | |
183 failed_login "OpenID verification was canceled" | |
184 when :failed | |
185 failed_login "Sorry, the OpenID verification failed" | |
186 when :successful | |
187 if @current_user = @account.users.find_by_identity_url(identity_url) | |
188 assign_registration_attributes!(registration) | |
189 | |
190 if current_user.save | |
191 successful_login | |
192 else | |
193 failed_login "Your OpenID profile registration failed: " + | |
194 @current_user.errors.full_messages.to_sentence | |
195 end | |
196 else | |
197 failed_login "Sorry, no user by that identity URL exists" | |
198 end | |
199 end | |
200 end | |
201 end | |
202 | |
203 # registration is a hash containing the valid sreg keys given above | |
204 # use this to map them to fields of your user model | |
205 def assign_registration_attributes!(registration) | |
206 model_to_registration_mapping.each do |model_attribute, registration_attribute| | |
207 unless registration[registration_attribute].blank? | |
208 @current_user.send("#{model_attribute}=", registration[registration_attribute]) | |
209 end | |
210 end | |
211 end | |
212 | |
213 def model_to_registration_mapping | |
214 { :login => 'nickname', :email => 'email', :display_name => 'fullname' } | |
215 end | |
216 | |
217 Attribute Exchange OpenID Extension | |
218 =================================== | |
219 | |
220 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 | |
221 | |
222 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: | |
223 | |
224 authenticate_with_open_id(identity_url, | |
225 :required => [ :email, 'http://schema.openid.net/birthDate' ]) do |result, identity_url, registration| | |
226 | |
227 This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate' | |
228 | |
229 | |
230 | |
231 Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license |