ruby-openid 1.1.4 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-openid might be problematic. Click here for more details.

Files changed (207) hide show
  1. data/INSTALL +0 -9
  2. data/README +21 -22
  3. data/UPGRADE +117 -0
  4. data/admin/runtests.rb +36 -0
  5. data/examples/README +13 -21
  6. data/examples/active_record_openid_store/README +8 -3
  7. data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +4 -8
  8. data/examples/active_record_openid_store/XXX_upgrade_open_id_store.rb +26 -0
  9. data/examples/active_record_openid_store/lib/association.rb +2 -0
  10. data/examples/active_record_openid_store/lib/openid_ar_store.rb +22 -47
  11. data/examples/active_record_openid_store/test/store_test.rb +78 -48
  12. data/examples/discover +46 -0
  13. data/examples/{rails_server → rails_openid}/README +0 -0
  14. data/examples/{rails_server → rails_openid}/Rakefile +0 -0
  15. data/examples/{rails_server → rails_openid}/app/controllers/application.rb +0 -0
  16. data/examples/rails_openid/app/controllers/consumer_controller.rb +115 -0
  17. data/examples/{rails_server → rails_openid}/app/controllers/login_controller.rb +10 -2
  18. data/examples/rails_openid/app/controllers/server_controller.rb +265 -0
  19. data/examples/{rails_server → rails_openid}/app/helpers/application_helper.rb +0 -0
  20. data/examples/{rails_server → rails_openid}/app/helpers/login_helper.rb +0 -0
  21. data/examples/{rails_server → rails_openid}/app/helpers/server_helper.rb +0 -0
  22. data/examples/rails_openid/app/views/consumer/index.rhtml +81 -0
  23. data/examples/rails_openid/app/views/consumer/start.rhtml +8 -0
  24. data/examples/{rails_server → rails_openid}/app/views/layouts/server.rhtml +0 -0
  25. data/examples/{rails_server → rails_openid}/app/views/login/index.rhtml +1 -1
  26. data/examples/rails_openid/app/views/server/decide.rhtml +26 -0
  27. data/examples/{rails_server → rails_openid}/config/boot.rb +0 -0
  28. data/examples/{rails_server → rails_openid}/config/database.yml +0 -0
  29. data/examples/{rails_server → rails_openid}/config/environment.rb +0 -0
  30. data/examples/{rails_server → rails_openid}/config/environments/development.rb +0 -0
  31. data/examples/{rails_server → rails_openid}/config/environments/production.rb +0 -0
  32. data/examples/{rails_server → rails_openid}/config/environments/test.rb +0 -0
  33. data/examples/{rails_server → rails_openid}/config/routes.rb +2 -1
  34. data/examples/{rails_server → rails_openid}/doc/README_FOR_APP +0 -0
  35. data/examples/{rails_server → rails_openid}/public/404.html +0 -0
  36. data/examples/{rails_server → rails_openid}/public/500.html +0 -0
  37. data/examples/{rails_server → rails_openid}/public/dispatch.cgi +0 -0
  38. data/examples/{rails_server → rails_openid}/public/dispatch.fcgi +0 -0
  39. data/examples/{rails_server → rails_openid}/public/dispatch.rb +0 -0
  40. data/examples/{rails_server → rails_openid}/public/favicon.ico +0 -0
  41. data/examples/rails_openid/public/images/openid_login_bg.gif +0 -0
  42. data/examples/{rails_server → rails_openid}/public/javascripts/controls.js +0 -0
  43. data/examples/{rails_server → rails_openid}/public/javascripts/dragdrop.js +0 -0
  44. data/examples/{rails_server → rails_openid}/public/javascripts/effects.js +0 -0
  45. data/examples/{rails_server → rails_openid}/public/javascripts/prototype.js +0 -0
  46. data/examples/{rails_server → rails_openid}/public/robots.txt +0 -0
  47. data/examples/{rails_server → rails_openid}/script/about +0 -0
  48. data/examples/{rails_server → rails_openid}/script/breakpointer +0 -0
  49. data/examples/{rails_server → rails_openid}/script/console +0 -0
  50. data/examples/{rails_server → rails_openid}/script/destroy +0 -0
  51. data/examples/{rails_server → rails_openid}/script/generate +0 -0
  52. data/examples/{rails_server → rails_openid}/script/performance/benchmarker +0 -0
  53. data/examples/{rails_server → rails_openid}/script/performance/profiler +0 -0
  54. data/examples/{rails_server → rails_openid}/script/plugin +0 -0
  55. data/examples/{rails_server → rails_openid}/script/process/reaper +0 -0
  56. data/examples/{rails_server → rails_openid}/script/process/spawner +0 -0
  57. data/examples/{rails_server → rails_openid}/script/process/spinner +0 -0
  58. data/examples/{rails_server → rails_openid}/script/runner +0 -0
  59. data/examples/{rails_server → rails_openid}/script/server +0 -0
  60. data/examples/{rails_server → rails_openid}/test/functional/login_controller_test.rb +0 -0
  61. data/examples/{rails_server → rails_openid}/test/functional/server_controller_test.rb +0 -0
  62. data/examples/{rails_server → rails_openid}/test/test_helper.rb +0 -0
  63. data/lib/{hmac.rb → hmac/hmac.rb} +0 -0
  64. data/lib/{hmac-sha1.rb → hmac/sha1.rb} +1 -1
  65. data/lib/{hmac-sha2.rb → hmac/sha2.rb} +1 -1
  66. data/lib/openid/association.rb +213 -73
  67. data/lib/openid/consumer/associationmanager.rb +338 -0
  68. data/lib/openid/consumer/checkid_request.rb +175 -0
  69. data/lib/openid/consumer/discovery.rb +480 -0
  70. data/lib/openid/consumer/discovery_manager.rb +123 -0
  71. data/lib/openid/consumer/html_parse.rb +136 -0
  72. data/lib/openid/consumer/idres.rb +525 -0
  73. data/lib/openid/consumer/responses.rb +133 -0
  74. data/lib/openid/consumer.rb +280 -807
  75. data/lib/openid/cryptutil.rb +85 -0
  76. data/lib/openid/dh.rb +60 -23
  77. data/lib/openid/extension.rb +31 -0
  78. data/lib/openid/extensions/ax.rb +506 -0
  79. data/lib/openid/extensions/pape.rb +182 -0
  80. data/lib/openid/extensions/sreg.rb +275 -0
  81. data/lib/openid/extras.rb +11 -0
  82. data/lib/openid/fetchers.rb +132 -93
  83. data/lib/openid/kvform.rb +133 -0
  84. data/lib/openid/kvpost.rb +56 -0
  85. data/lib/openid/message.rb +534 -0
  86. data/lib/openid/protocolerror.rb +6 -0
  87. data/lib/openid/server.rb +1215 -666
  88. data/lib/openid/store/filesystem.rb +271 -0
  89. data/lib/openid/store/interface.rb +75 -0
  90. data/lib/openid/store/memory.rb +84 -0
  91. data/lib/openid/store/nonce.rb +68 -0
  92. data/lib/openid/trustroot.rb +314 -87
  93. data/lib/openid/urinorm.rb +37 -34
  94. data/lib/openid/util.rb +42 -220
  95. data/lib/openid/yadis/accept.rb +148 -0
  96. data/lib/openid/yadis/constants.rb +21 -0
  97. data/lib/openid/yadis/discovery.rb +153 -0
  98. data/lib/openid/yadis/filters.rb +205 -0
  99. data/lib/openid/{htmltokenizer.rb → yadis/htmltokenizer.rb} +1 -54
  100. data/lib/openid/yadis/parsehtml.rb +36 -0
  101. data/lib/openid/yadis/services.rb +42 -0
  102. data/lib/openid/yadis/xrds.rb +171 -0
  103. data/lib/openid/yadis/xri.rb +90 -0
  104. data/lib/openid/yadis/xrires.rb +106 -0
  105. data/lib/openid.rb +1 -4
  106. data/test/data/accept.txt +124 -0
  107. data/test/data/dh.txt +29 -0
  108. data/test/data/example-xrds.xml +14 -0
  109. data/test/data/linkparse.txt +587 -0
  110. data/test/data/n2b64 +650 -0
  111. data/test/data/test1-discover.txt +137 -0
  112. data/test/data/test1-parsehtml.txt +128 -0
  113. data/test/data/test_discover/openid.html +11 -0
  114. data/test/data/test_discover/openid2.html +11 -0
  115. data/test/data/test_discover/openid2_xrds.xml +12 -0
  116. data/test/data/test_discover/openid2_xrds_no_local_id.xml +11 -0
  117. data/test/data/test_discover/openid_1_and_2.html +11 -0
  118. data/test/data/test_discover/openid_1_and_2_xrds.xml +16 -0
  119. data/test/data/test_discover/openid_1_and_2_xrds_bad_delegate.xml +17 -0
  120. data/test/data/test_discover/openid_and_yadis.html +12 -0
  121. data/test/data/test_discover/openid_no_delegate.html +10 -0
  122. data/test/data/test_discover/yadis_0entries.xml +12 -0
  123. data/test/data/test_discover/yadis_2_bad_local_id.xml +15 -0
  124. data/test/data/test_discover/yadis_2entries_delegate.xml +22 -0
  125. data/test/data/test_discover/yadis_2entries_idp.xml +21 -0
  126. data/test/data/test_discover/yadis_another_delegate.xml +14 -0
  127. data/test/data/test_discover/yadis_idp.xml +12 -0
  128. data/test/data/test_discover/yadis_idp_delegate.xml +13 -0
  129. data/test/data/test_discover/yadis_no_delegate.xml +11 -0
  130. data/test/data/test_xrds/=j3h.2007.11.14.xrds +25 -0
  131. data/test/data/test_xrds/README +12 -0
  132. data/test/data/test_xrds/delegated-20060809-r1.xrds +34 -0
  133. data/test/data/test_xrds/delegated-20060809-r2.xrds +34 -0
  134. data/test/data/test_xrds/delegated-20060809.xrds +34 -0
  135. data/test/data/test_xrds/no-xrd.xml +7 -0
  136. data/test/data/test_xrds/not-xrds.xml +2 -0
  137. data/test/data/test_xrds/prefixsometimes.xrds +34 -0
  138. data/test/data/test_xrds/ref.xrds +109 -0
  139. data/test/data/test_xrds/sometimesprefix.xrds +34 -0
  140. data/test/data/test_xrds/spoof1.xrds +25 -0
  141. data/test/data/test_xrds/spoof2.xrds +25 -0
  142. data/test/data/test_xrds/spoof3.xrds +37 -0
  143. data/test/data/test_xrds/status222.xrds +9 -0
  144. data/test/data/test_xrds/valid-populated-xrds.xml +39 -0
  145. data/test/data/trustroot.txt +147 -0
  146. data/test/discoverdata.rb +131 -0
  147. data/test/test_accept.rb +170 -0
  148. data/test/test_association.rb +266 -0
  149. data/test/test_associationmanager.rb +899 -0
  150. data/test/test_ax.rb +587 -0
  151. data/test/test_checkid_request.rb +297 -0
  152. data/test/test_consumer.rb +257 -0
  153. data/test/test_cryptutil.rb +117 -0
  154. data/test/test_dh.rb +86 -0
  155. data/test/test_discover.rb +772 -0
  156. data/test/test_discovery_manager.rb +262 -0
  157. data/test/test_extras.rb +35 -0
  158. data/test/test_fetchers.rb +472 -0
  159. data/test/test_filters.rb +270 -0
  160. data/test/test_idres.rb +816 -0
  161. data/test/test_kvform.rb +165 -0
  162. data/test/test_kvpost.rb +65 -0
  163. data/test/test_linkparse.rb +101 -0
  164. data/test/test_message.rb +1058 -0
  165. data/test/test_nonce.rb +89 -0
  166. data/test/test_openid_yadis.rb +178 -0
  167. data/test/test_pape.rb +233 -0
  168. data/test/test_parsehtml.rb +80 -0
  169. data/test/test_responses.rb +63 -0
  170. data/test/test_server.rb +2270 -0
  171. data/test/test_sreg.rb +479 -0
  172. data/test/test_stores.rb +269 -0
  173. data/test/test_trustroot.rb +112 -0
  174. data/test/{urinorm.rb → test_urinorm.rb} +6 -3
  175. data/test/test_util.rb +144 -0
  176. data/test/test_xrds.rb +160 -0
  177. data/test/test_xri.rb +48 -0
  178. data/test/test_xrires.rb +63 -0
  179. data/test/test_yadis_discovery.rb +207 -0
  180. data/test/testutil.rb +116 -0
  181. data/test/util.rb +47 -50
  182. metadata +233 -143
  183. data/examples/consumer.rb +0 -290
  184. data/examples/rails_openid_login_generator/openid_login_generator-0.1.gem +0 -0
  185. data/examples/rails_server/app/controllers/server_controller.rb +0 -190
  186. data/examples/rails_server/app/views/server/decide.rhtml +0 -11
  187. data/examples/rails_server/public/images/rails.png +0 -0
  188. data/lib/hmac-md5.rb +0 -11
  189. data/lib/hmac-rmd160.rb +0 -11
  190. data/lib/openid/discovery.rb +0 -122
  191. data/lib/openid/filestore.rb +0 -315
  192. data/lib/openid/parse.rb +0 -23
  193. data/lib/openid/service.rb +0 -147
  194. data/lib/openid/stores.rb +0 -178
  195. data/test/assoc.rb +0 -38
  196. data/test/consumer.rb +0 -376
  197. data/test/data/brian.xrds +0 -16
  198. data/test/data/brianellin.mylid.xrds +0 -42
  199. data/test/dh.rb +0 -20
  200. data/test/extensions.rb +0 -30
  201. data/test/linkparse.rb +0 -305
  202. data/test/runtests.rb +0 -22
  203. data/test/server2.rb +0 -1053
  204. data/test/service.rb +0 -47
  205. data/test/storetestcase.rb +0 -172
  206. data/test/teststore.rb +0 -47
  207. data/test/trustroot.rb +0 -117
@@ -4,46 +4,43 @@ RAILS_ENV = "test"
4
4
  require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb'))
5
5
 
6
6
  module StoreTestCase
7
-
8
7
  @@allowed_handle = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
9
8
  @@allowed_nonce = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
10
-
9
+
11
10
  def _gen_nonce
12
- OpenID::Util.random_string(8, @@allowed_nonce)
11
+ OpenID::CryptUtil.random_string(8, @@allowed_nonce)
13
12
  end
14
13
 
15
14
  def _gen_handle(n)
16
- OpenID::Util.random_string(n, @@allowed_handle)
15
+ OpenID::CryptUtil.random_string(n, @@allowed_handle)
17
16
  end
18
17
 
19
18
  def _gen_secret(n, chars=nil)
20
- OpenID::Util.random_string(n, chars)
19
+ OpenID::CryptUtil.random_string(n, chars)
21
20
  end
22
21
 
23
22
  def _gen_assoc(issued, lifetime=600)
24
23
  secret = _gen_secret(20)
25
24
  handle = _gen_handle(128)
26
- OpenID::Association.new(handle, secret, Time.now.to_i + issued, lifetime,
25
+ OpenID::Association.new(handle, secret, Time.now + issued, lifetime,
27
26
  'HMAC-SHA1')
28
27
  end
29
-
28
+
30
29
  def _check_retrieve(url, handle=nil, expected=nil)
31
30
  ret_assoc = @store.get_association(url, handle)
32
31
 
33
- if expected.nil? or @store.dumb?
32
+ if expected.nil?
34
33
  assert_nil(ret_assoc)
35
34
  else
36
- assert_equal(ret_assoc, expected)
37
- assert_equal(ret_assoc.handle, expected.handle)
38
- assert_equal(ret_assoc.secret, expected.secret)
35
+ assert_equal(expected, ret_assoc)
36
+ assert_equal(expected.handle, ret_assoc.handle)
37
+ assert_equal(expected.secret, ret_assoc.secret)
39
38
  end
40
39
  end
41
40
 
42
41
  def _check_remove(url, handle, expected)
43
42
  present = @store.remove_association(url, handle)
44
- expected_present = ((not @store.dumb?) and expected)
45
- assert ((not expected_present and not present) or \
46
- (expected_present and present))
43
+ assert_equal(expected, present)
47
44
  end
48
45
 
49
46
  def test_store
@@ -132,50 +129,83 @@ module StoreTestCase
132
129
  _check_remove(server_url, assoc2.handle, false)
133
130
  _check_remove(server_url, assoc.handle, false)
134
131
  _check_remove(server_url, assoc3.handle, false)
132
+
133
+ assocValid1 = _gen_assoc(-3600, 7200)
134
+ assocValid2 = _gen_assoc(-5)
135
+ assocExpired1 = _gen_assoc(-7200, 3600)
136
+ assocExpired2 = _gen_assoc(-7200, 3600)
137
+
138
+ @store.cleanup_associations
139
+ @store.store_association(server_url + '1', assocValid1)
140
+ @store.store_association(server_url + '1', assocExpired1)
141
+ @store.store_association(server_url + '2', assocExpired2)
142
+ @store.store_association(server_url + '3', assocValid2)
143
+
144
+ cleaned = @store.cleanup_associations()
145
+ assert_equal(2, cleaned, "cleaned up associations")
135
146
  end
136
-
147
+
148
+ def _check_use_nonce(nonce, expected, server_url, msg='')
149
+ stamp, salt = OpenID::Nonce::split_nonce(nonce)
150
+ actual = @store.use_nonce(server_url, stamp, salt)
151
+ assert_equal(expected, actual, msg)
152
+ end
153
+
137
154
  def test_nonce
138
- nonce1 = _gen_nonce
139
-
140
- assert_not_nil(nonce1)
141
-
142
- # a nonce is present by default
143
- present = @store.use_nonce(nonce1)
144
- assert_equal(present, false)
145
-
146
- # Storing once causes use_nonce to return true the first, and only
147
- # the first, time it is called after the store.
148
- @store.store_nonce(nonce1)
149
- present = @store.use_nonce(nonce1)
150
- assert present
151
- present = @store.use_nonce(nonce1)
152
- assert_equal(present, false)
153
-
154
- # Storing twice has the same effect as storing once.
155
- @store.store_nonce(nonce1)
156
- @store.store_nonce(nonce1)
157
- present = @store.use_nonce(nonce1)
158
- assert present
159
- present = @store.use_nonce(nonce1)
160
- assert_equal(present, false)
161
-
162
- ### Auth key stuff
163
-
164
- # there is no key to start with, so generate a new key and return it
165
- key = @store.get_auth_key
155
+ server_url = "http://www.myopenid.com/openid"
156
+ [server_url, ''].each{|url|
157
+ nonce1 = OpenID::Nonce::mk_nonce
158
+
159
+ _check_use_nonce(nonce1, true, url, "#{url}: nonce allowed by default")
160
+ _check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed twice")
161
+ _check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed third time")
162
+
163
+ # old nonces shouldn't pass
164
+ old_nonce = OpenID::Nonce::mk_nonce(3600)
165
+ _check_use_nonce(old_nonce, false, url, "Old nonce #{old_nonce.inspect} passed")
166
+
167
+ }
168
+
169
+ now = Time.now.to_i
170
+ old_nonce1 = OpenID::Nonce::mk_nonce(now - 20000)
171
+ old_nonce2 = OpenID::Nonce::mk_nonce(now - 10000)
172
+ recent_nonce = OpenID::Nonce::mk_nonce(now - 600)
173
+
174
+ orig_skew = OpenID::Nonce.skew
175
+ OpenID::Nonce.skew = 0
176
+ count = @store.cleanup_nonces
177
+ OpenID::Nonce.skew = 1000000
178
+ ts, salt = OpenID::Nonce::split_nonce(old_nonce1)
179
+ assert(@store.use_nonce(server_url, ts, salt), "oldnonce1")
180
+ ts, salt = OpenID::Nonce::split_nonce(old_nonce2)
181
+ assert(@store.use_nonce(server_url, ts, salt), "oldnonce2")
182
+ ts, salt = OpenID::Nonce::split_nonce(recent_nonce)
183
+ assert(@store.use_nonce(server_url, ts, salt), "recent_nonce")
184
+
166
185
 
167
- # the second time we should return the same key as before
168
- key2 = @store.get_auth_key
169
- assert key == key2
186
+ OpenID::Nonce.skew = 1000
187
+ cleaned = @store.cleanup_nonces
188
+ assert_equal(2, cleaned, "Cleaned #{cleaned} nonces")
189
+
190
+ OpenID::Nonce.skew = 100000
191
+ ts, salt = OpenID::Nonce::split_nonce(old_nonce1)
192
+ assert(@store.use_nonce(server_url, ts, salt), "oldnonce1 after cleanup")
193
+ ts, salt = OpenID::Nonce::split_nonce(old_nonce2)
194
+ assert(@store.use_nonce(server_url, ts, salt), "oldnonce2 after cleanup")
195
+ ts, salt = OpenID::Nonce::split_nonce(recent_nonce)
196
+ assert(!@store.use_nonce(server_url, ts, salt), "recent_nonce after cleanup")
197
+
198
+ OpenID::Nonce.skew = orig_skew
199
+
170
200
  end
171
-
172
201
  end
173
202
 
203
+
174
204
  class TestARStore < Test::Unit::TestCase
175
205
  include StoreTestCase
176
206
 
177
207
  def setup
178
- @store = ActiveRecordOpenIDStore.new
208
+ @store = ActiveRecordStore.new
179
209
  end
180
210
 
181
211
  end
data/examples/discover ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+ require "openid/consumer/discovery"
3
+
4
+ $names = [[:server_url, "Server URL "],
5
+ [:local_id, "Local ID "],
6
+ [:canonical_id, "Canonical ID"],
7
+ ]
8
+
9
+ def show_services(user_input, normalized, services)
10
+ puts " Claimed identifier: #{normalized}"
11
+ if services.empty?
12
+ puts " No OpenID services found"
13
+ puts
14
+ else
15
+ puts " Discovered services:"
16
+ n = 0
17
+ services.each do |service|
18
+ n += 1
19
+ puts " #{n}."
20
+ $names.each do |meth, name|
21
+ val = service.send(meth)
22
+ if val
23
+ printf(" %s: %s\n", name, val)
24
+ end
25
+ end
26
+ puts " Type URIs:"
27
+ for type_uri in service.type_uris
28
+ puts " * #{type_uri}"
29
+ end
30
+ puts
31
+ end
32
+ end
33
+ end
34
+
35
+ ARGV.each do |openid_identifier|
36
+ puts "=" * 50
37
+ puts "Running discovery on #{openid_identifier}"
38
+ begin
39
+ normalized_identifier, services = OpenID.discover(openid_identifier)
40
+ rescue OpenID::Yadis::DiscoveryFailure => why
41
+ puts "Discovery failed: #{why.message}"
42
+ puts
43
+ else
44
+ show_services(openid_identifier, normalized_identifier, services)
45
+ end
46
+ end
File without changes
File without changes
@@ -0,0 +1,115 @@
1
+ require 'pathname'
2
+
3
+ require "openid"
4
+ require 'openid/extensions/sreg'
5
+ require 'openid/extensions/pape'
6
+ require 'openid/store/filesystem'
7
+
8
+ class ConsumerController < ApplicationController
9
+ layout nil
10
+
11
+ def index
12
+ # render an openid form
13
+ end
14
+
15
+ def start
16
+ begin
17
+ oidreq = consumer.begin(params[:openid_identifier])
18
+ rescue OpenID::OpenIDError => e
19
+ flash[:error] = "Discovery failed for #{params[:openid_identifier]}: #{e}"
20
+ redirect_to :action => 'index'
21
+ return
22
+ end
23
+ if params[:use_sreg]
24
+ sregreq = OpenID::SReg::Request.new
25
+ # required fields
26
+ sregreq.request_fields(['email','nickname'], true)
27
+ # optional fields
28
+ sregreq.request_fields(['dob', 'fullname'], false)
29
+ oidreq.add_extension(sregreq)
30
+ oidreq.return_to_args['did_sreg'] = 'y'
31
+ end
32
+ if params[:use_pape]
33
+ papereq = OpenID::PAPE::Request.new
34
+ papereq.add_policy_uri(OpenID::PAPE::AUTH_PHISHING_RESISTANT)
35
+ papereq.max_auth_age = 2*60*60
36
+ oidreq.add_extension(papereq)
37
+ oidreq.return_to_args['did_pape'] = 'y'
38
+ end
39
+ if params[:force_post]
40
+ oidreq.return_to_args['force_post']='x'*2048
41
+ end
42
+ return_to = url_for :action => 'complete', :only_path => false
43
+ realm = url_for :action => 'index', :only_path => false
44
+
45
+ if oidreq.send_redirect?(realm, return_to, params[:immediate])
46
+ redirect_to oidreq.redirect_url(realm, return_to, params[:immediate])
47
+ else
48
+ @form_text = oidreq.form_markup(realm, return_to, params[:immediate], {'id' => 'openid_form'})
49
+ end
50
+ end
51
+
52
+ def complete
53
+ return_to = url_for(:action => 'complete', :only_path => false)
54
+ parameters = params.reject{|k,v|request.path_parameters[k]}
55
+ oidresp = consumer.complete(parameters, return_to)
56
+ case oidresp.status
57
+ when OpenID::Consumer::FAILURE
58
+ if oidresp.display_identifier
59
+ flash[:error] = ("Verification of #{oidresp.display_identifier}"\
60
+ " failed: #{oidresp.message}")
61
+ else
62
+ flash[:error] = "Verification failed: #{oidresp.message}"
63
+ end
64
+ when OpenID::Consumer::SUCCESS
65
+ flash[:success] = ("Verification of #{oidresp.display_identifier}"\
66
+ " succeeded.")
67
+ if params[:did_sreg]
68
+ sreg_resp = OpenID::SReg::Response.from_success_response(oidresp)
69
+ sreg_message = "Simple Registration data was requested"
70
+ if sreg_resp.empty?
71
+ sreg_message << ", but none was returned."
72
+ else
73
+ sreg_message << ". The following data were sent:"
74
+ sreg_resp.data.each {|k,v|
75
+ sreg_message << "<br/><b>#{k}</b>: #{v}"
76
+ }
77
+ end
78
+ flash[:sreg_results] = sreg_message
79
+ end
80
+ if params[:did_pape]
81
+ pape_resp = OpenID::PAPE::Response.from_success_response(oidresp)
82
+ pape_message = "A phishing resistant authentication method was requested"
83
+ if pape_resp.auth_policies.member? OpenID::PAPE::AUTH_PHISHING_RESISTANT
84
+ pape_message << ", and the server reported one."
85
+ else
86
+ pape_message << ", but the server did not report one."
87
+ end
88
+ if pape_resp.auth_age
89
+ pape_message << "<br><b>Authentication age:</b> #{pape_resp.auth_age} seconds"
90
+ end
91
+ if pape_resp.nist_auth_level
92
+ pape_message << "<br><b>NIST Auth Level:</b> #{pape_resp.nist_auth_level}"
93
+ end
94
+ flash[:pape_results] = pape_message
95
+ end
96
+ when OpenID::Consumer::SETUP_NEEDED
97
+ flash[:alert] = "Immediate request failed - Setup Needed"
98
+ when OpenID::Consumer::CANCEL
99
+ flash[:alert] = "OpenID transaction cancelled."
100
+ else
101
+ end
102
+ redirect_to :action => 'index'
103
+ end
104
+
105
+ private
106
+
107
+ def consumer
108
+ if @consumer.nil?
109
+ dir = Pathname.new(RAILS_ROOT).join('db').join('cstore')
110
+ store = OpenID::Store::Filesystem.new(dir)
111
+ @consumer = OpenID::Consumer.new(session, store)
112
+ end
113
+ return @consumer
114
+ end
115
+ end
@@ -5,19 +5,27 @@ class LoginController < ApplicationController
5
5
 
6
6
  layout 'server'
7
7
 
8
+ def base_url
9
+ url_for(:controller => 'login', :action => nil, :only_path => false)
10
+ end
11
+
8
12
  def index
13
+ response.headers['X-XRDS-Location'] = url_for(:controller => "server",
14
+ :action => "idp_xrds",
15
+ :only_path => false)
16
+ @base_url = base_url
9
17
  # just show the login page
10
18
  end
11
19
 
12
20
  def submit
13
- user = @params[:username]
21
+ user = params[:username]
14
22
 
15
23
  # if we get a user, log them in by putting their username in
16
24
  # the session hash.
17
25
  unless user.nil?
18
26
  session[:username] = user unless user.nil?
19
27
  session[:approvals] = []
20
- flash[:notice] = "Your OpenID URL is <b>http://localhost:3000/user/#{user}</b><br/><br/>Proceed to step 2 below."
28
+ flash[:notice] = "Your OpenID URL is <b>#{base_url}user/#{user}</b><br/><br/>Proceed to step 2 below."
21
29
  else
22
30
  flash[:error] = "Sorry, couldn't log you in. Try again."
23
31
  end
@@ -0,0 +1,265 @@
1
+ require 'pathname'
2
+
3
+ # load the openid library, first trying rubygems
4
+ #begin
5
+ # require "rubygems"
6
+ # require_gem "ruby-openid", ">= 1.0"
7
+ #rescue LoadError
8
+ require "openid"
9
+ require "openid/consumer/discovery"
10
+ require 'openid/extensions/sreg'
11
+ require 'openid/extensions/pape'
12
+ require 'openid/store/filesystem'
13
+ #end
14
+
15
+ class ServerController < ApplicationController
16
+
17
+ include ServerHelper
18
+ include OpenID::Server
19
+ layout nil
20
+
21
+ def index
22
+ begin
23
+ oidreq = server.decode_request(params)
24
+ rescue ProtocolError => e
25
+ # invalid openid request, so just display a page with an error message
26
+ render_text e.to_s
27
+ return
28
+ end
29
+
30
+ # no openid.mode was given
31
+ unless oidreq
32
+ render_text "This is an OpenID server endpoint."
33
+ return
34
+ end
35
+
36
+ oidresp = nil
37
+
38
+ if oidreq.kind_of?(CheckIDRequest)
39
+
40
+ identity = oidreq.identity
41
+
42
+ if oidreq.id_select
43
+ if oidreq.immediate
44
+ oidresp = oidreq.answer(false)
45
+ elsif session[:username].nil?
46
+ # The user hasn't logged in.
47
+ show_decision_page(oidreq)
48
+ return
49
+ else
50
+ # Else, set the identity to the one the user is using.
51
+ identity = url_for_user
52
+ end
53
+ end
54
+
55
+ if oidresp
56
+ nil
57
+ elsif self.is_authorized(identity, oidreq.trust_root)
58
+ oidresp = oidreq.answer(true, nil, identity)
59
+
60
+ # add the sreg response if requested
61
+ add_sreg(oidreq, oidresp)
62
+ # ditto pape
63
+ add_pape(oidreq, oidresp)
64
+
65
+ elsif oidreq.immediate
66
+ server_url = url_for :action => 'index'
67
+ oidresp = oidreq.answer(false, server_url)
68
+
69
+ else
70
+ show_decision_page(oidreq)
71
+ return
72
+ end
73
+
74
+ else
75
+ oidresp = server.handle_request(oidreq)
76
+ end
77
+
78
+ self.render_response(oidresp)
79
+ end
80
+
81
+ def show_decision_page(oidreq, message="Do you trust this site with your identity?")
82
+ session[:last_oidreq] = oidreq
83
+ @oidreq = oidreq
84
+
85
+ if message
86
+ flash[:notice] = message
87
+ end
88
+
89
+ render :template => 'server/decide', :layout => 'server'
90
+ end
91
+
92
+ def user_page
93
+ # Yadis content-negotiation: we want to return the xrds if asked for.
94
+ accept = request.env['HTTP_ACCEPT']
95
+
96
+ # This is not technically correct, and should eventually be updated
97
+ # to do real Accept header parsing and logic. Though I expect it will work
98
+ # 99% of the time.
99
+ if accept and accept.include?('application/xrds+xml')
100
+ user_xrds
101
+ return
102
+ end
103
+
104
+ # content negotiation failed, so just render the user page
105
+ xrds_url = url_for(:controller=>'user',:action=>params[:username])+'/xrds'
106
+ identity_page = <<EOS
107
+ <html><head>
108
+ <meta http-equiv="X-XRDS-Location" content="#{xrds_url}" />
109
+ <link rel="openid.server" href="#{url_for :action => 'index'}" />
110
+ </head><body><p>OpenID identity page for #{params[:username]}</p>
111
+ </body></html>
112
+ EOS
113
+
114
+ # Also add the Yadis location header, so that they don't have
115
+ # to parse the html unless absolutely necessary.
116
+ response.headers['X-XRDS-Location'] = xrds_url
117
+ render_text identity_page
118
+ end
119
+
120
+ def user_xrds
121
+ types = [
122
+ OpenID::OPENID_2_0_TYPE,
123
+ OpenID::OPENID_1_0_TYPE,
124
+ OpenID::SREG_URI,
125
+ ]
126
+
127
+ render_xrds(types)
128
+ end
129
+
130
+ def idp_xrds
131
+ types = [
132
+ OpenID::OPENID_IDP_2_0_TYPE,
133
+ ]
134
+
135
+ render_xrds(types)
136
+ end
137
+
138
+ def decision
139
+ oidreq = session[:last_oidreq]
140
+ session[:last_oidreq] = nil
141
+
142
+ if params[:yes].nil?
143
+ redirect_to oidreq.cancel_url
144
+ return
145
+ else
146
+ id_to_send = params[:id_to_send]
147
+
148
+ identity = oidreq.identity
149
+ if oidreq.id_select
150
+ if id_to_send and id_to_send != ""
151
+ session[:username] = id_to_send
152
+ session[:approvals] = []
153
+ identity = url_for_user
154
+ else
155
+ msg = "You must enter a username to in order to send " +
156
+ "an identifier to the Relying Party."
157
+ show_decision_page(oidreq, msg)
158
+ return
159
+ end
160
+ end
161
+
162
+ if session[:approvals]
163
+ session[:approvals] << oidreq.trust_root
164
+ else
165
+ session[:approvals] = [oidreq.trust_root]
166
+ end
167
+ oidresp = oidreq.answer(true, nil, identity)
168
+ add_sreg(oidreq, oidresp)
169
+ add_pape(oidreq, oidresp)
170
+ return self.render_response(oidresp)
171
+ end
172
+ end
173
+
174
+ protected
175
+
176
+ def server
177
+ if @server.nil?
178
+ server_url = url_for :action => 'index', :only_path => false
179
+ dir = Pathname.new(RAILS_ROOT).join('db').join('openid-store')
180
+ store = OpenID::Store::Filesystem.new(dir)
181
+ @server = Server.new(store, server_url)
182
+ end
183
+ return @server
184
+ end
185
+
186
+ def approved(trust_root)
187
+ return false if session[:approvals].nil?
188
+ return session[:approvals].member?(trust_root)
189
+ end
190
+
191
+ def is_authorized(identity_url, trust_root)
192
+ return (session[:username] and (identity_url == url_for_user) and self.approved(trust_root))
193
+ end
194
+
195
+ def render_xrds(types)
196
+ type_str = ""
197
+
198
+ types.each { |uri|
199
+ type_str += "<Type>#{uri}</Type>\n "
200
+ }
201
+
202
+ yadis = <<EOS
203
+ <?xml version="1.0" encoding="UTF-8"?>
204
+ <xrds:XRDS
205
+ xmlns:xrds="xri://$xrds"
206
+ xmlns="xri://$xrd*($v*2.0)">
207
+ <XRD>
208
+ <Service priority="0">
209
+ #{type_str}
210
+ <URI>#{url_for(:controller => 'server', :only_path => false)}</URI>
211
+ </Service>
212
+ </XRD>
213
+ </xrds:XRDS>
214
+ EOS
215
+
216
+ response.headers['content-type'] = 'application/xrds+xml'
217
+ render_text yadis
218
+ end
219
+
220
+ def add_sreg(oidreq, oidresp)
221
+ # check for Simple Registration arguments and respond
222
+ sregreq = OpenID::SReg::Request.from_openid_request(oidreq)
223
+
224
+ return if sregreq.nil?
225
+ # In a real application, this data would be user-specific,
226
+ # and the user should be asked for permission to release
227
+ # it.
228
+ sreg_data = {
229
+ 'nickname' => session[:username],
230
+ 'fullname' => 'Mayor McCheese',
231
+ 'email' => 'mayor@example.com'
232
+ }
233
+
234
+ sregresp = OpenID::SReg::Response.extract_response(sregreq, sreg_data)
235
+ oidresp.add_extension(sregresp)
236
+ end
237
+
238
+ def add_pape(oidreq, oidresp)
239
+ papereq = OpenID::PAPE::Request.from_openid_request(oidreq)
240
+ return if papereq.nil?
241
+ paperesp = OpenID::PAPE::Response.new
242
+ paperesp.nist_auth_level = 0 # we don't even do auth at all!
243
+ oidresp.add_extension(paperesp)
244
+ end
245
+
246
+ def render_response(oidresp)
247
+ if oidresp.needs_signing
248
+ signed_response = server.signatory.sign(oidresp)
249
+ end
250
+ web_response = server.encode_response(oidresp)
251
+
252
+ case web_response.code
253
+ when HTTP_OK
254
+ render :text => web_response.body, :status => 200
255
+
256
+ when HTTP_REDIRECT
257
+ redirect_to web_response.headers['location']
258
+
259
+ else
260
+ render :text => web_response.body, :status => 400
261
+ end
262
+ end
263
+
264
+
265
+ end