Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 223 lines (164 sloc) 8.143 kb
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
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
a3758ca Updated OpenIdAuthentication to use Ruby OpenID 2.x.x gem (closes #10604...
josh authored
11 The specification used is http://openid.net/specs/openid-authentication-2_0.html.
6cc90bf Added normalize_url and applied it to all operations going through the p...
david authored
12
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
13
14 Prerequisites
15 =============
16
ee5be2f @josh Axe DB store, use memcache.
josh authored
17 OpenID authentication uses the session, so be sure that you haven't turned that off.
a27b1c0 @topfunky README documentation for the generators and root URL.
topfunky authored
18
d5caeb0 Added a new default database-backed store after experiencing trouble wit...
david authored
19 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:
20
21 OpenIdAuthentication.store = :file
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
22
23 This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations.
ee5be2f @josh Axe DB store, use memcache.
josh authored
24 If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb.
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
25
a27b1c0 @topfunky README documentation for the generators and root URL.
topfunky authored
26 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:
27
28 map.root :controller => 'articles'
29
7d9750c Stop relying on root_url being defined, we can just grab the current url...
david authored
30 This plugin relies on Rails Edge revision 6317 or newer.
31
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
32
33 Example
34 =======
35
f6f7eac @pdsphil README documentation for OpenIdAuthentication.normalize_url method
pdsphil authored
36 This example is just to meant to demonstrate how you could use OpenID authentication. You might well want to add
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
37 salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point,
38 not a destination.
39
f6f7eac @pdsphil README documentation for OpenIdAuthentication.normalize_url method
pdsphil authored
40 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
41 model you are using for authentication.
42
43 Also of note is the following code block used in the example below:
44
45 authenticate_with_open_id do |result, identity_url|
46 ...
47 end
ee5be2f @josh Axe DB store, use memcache.
josh authored
48
f6f7eac @pdsphil README documentation for OpenIdAuthentication.normalize_url method
pdsphil authored
49 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' -
50 If you are storing just 'example.com' with your user, the lookup will fail.
51
52 There is a handy method in this plugin called 'normalize_url' that will help with validating OpenID URLs.
53
54 OpenIdAuthentication.normalize_url(user.identity_url)
55
56 The above will return a standardized version of the OpenID URL - the above called with 'example.com' will return 'http://example.com/'
57 It will also raise an InvalidOpenId exception if the URL is determined to not be valid.
58 Use the above code in your User model and validate OpenID URLs before saving them.
59
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
60 config/routes.rb
61
a27b1c0 @topfunky README documentation for the generators and root URL.
topfunky authored
62 map.root :controller => 'articles'
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
63 map.resource :session
64
65
6cc90bf Added normalize_url and applied it to all operations going through the p...
david authored
66 app/views/sessions/new.erb
67
68 <% form_tag(session_url) do %>
69 <p>
70 <label for="name">Username:</label>
71 <%= text_field_tag "name" %>
72 </p>
73
74 <p>
75 <label for="password">Password:</label>
76 <%= password_field_tag %>
77 </p>
78
79 <p>
80 ...or use:
81 </p>
82
83 <p>
9efbd25 @josh Changed default identity url parameter from "openid_url" to "openid_iden...
josh authored
84 <label for="openid_identifier">OpenID:</label>
85 <%= text_field_tag "openid_identifier" %>
6cc90bf Added normalize_url and applied it to all operations going through the p...
david authored
86 </p>
87
88 <p>
89 <%= submit_tag 'Sign in', :disable_with => "Signing in&hellip;" %>
90 </p>
91 <% end %>
92
9f52fdc Update README to reflect pluralized controller name for singleton resour...
bitsweat authored
93 app/controllers/sessions_controller.rb
94 class SessionsController < ApplicationController
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
95 def create
6cc90bf Added normalize_url and applied it to all operations going through the p...
david authored
96 if using_open_id?
97 open_id_authentication
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
98 else
99 password_authentication(params[:name], params[:password])
100 end
101 end
102
103
104 protected
105 def password_authentication(name, password)
7d9750c Stop relying on root_url being defined, we can just grab the current url...
david authored
106 if @current_user = @account.users.authenticate(params[:name], params[:password])
913f113 attempt to load ruby-openid. if it's not there, #open_id? always return...
rick authored
107 successful_login
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
108 else
913f113 attempt to load ruby-openid. if it's not there, #open_id? always return...
rick authored
109 failed_login "Sorry, that username/password doesn't work"
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
110 end
111 end
112
6cc90bf Added normalize_url and applied it to all operations going through the p...
david authored
113 def open_id_authentication
114 authenticate_with_open_id do |result, identity_url|
424abe6 * Allow -'s in #normalize_url [Rick]
rick authored
115 if result.successful?
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
116 if @current_user = @account.users.find_by_identity_url(identity_url)
117 successful_login
118 else
f3a66c6 Docfix (closes #9131)
david authored
119 failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
120 end
424abe6 * Allow -'s in #normalize_url [Rick]
rick authored
121 else
122 failed_login result.message
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
123 end
124 end
125 end
ee5be2f @josh Axe DB store, use memcache.
josh authored
126
127
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
128 private
129 def successful_login
130 session[:user_id] = @current_user.id
131 redirect_to(root_url)
132 end
133
134 def failed_login(message)
135 flash[:error] = message
136 redirect_to(new_session_url)
137 end
138 end
139
7d9750c Stop relying on root_url being defined, we can just grab the current url...
david authored
140
f8fe1a5 Added OpenIdAuthentication::Result to make it easier to deal with defaul...
david authored
141
142 If you're fine with the result messages above and don't need individual logic on a per-failure basis,
143 you can collapse the case into a mere boolean:
144
6cc90bf Added normalize_url and applied it to all operations going through the p...
david authored
145 def open_id_authentication
146 authenticate_with_open_id do |result, identity_url|
147 if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url)
148 successful_login
f8fe1a5 Added OpenIdAuthentication::Result to make it easier to deal with defaul...
david authored
149 else
6cc90bf Added normalize_url and applied it to all operations going through the p...
david authored
150 failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})")
f8fe1a5 Added OpenIdAuthentication::Result to make it easier to deal with defaul...
david authored
151 end
152 end
153 end
154
155
5813e28 add sreg support
rick authored
156 Simple Registration OpenID Extension
157 ====================================
158
159 Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension
160
161 You can support it in your app by changing #open_id_authentication
162
163 def open_id_authentication(identity_url)
164 # Pass optional :required and :optional keys to specify what sreg fields you want.
165 # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
ee5be2f @josh Axe DB store, use memcache.
josh authored
166 authenticate_with_open_id(identity_url,
7d9750c Stop relying on root_url being defined, we can just grab the current url...
david authored
167 :required => [ :nickname, :email ],
c5f60a4 @josh Drop Result#=== comparison in favor of status accessor.
josh authored
168 :optional => :fullname) do |result, identity_url, registration|
169 case result.status
5813e28 add sreg support
rick authored
170 when :missing
171 failed_login "Sorry, the OpenID server couldn't be found"
8a0758c @josh An invalid identity url passed through authenticate_with_open_id will no...
josh authored
172 when :invalid
173 failed_login "Sorry, but this does not appear to be a valid OpenID"
5813e28 add sreg support
rick authored
174 when :canceled
175 failed_login "OpenID verification was canceled"
176 when :failed
177 failed_login "Sorry, the OpenID verification failed"
178 when :successful
179 if @current_user = @account.users.find_by_identity_url(identity_url)
7d9750c Stop relying on root_url being defined, we can just grab the current url...
david authored
180 assign_registration_attributes!(registration)
181
182 if current_user.save
183 successful_login
184 else
185 failed_login "Your OpenID profile registration failed: " +
186 @current_user.errors.full_messages.to_sentence
5813e28 add sreg support
rick authored
187 end
188 else
189 failed_login "Sorry, no user by that identity URL exists"
190 end
191 end
192 end
193 end
ee5be2f @josh Axe DB store, use memcache.
josh authored
194
7d9750c Stop relying on root_url being defined, we can just grab the current url...
david authored
195 # registration is a hash containing the valid sreg keys given above
196 # use this to map them to fields of your user model
197 def assign_registration_attributes!(registration)
198 model_to_registration_mapping.each do |model_attribute, registration_attribute|
199 unless registration[registration_attribute].blank?
200 @current_user.send("#{model_attribute}=", registration[registration_attribute])
201 end
202 end
203 end
204
205 def model_to_registration_mapping
206 { :login => 'nickname', :email => 'email', :display_name => 'fullname' }
207 end
208
e2b2ae5 @peat Added short section for AX data requests
peat authored
209 Attribute Exchange OpenID Extension
210 ===================================
211
212 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
213
214 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:
215
ee5be2f @josh Axe DB store, use memcache.
josh authored
216 authenticate_with_open_id(identity_url,
e2b2ae5 @peat Added short section for AX data requests
peat authored
217 :required => [ :email, 'http://schema.openid.net/birthDate' ]) do |result, identity_url, registration|
ee5be2f @josh Axe DB store, use memcache.
josh authored
218
e2b2ae5 @peat Added short section for AX data requests
peat authored
219 This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate'
220
221
b036ee0 Added simple OpenID authentication Rails plugin wrapper for ruby-openid
david authored
222
223 Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
Something went wrong with that request. Please try again.