ruby-openid 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. data/COPYING +21 -0
  2. data/INSTALL +34 -0
  3. data/README +67 -0
  4. data/TODO +9 -0
  5. data/examples/README +54 -0
  6. data/examples/cacert.pem +7815 -0
  7. data/examples/consumer.rb +285 -0
  8. data/examples/openid-store/associations/http-localhost_3A3000_2Fserver-EMQbAy3NnHVzA.s0u5KAcplKGzo +6 -0
  9. data/examples/openid-store/auth_key +1 -0
  10. data/examples/rails_active_record_store/README +59 -0
  11. data/examples/rails_active_record_store/XX_add_openidstore.rb +30 -0
  12. data/examples/rails_active_record_store/models/openid_association.rb +12 -0
  13. data/examples/rails_active_record_store/models/openid_nonce.rb +3 -0
  14. data/examples/rails_active_record_store/models/openid_setting.rb +2 -0
  15. data/examples/rails_active_record_store/openid_helper.rb +91 -0
  16. data/examples/rails_active_record_store/openidstore_test.rb +15 -0
  17. data/examples/rails_active_record_store/schema.mysql.sql +22 -0
  18. data/examples/rails_active_record_store/schema.postgresql.sql +21 -0
  19. data/examples/rails_active_record_store/schema.sqlite.sql +21 -0
  20. data/examples/rails_openid_login_generator/USAGE +23 -0
  21. data/examples/rails_openid_login_generator/openid_login_generator.rb +36 -0
  22. data/examples/rails_openid_login_generator/templates/README +116 -0
  23. data/examples/rails_openid_login_generator/templates/controller.rb +116 -0
  24. data/examples/rails_openid_login_generator/templates/controller_test.rb +0 -0
  25. data/examples/rails_openid_login_generator/templates/helper.rb +2 -0
  26. data/examples/rails_openid_login_generator/templates/openid_login_system.rb +87 -0
  27. data/examples/rails_openid_login_generator/templates/user.rb +14 -0
  28. data/examples/rails_openid_login_generator/templates/user_test.rb +0 -0
  29. data/examples/rails_openid_login_generator/templates/users.yml +0 -0
  30. data/examples/rails_openid_login_generator/templates/view_login.rhtml +15 -0
  31. data/examples/rails_openid_login_generator/templates/view_logout.rhtml +10 -0
  32. data/examples/rails_openid_login_generator/templates/view_welcome.rhtml +9 -0
  33. data/examples/rails_server/README +153 -0
  34. data/examples/rails_server/Rakefile +10 -0
  35. data/examples/rails_server/app/controllers/application.rb +4 -0
  36. data/examples/rails_server/app/controllers/login_controller.rb +35 -0
  37. data/examples/rails_server/app/controllers/server_controller.rb +185 -0
  38. data/examples/rails_server/app/helpers/application_helper.rb +3 -0
  39. data/examples/rails_server/app/helpers/login_helper.rb +2 -0
  40. data/examples/rails_server/app/helpers/server_helper.rb +9 -0
  41. data/examples/rails_server/app/views/layouts/server.rhtml +61 -0
  42. data/examples/rails_server/app/views/login/index.rhtml +32 -0
  43. data/examples/rails_server/app/views/server/decide.rhtml +11 -0
  44. data/examples/rails_server/config/boot.rb +19 -0
  45. data/examples/rails_server/config/database.yml +85 -0
  46. data/examples/rails_server/config/environment.rb +53 -0
  47. data/examples/rails_server/config/environments/development.rb +19 -0
  48. data/examples/rails_server/config/environments/production.rb +19 -0
  49. data/examples/rails_server/config/environments/test.rb +19 -0
  50. data/examples/rails_server/config/routes.rb +23 -0
  51. data/examples/rails_server/db/openid-store/associations/http-localhost_2F_7Cnormal-YU.tkND1J4fEZhnuAoT5Zc0yCA0 +6 -0
  52. data/examples/rails_server/doc/README_FOR_APP +2 -0
  53. data/examples/rails_server/log/development.log +6059 -0
  54. data/examples/rails_server/log/production.log +0 -0
  55. data/examples/rails_server/log/server.log +0 -0
  56. data/examples/rails_server/log/test.log +0 -0
  57. data/examples/rails_server/public/404.html +8 -0
  58. data/examples/rails_server/public/500.html +8 -0
  59. data/examples/rails_server/public/dispatch.cgi +12 -0
  60. data/examples/rails_server/public/dispatch.fcgi +26 -0
  61. data/examples/rails_server/public/dispatch.rb +12 -0
  62. data/examples/rails_server/public/favicon.ico +0 -0
  63. data/examples/rails_server/public/images/rails.png +0 -0
  64. data/examples/rails_server/public/javascripts/controls.js +750 -0
  65. data/examples/rails_server/public/javascripts/dragdrop.js +584 -0
  66. data/examples/rails_server/public/javascripts/effects.js +854 -0
  67. data/examples/rails_server/public/javascripts/prototype.js +1785 -0
  68. data/examples/rails_server/public/robots.txt +1 -0
  69. data/examples/rails_server/script/about +3 -0
  70. data/examples/rails_server/script/breakpointer +3 -0
  71. data/examples/rails_server/script/console +3 -0
  72. data/examples/rails_server/script/destroy +3 -0
  73. data/examples/rails_server/script/generate +3 -0
  74. data/examples/rails_server/script/performance/benchmarker +3 -0
  75. data/examples/rails_server/script/performance/profiler +3 -0
  76. data/examples/rails_server/script/plugin +3 -0
  77. data/examples/rails_server/script/process/reaper +3 -0
  78. data/examples/rails_server/script/process/spawner +3 -0
  79. data/examples/rails_server/script/process/spinner +3 -0
  80. data/examples/rails_server/script/runner +3 -0
  81. data/examples/rails_server/script/server +3 -0
  82. data/examples/rails_server/test/functional/login_controller_test.rb +18 -0
  83. data/examples/rails_server/test/functional/server_controller_test.rb +18 -0
  84. data/examples/rails_server/test/test_helper.rb +28 -0
  85. data/lib/hmac-md5.rb +11 -0
  86. data/lib/hmac-rmd160.rb +11 -0
  87. data/lib/hmac-sha1.rb +11 -0
  88. data/lib/hmac-sha2.rb +25 -0
  89. data/lib/hmac.rb +112 -0
  90. data/lib/openid/association.rb +109 -0
  91. data/lib/openid/consumer.rb +928 -0
  92. data/lib/openid/dh.rb +48 -0
  93. data/lib/openid/discovery.rb +89 -0
  94. data/lib/openid/fetchers.rb +119 -0
  95. data/lib/openid/filestore.rb +315 -0
  96. data/lib/openid/htmltokenizer.rb +355 -0
  97. data/lib/openid/parse.rb +23 -0
  98. data/lib/openid/server.rb +951 -0
  99. data/lib/openid/service.rb +135 -0
  100. data/lib/openid/stores.rb +178 -0
  101. data/lib/openid/trustroot.rb +100 -0
  102. data/lib/openid/util.rb +273 -0
  103. data/test/assoc.rb +38 -0
  104. data/test/consumer.rb +384 -0
  105. data/test/dh.rb +20 -0
  106. data/test/extensions.rb +30 -0
  107. data/test/linkparse.rb +305 -0
  108. data/test/runtests.rb +11 -0
  109. data/test/server2.rb +1053 -0
  110. data/test/storetestcase.rb +172 -0
  111. data/test/teststore.rb +23 -0
  112. data/test/trustroot.rb +113 -0
  113. data/test/util.rb +56 -0
  114. metadata +218 -0
data/test/assoc.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'test/unit'
2
+ require 'openid/association'
3
+
4
+ class AssociationTestCase < Test::Unit::TestCase
5
+
6
+ def _get_assoc
7
+ issued = Time.now.to_i
8
+ lifetime = 600
9
+ OpenID::Association.new('handle', 'secret', issued, lifetime, 'HMAC-SHA1')
10
+ end
11
+
12
+ def test_assoc
13
+ assoc = _get_assoc
14
+ s = OpenID::Association.serialize(assoc)
15
+ assert_equal(assoc, OpenID::Association.deserialize(s))
16
+ end
17
+
18
+ def test_sign
19
+ assoc = _get_assoc
20
+
21
+ h = {
22
+ 'openid.a' => 'b',
23
+ 'openid.c' => 'd',
24
+ }
25
+
26
+ assoc.add_signature(['a','c'], h)
27
+ assert_not_nil(h['openid.signed'])
28
+ assert_not_nil(h['openid.sig'])
29
+ assert_equal(h['openid.signed'], 'a,c')
30
+
31
+ sig = OpenID::Util.to_base64( \
32
+ OpenID::Util.hmac_sha1(assoc.secret, "a:b\nc:d\n"))
33
+
34
+ assert_equal(h['openid.sig'], sig)
35
+ end
36
+
37
+ end
38
+
data/test/consumer.rb ADDED
@@ -0,0 +1,384 @@
1
+ require 'cgi'
2
+ require 'uri'
3
+ require 'test/unit'
4
+
5
+ require 'openid/util'
6
+ require 'openid/dh'
7
+ require 'openid/stores'
8
+ require 'openid/consumer'
9
+ require 'openid/service'
10
+ require 'openid/association'
11
+
12
+ ASSOCS = [
13
+ ['another 20-byte key.', 'Snarky'],
14
+ ["\x00" * 20, 'Zeros']
15
+ ]
16
+
17
+ HTTP_SERVER_URL = 'http://server.example.com/'
18
+ HTTPS_SERVER_URL = 'https://server.example.com/'
19
+ CONSUMER_URL = 'http://consumer.example.com/'
20
+
21
+
22
+ # extract a hash from an application/x-www-form-urlencoded string
23
+ def parse_query(qs)
24
+ query = {}
25
+ CGI::parse(qs).each {|k,v| query[k] = v[0]}
26
+ return query
27
+ end
28
+
29
+ # do the server side associate using the given secret and handle
30
+ def associate(qs, assoc_secret, assoc_handle)
31
+ q = parse_query(qs)
32
+ raise ArgumentError unless q['openid.mode'] == 'associate'
33
+ raise ArgumentError unless q['openid.assoc_type'] == 'HMAC-SHA1'
34
+
35
+ if q['openid.session_type'] == 'DH-SHA1'
36
+ raise ArgumentError unless [4,6].member?(q.length)
37
+ d = OpenID::DiffieHellman.from_base64(q['openid.dh_modulus'],
38
+ q['openid.dh_gen'])
39
+ composite = OpenID::Util.base64_to_num(q['openid.dh_consumer_public'])
40
+ enc_mac_key = OpenID::Util.to_base64(d.xor_secrect(composite,
41
+ assoc_secret))
42
+ reply = {
43
+ 'assoc_type' => 'HMAC-SHA1',
44
+ 'assoc_handle' => assoc_handle,
45
+ 'expires_in' => '600',
46
+ 'session_type' => 'DH-SHA1',
47
+ 'dh_server_public' => OpenID::Util.num_to_base64(d.public),
48
+ 'enc_mac_key' => enc_mac_key
49
+ }
50
+ else
51
+ # dumb mode
52
+ raise ArgumentError unless q.length == 2
53
+ mac_key = OpenID::Util.to_base64(assoc_secret)
54
+ reply = {
55
+ 'assoc_type' => 'HMAC-SHA1',
56
+ 'assoc_handle' => assoc_handle,
57
+ 'expires_in' => '600',
58
+ 'mac_key' => mac_key
59
+ }
60
+ end
61
+
62
+ return OpenID::Util.kvform(reply)
63
+ end
64
+
65
+
66
+ class TestFetcher
67
+
68
+ attr_accessor :get_responses, :assoc_secret, :assoc_handle, :num_assocs
69
+
70
+ def initialize(assoc_secret, assoc_handle)
71
+ @get_responses = {}
72
+ @assoc_secret = assoc_secret
73
+ @assoc_handle = assoc_handle
74
+ @num_assocs = 0
75
+ end
76
+
77
+ def response(url, status, body)
78
+ return [url, body]
79
+ end
80
+
81
+ def fetch(url, body=nil, headers=nil)
82
+ if body.nil?
83
+ return @get_responses[url] if @get_responses.has_key?(url)
84
+
85
+ else
86
+ if body.include?('openid.mode=associate')
87
+ response = associate(body, @assoc_secret, @assoc_handle)
88
+ @num_assocs += 1
89
+ return [url, response]
90
+ end
91
+ end
92
+
93
+ return [url, 'not found']
94
+ end
95
+
96
+ def get(url)
97
+ return self.fetch(url)
98
+ end
99
+
100
+ def post(url, body)
101
+ return self.fetch(url, body)
102
+ end
103
+
104
+ end
105
+
106
+ class SuccessFlowTest < Test::Unit::TestCase
107
+
108
+ def _test_success(service, immediate=false)
109
+ store = OpenID::MemoryStore.new
110
+ mode = immediate ? 'checkid_immediate' : 'checkid_setup'
111
+
112
+ assoc_secret, assoc_handle = ASSOCS[0]
113
+ fetcher = TestFetcher.new(assoc_secret, assoc_handle)
114
+
115
+ run = Proc.new {
116
+ trust_root = CONSUMER_URL
117
+ return_to = CONSUMER_URL
118
+ session = {}
119
+
120
+ consumer = OpenID::Consumer.new(session, store, fetcher)
121
+ req = consumer.begin_without_discovery(service)
122
+
123
+ # need to extract the return_to url
124
+
125
+ return_to = req.return_to(return_to)
126
+
127
+ assert_equal(OpenID::SUCCESS, req.status)
128
+
129
+ redirect_url = req.redirect_url(trust_root, return_to, immediate)
130
+ assert redirect_url.starts_with?(service.server_url)
131
+
132
+ # make sure the query in the redirect URL is what we want
133
+ q = parse_query(URI.parse(redirect_url).query)
134
+
135
+ assert_equal(mode, q['openid.mode'])
136
+ assert_equal(service.server_id, q['openid.identity'])
137
+ assert_equal(trust_root, q['openid.trust_root'])
138
+ assert_equal(fetcher.assoc_handle, q['openid.assoc_handle'])
139
+
140
+ # make sure the return_to has the nonce in it
141
+ return_to_query = parse_query(URI.parse(q['openid.return_to']).query)
142
+ assert return_to_query.has_key?('nonce')
143
+
144
+ # build a fake response from the OpenID server
145
+ query = {
146
+ 'openid.mode' => 'id_res',
147
+ 'openid.return_to' => 'return_to',
148
+ 'openid.identity' => service.server_id,
149
+ 'openid.assoc_handle' => fetcher.assoc_handle,
150
+ 'nonce' => return_to_query['nonce']
151
+ }
152
+
153
+ # sign the fake response with our assoc
154
+ assoc = store.get_association(service.server_url, fetcher.assoc_handle)
155
+ assoc.add_signature(['mode','return_to','identity'], query)
156
+
157
+ # complete the auth
158
+ resp = consumer.complete(query)
159
+
160
+ if resp.status == OpenID::FAILURE
161
+ p 'Failure Message', resp.msg
162
+ end
163
+
164
+ # we're testing success here, so make sure we have a success response
165
+ assert_equal(OpenID::SUCCESS, resp.status)
166
+
167
+ # make sure we've got the right identity url
168
+ assert_equal(service.consumer_id, resp.identity_url)
169
+ }
170
+
171
+ assert_equal(0, fetcher.num_assocs)
172
+ run.call
173
+ assert_equal(1, fetcher.num_assocs)
174
+
175
+ # make sure we use the same association
176
+ run.call
177
+ assert_equal(1, fetcher.num_assocs)
178
+
179
+ # another assoc is created if we remove the existing one
180
+ store.remove_association(service.server_url, fetcher.assoc_handle)
181
+ run.call
182
+ assert_equal(2, fetcher.num_assocs)
183
+ run.call
184
+ assert_equal(2, fetcher.num_assocs)
185
+ end
186
+
187
+ def test_no_delegate
188
+ service = OpenID::FakeOpenIDServiceEndpoint.new(
189
+ 'http://example.com/user.html',
190
+ 'http://example.com/user.html',
191
+ HTTP_SERVER_URL)
192
+ self._test_success(service)
193
+ end
194
+
195
+ def test_nodelegate_immediate
196
+ service = OpenID::FakeOpenIDServiceEndpoint.new(
197
+ 'http://example.com/user.html',
198
+ 'http://example.com/user.html',
199
+ HTTP_SERVER_URL)
200
+ self._test_success(service, true)
201
+ end
202
+
203
+ def test_delegate
204
+ s = OpenID::FakeOpenIDServiceEndpoint.new(
205
+ 'http://example.com/user.html',
206
+ 'http://server.com/user.html',
207
+ HTTP_SERVER_URL)
208
+ self._test_success(s)
209
+ end
210
+
211
+ def test_delegate_immediate
212
+ s = OpenID::FakeOpenIDServiceEndpoint.new(
213
+ 'http://example.com/user.html',
214
+ 'http://server.com/user.html',
215
+ HTTP_SERVER_URL)
216
+ self._test_success(s, true)
217
+ end
218
+
219
+ def test_https
220
+ service = OpenID::FakeOpenIDServiceEndpoint.new(
221
+ 'http://example.com/user.html',
222
+ 'http://example.com/user.html',
223
+ HTTPS_SERVER_URL)
224
+ self._test_success(service)
225
+ end
226
+
227
+ end
228
+
229
+
230
+ class TestIdRes < Test::Unit::TestCase
231
+
232
+ def test_setup_needed
233
+ store = OpenID::MemoryStore.new
234
+ consumer = OpenID::GenericConsumer.new(store)
235
+ return_to = "nonny"
236
+ server_id = "sirod"
237
+ server_url = "serlie"
238
+ consumer_id = "consu"
239
+ setup_url = "http://example.com/setup-here"
240
+
241
+ query = {
242
+ 'openid.mode' => 'id_res',
243
+ 'openid.user_setup_url' => setup_url
244
+ }
245
+
246
+ # this isn't really necessary, but we'll make sure the token
247
+ # generation and extraction stuff works
248
+ token = consumer.gen_token(consumer_id, server_id, server_url)
249
+ consumer_id, server_id, server_url = consumer.split_token(token)
250
+ nonce = consumer.create_nonce
251
+
252
+ ret = consumer.do_id_res(nonce, consumer_id, server_id, server_url, query)
253
+
254
+ assert_equal(OpenID::SETUP_NEEDED, ret.status)
255
+ assert_equal(setup_url, ret.setup_url)
256
+ end
257
+
258
+ end
259
+
260
+
261
+ class CheckAuthHappened < Exception; end
262
+
263
+ class CheckAuthDetectingConsumer < OpenID::GenericConsumer
264
+
265
+ def check_auth(nonce, query, server_url)
266
+ raise CheckAuthHappened
267
+ end
268
+
269
+ end
270
+
271
+ class TestCheckAuth < Test::Unit::TestCase
272
+
273
+ def setup
274
+ @store = OpenID::MemoryStore.new
275
+ @consumer = CheckAuthDetectingConsumer.new(@store)
276
+ @return_to = "nonny"
277
+ @server_id = "sirod"
278
+ @server_url = "http://server.com/url"
279
+ @consumer_id = "consu"
280
+ @nonce = @consumer.create_nonce
281
+ @token = @consumer.gen_token(@consumer_id,
282
+ @server_id,
283
+ @server_url)
284
+ @setup_url = "http://example.com/setup-here"
285
+ end
286
+
287
+
288
+ def _do_id_res(query)
289
+ return @consumer.do_id_res(@nonce, @consumer_id, @server_id, @server_url,
290
+ query)
291
+ end
292
+
293
+ def test_chech_auth_triggered
294
+ query = {
295
+ 'openid.return_to' => @return_to,
296
+ 'openid.identity' => @server_id,
297
+ 'openid.assoc_handle' => 'not_found'
298
+ }
299
+ begin
300
+ self._do_id_res(query)
301
+ rescue CheckAuthHappened
302
+ assert true
303
+ else
304
+ raise 'CheckAuthDidntHappen'
305
+ end
306
+ end
307
+
308
+ def test_check_auth_triggered_with_assoc
309
+ issued = Time.now.to_i
310
+ lifetime = 1000
311
+ assoc = OpenID::Association.new('handle',
312
+ 'secret',
313
+ issued,
314
+ lifetime, 'HMAC-SHA1')
315
+
316
+ @store.store_association(@server_url, assoc)
317
+
318
+ query = {
319
+ 'openid.return_to' => @return_to,
320
+ 'openid.identity' => @server_id,
321
+ 'openid.assoc_handle' => 'bad_assoc_handle_for_assoc!'
322
+ }
323
+
324
+ begin
325
+ result = self._do_id_res(query)
326
+ rescue CheckAuthHappened
327
+ assert true
328
+ else
329
+ raise ArgumentError.new(result.msg)
330
+ end
331
+ end
332
+
333
+ def test_expired_assoc
334
+ issued = Time.now.to_i - 10
335
+ lifetime = 0
336
+ handle = 'handle'
337
+ assoc = OpenID::Association.new(handle, 'secret', issued, lifetime,
338
+ 'HMAC-SHA1')
339
+ assert assoc.expires_in <= 0
340
+ @store.store_association(@server_url, assoc)
341
+
342
+ query = {
343
+ 'openid.return_to' => @return_to,
344
+ 'openid.identity' => @server_id,
345
+ 'openid.assoc_handle' => handle
346
+ }
347
+
348
+ info = self._do_id_res(query)
349
+ assert_equal(OpenID::FAILURE, info.status)
350
+ assert_equal(@consumer_id, info.identity_url)
351
+ end
352
+
353
+ def test_newer_assoc
354
+ lifetime = 1000
355
+ good_issued = Time.now.to_i - 10
356
+ good_handle = 'handle'
357
+ good_assoc = OpenID::Association.new(good_handle, 'secret',
358
+ good_issued, lifetime, 'HMAC-SHA1')
359
+ @store.store_association(@server_url, good_assoc)
360
+
361
+ bad_issued = Time.now.to_i - 5
362
+ bad_handle = 'handle2'
363
+ bad_assoc = OpenID::Association.new(bad_handle, 'secret',
364
+ bad_issued, lifetime, 'HMAC-SHA1')
365
+ @store.store_association(@server_url, bad_assoc)
366
+
367
+ query = {
368
+ 'openid.return_to' => @return_to,
369
+ 'openid.identity' => @server_id,
370
+ 'openid.assoc_handle' => good_handle
371
+ }
372
+
373
+ good_assoc.add_signature(['return_to','identity'], query)
374
+ info = self._do_id_res(query)
375
+
376
+ if info.status != OpenID::SUCCESS
377
+ p 'Failure Message', info.msg
378
+ end
379
+
380
+ assert_equal(OpenID::SUCCESS, info.status)
381
+ assert_equal(@consumer_id, info.identity_url)
382
+ end
383
+
384
+ end
data/test/dh.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'test/unit'
2
+
3
+ require "openid/dh"
4
+ require "openid/util"
5
+
6
+ # Diffie Hellman test case
7
+
8
+ class DiffieHellmanTestCase < Test::Unit::TestCase
9
+
10
+ def test_dh
11
+ dh1 = OpenID::DiffieHellman.new
12
+ dh2 = OpenID::DiffieHellman.new
13
+
14
+ secret1 = dh1.get_shared_secret(dh2.public)
15
+ secret2 = dh2.get_shared_secret(dh1.public)
16
+ assert(secret1 == secret2)
17
+ end
18
+
19
+ end
20
+
@@ -0,0 +1,30 @@
1
+ require "test/unit"
2
+
3
+ require "openid/extensions"
4
+ require "openid/sreg"
5
+ require "openid/util"
6
+
7
+ class UtilTestCase < Test::Unit::TestCase
8
+
9
+ def test_sreg
10
+ secret = 'foo'
11
+ openid_sig = 'xxx'
12
+
13
+ ext_content = "openid.sig:xxx\nsreg.dob:0000-00-00\nsreg.email:foo@bar.com\n"
14
+ ext_sig = OpenID::Util.to_base64(OpenID::Util.hmac_sha1(secret, ext_content))
15
+ query = {
16
+ 'openid.sig' => openid_sig,
17
+ 'sreg.email' => 'foo@bar.com',
18
+ 'sreg.dob' => '0000-00-00',
19
+ 'sreg.sig' => ext_sig
20
+ }
21
+
22
+ sreg = OpenID::SREG.create(secret, query)
23
+ assert_not_nil(sreg)
24
+ assert_equal(ext_content, sreg.ext_content)
25
+ assert_equal(ext_sig, sreg.gen_sig)
26
+ assert_equal(true, sreg.check_sig)
27
+ assert_equal(true, OpenID::SREG.check(secret, query))
28
+ end
29
+
30
+ end