ruby-openid 2.1.6 → 2.1.7
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.
Potentially problematic release.
This version of ruby-openid might be problematic. Click here for more details.
- data/CHANGELOG +32 -12
- data/admin/runtests.rb +10 -1
- data/lib/openid.rb +1 -1
- data/lib/openid/consumer/associationmanager.rb +4 -0
- data/lib/openid/store/memcache.rb +107 -0
- data/test/test_associationmanager.rb +18 -18
- data/test/test_stores.rb +51 -22
- metadata +3 -2
data/CHANGELOG
CHANGED
@@ -1,15 +1,35 @@
|
|
1
|
-
|
2
|
-
tagged 2.1.
|
3
|
-
Ignore-this:
|
1
|
+
Wed Jul 1 15:07:23 PDT 2009 chowells@janrain.com
|
2
|
+
tagged 2.1.7
|
3
|
+
Ignore-this: 9bef91a9c9d6232961500dd4b9416c14
|
4
|
+
|
5
|
+
Wed Jul 1 14:43:24 PDT 2009 chowells@janrain.com
|
6
|
+
* update version to 2.1.7
|
7
|
+
Ignore-this: 9b158a7f5c948b1a042331bf8137e95d
|
8
|
+
|
9
|
+
Wed Jul 1 12:23:50 PDT 2009 chowells@janrain.com
|
10
|
+
* Handle malformed associate responses better in negotiate association
|
11
|
+
Ignore-this: 13d2c5718f1f798d3e60ce9ffac9a135
|
12
|
+
|
13
|
+
Wed Jul 1 12:05:19 PDT 2009 chowells@janrain.com
|
14
|
+
* whitespace
|
15
|
+
Ignore-this: e4b91f8280dc1591726467448a468188
|
4
16
|
|
5
|
-
|
6
|
-
*
|
7
|
-
Ignore-this:
|
17
|
+
Mon Jun 29 15:19:08 PDT 2009 cygnus@janrain.com
|
18
|
+
* Add memcache store implementation and tests
|
19
|
+
Ignore-this: a8cde55ae2c28a9ba6f8c0a46436d336
|
8
20
|
|
9
|
-
Mon
|
10
|
-
*
|
11
|
-
Ignore-this:
|
21
|
+
Mon Jun 29 15:18:41 PDT 2009 cygnus@janrain.com
|
22
|
+
* Store tests: loosen get_association tests so that it is only asserting that we are not returning deleted associations rather than testing that we return a particular association
|
23
|
+
Ignore-this: a2514be4e99da76ca8c55a78bf10817a
|
12
24
|
|
13
|
-
|
14
|
-
|
15
|
-
Ignore-this:
|
25
|
+
Mon Jun 29 15:17:04 PDT 2009 cygnus@janrain.com
|
26
|
+
* Store tests: separate cleanup tests from other store tests
|
27
|
+
Ignore-this: 49ce6bc616af0deb063d8b1a9633ee0a
|
28
|
+
|
29
|
+
Mon Jun 29 15:15:49 PDT 2009 cygnus@janrain.com
|
30
|
+
* whitespace
|
31
|
+
Ignore-this: a69795c5131e0cf6f687ccc8dfbba61a
|
32
|
+
|
33
|
+
Tue Apr 21 11:42:57 PDT 2009 cygnus@janrain.com
|
34
|
+
tagged 2.1.6
|
35
|
+
Ignore-this: b97ef05fbb348ace2f86513a5de7db46
|
data/admin/runtests.rb
CHANGED
@@ -7,6 +7,16 @@ require "pathname"
|
|
7
7
|
require 'test/unit/collector/dir'
|
8
8
|
require 'test/unit/ui/console/testrunner'
|
9
9
|
|
10
|
+
begin
|
11
|
+
require 'rubygems'
|
12
|
+
require 'memcache'
|
13
|
+
rescue LoadError
|
14
|
+
else
|
15
|
+
if ENV['TESTING_MEMCACHE']
|
16
|
+
TESTING_MEMCACHE = MemCache.new(ENV['TESTING_MEMCACHE'])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
10
20
|
def main
|
11
21
|
old_verbose = $VERBOSE
|
12
22
|
$VERBOSE = true
|
@@ -26,7 +36,6 @@ def main
|
|
26
36
|
suite = c.collect(tests_dir)
|
27
37
|
end
|
28
38
|
|
29
|
-
|
30
39
|
result = Test::Unit::UI::Console::TestRunner.run(suite)
|
31
40
|
result.passed?
|
32
41
|
ensure
|
data/lib/openid.rb
CHANGED
@@ -143,6 +143,10 @@ module OpenID
|
|
143
143
|
return nil
|
144
144
|
end
|
145
145
|
end
|
146
|
+
rescue InvalidOpenIDNamespace
|
147
|
+
Util.log("Server #{@server_url} returned a malformed association " \
|
148
|
+
"response. Falling back to check_id mode for this request.")
|
149
|
+
return nil
|
146
150
|
end
|
147
151
|
end
|
148
152
|
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'openid/util'
|
2
|
+
require 'openid/store/interface'
|
3
|
+
require 'openid/store/nonce'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
module OpenID
|
7
|
+
module Store
|
8
|
+
class Memcache < Interface
|
9
|
+
attr_accessor :key_prefix
|
10
|
+
|
11
|
+
def initialize(cache_client, key_prefix='openid-store:')
|
12
|
+
@cache_client = cache_client
|
13
|
+
self.key_prefix = key_prefix
|
14
|
+
end
|
15
|
+
|
16
|
+
# Put a Association object into storage.
|
17
|
+
# When implementing a store, don't assume that there are any limitations
|
18
|
+
# on the character set of the server_url. In particular, expect to see
|
19
|
+
# unescaped non-url-safe characters in the server_url field.
|
20
|
+
def store_association(server_url, association)
|
21
|
+
serialized = serialize(association)
|
22
|
+
[nil, association.handle].each do |handle|
|
23
|
+
key = assoc_key(server_url, handle)
|
24
|
+
@cache_client.set(key, serialized, expiry(association.lifetime))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a Association object from storage that matches
|
29
|
+
# the server_url. Returns nil if no such association is found or if
|
30
|
+
# the one matching association is expired. (Is allowed to GC expired
|
31
|
+
# associations when found.)
|
32
|
+
def get_association(server_url, handle=nil)
|
33
|
+
serialized = @cache_client.get(assoc_key(server_url, handle))
|
34
|
+
if serialized
|
35
|
+
return deserialize(serialized)
|
36
|
+
else
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# If there is a matching association, remove it from the store and
|
42
|
+
# return true, otherwise return false.
|
43
|
+
def remove_association(server_url, handle)
|
44
|
+
deleted = delete(assoc_key(server_url, handle))
|
45
|
+
server_assoc = get_association(server_url)
|
46
|
+
if server_assoc && server_assoc.handle == handle
|
47
|
+
deleted = delete(assoc_key(server_url)) | deleted
|
48
|
+
end
|
49
|
+
return deleted
|
50
|
+
end
|
51
|
+
|
52
|
+
# Return true if the nonce has not been used before, and store it
|
53
|
+
# for a while to make sure someone doesn't try to use the same value
|
54
|
+
# again. Return false if the nonce has already been used or if the
|
55
|
+
# timestamp is not current.
|
56
|
+
# You can use OpenID::Store::Nonce::SKEW for your timestamp window.
|
57
|
+
# server_url: URL of the server from which the nonce originated
|
58
|
+
# timestamp: time the nonce was created in seconds since unix epoch
|
59
|
+
# salt: A random string that makes two nonces issued by a server in
|
60
|
+
# the same second unique
|
61
|
+
def use_nonce(server_url, timestamp, salt)
|
62
|
+
return false if (timestamp - Time.now.to_i).abs > Nonce.skew
|
63
|
+
ts = timestamp.to_s # base 10 seconds since epoch
|
64
|
+
nonce_key = key_prefix + 'N' + server_url + '|' + ts + '|' + salt
|
65
|
+
result = @cache_client.add(nonce_key, '', expiry(Nonce.skew + 5))
|
66
|
+
return !!(result =~ /^STORED/)
|
67
|
+
end
|
68
|
+
|
69
|
+
def assoc_key(server_url, assoc_handle=nil)
|
70
|
+
key = key_prefix + 'A' + server_url
|
71
|
+
if assoc_handle
|
72
|
+
key += '|' + assoc_handle
|
73
|
+
end
|
74
|
+
return key
|
75
|
+
end
|
76
|
+
|
77
|
+
def cleanup_nonces
|
78
|
+
end
|
79
|
+
|
80
|
+
def cleanup
|
81
|
+
end
|
82
|
+
|
83
|
+
def cleanup_associations
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def delete(key)
|
89
|
+
result = @cache_client.delete(key)
|
90
|
+
return !!(result =~ /^DELETED/)
|
91
|
+
end
|
92
|
+
|
93
|
+
def serialize(assoc)
|
94
|
+
Marshal.dump(assoc)
|
95
|
+
end
|
96
|
+
|
97
|
+
def deserialize(assoc_str)
|
98
|
+
Marshal.load(assoc_str)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Convert a lifetime in seconds into a memcache expiry value
|
102
|
+
def expiry(t)
|
103
|
+
Time.now.to_i + t
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -314,9 +314,9 @@ module OpenID
|
|
314
314
|
# in an unsupported-type response is absent.
|
315
315
|
def test_empty_assoc_type
|
316
316
|
msg = mk_message({'error' => 'Unsupported type',
|
317
|
-
|
318
|
-
|
319
|
-
|
317
|
+
'error_code' => 'unsupported-type',
|
318
|
+
'session_type' => 'new-session-type',
|
319
|
+
})
|
320
320
|
|
321
321
|
assert_log_matches('Unsupported association type',
|
322
322
|
"Server #{@server_url} responded with unsupported "\
|
@@ -331,9 +331,9 @@ module OpenID
|
|
331
331
|
# in an unsupported-type response is absent.
|
332
332
|
def test_empty_session_type
|
333
333
|
msg = mk_message({'error' => 'Unsupported type',
|
334
|
-
|
335
|
-
|
336
|
-
|
334
|
+
'error_code' => 'unsupported-type',
|
335
|
+
'assoc_type' => 'new-assoc-type',
|
336
|
+
})
|
337
337
|
|
338
338
|
assert_log_matches('Unsupported association type',
|
339
339
|
"Server #{@server_url} responded with unsupported "\
|
@@ -352,10 +352,10 @@ module OpenID
|
|
352
352
|
@allowed_types = [['assoc_bogus', 'session_bogus']]
|
353
353
|
}
|
354
354
|
msg = mk_message({'error' => 'Unsupported type',
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
355
|
+
'error_code' => 'unsupported-type',
|
356
|
+
'assoc_type' => 'not-allowed',
|
357
|
+
'session_type' => 'not-allowed',
|
358
|
+
})
|
359
359
|
|
360
360
|
assert_log_matches('Unsupported association type',
|
361
361
|
'Server sent unsupported session/association type:') {
|
@@ -367,10 +367,10 @@ module OpenID
|
|
367
367
|
# retry to get an association with the new preferred type.
|
368
368
|
def test_unsupported_with_retry
|
369
369
|
msg = mk_message({'error' => 'Unsupported type',
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
370
|
+
'error_code' => 'unsupported-type',
|
371
|
+
'assoc_type' => 'HMAC-SHA1',
|
372
|
+
'session_type' => 'DH-SHA1',
|
373
|
+
})
|
374
374
|
|
375
375
|
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
|
376
376
|
|
@@ -383,10 +383,10 @@ module OpenID
|
|
383
383
|
# retry, but the retry fails and nil is returned instead.
|
384
384
|
def test_unsupported_with_retry_and_fail
|
385
385
|
msg = mk_message({'error' => 'Unsupported type',
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
386
|
+
'error_code' => 'unsupported-type',
|
387
|
+
'assoc_type' => 'HMAC-SHA1',
|
388
|
+
'session_type' => 'DH-SHA1',
|
389
|
+
})
|
390
390
|
|
391
391
|
assert_log_matches('Unsupported association type',
|
392
392
|
"Server #{@server_url} refused") {
|
data/test/test_stores.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
require 'openid/store/interface'
|
3
3
|
require 'openid/store/filesystem'
|
4
|
+
require 'openid/store/memcache'
|
4
5
|
require 'openid/store/memory'
|
5
6
|
require 'openid/util'
|
6
7
|
require 'openid/store/nonce'
|
@@ -11,7 +12,7 @@ module OpenID
|
|
11
12
|
module StoreTestCase
|
12
13
|
@@allowed_handle = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
|
13
14
|
@@allowed_nonce = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
14
|
-
|
15
|
+
|
15
16
|
def _gen_nonce
|
16
17
|
OpenID::CryptUtil.random_string(8, @@allowed_nonce)
|
17
18
|
end
|
@@ -28,9 +29,9 @@ module OpenID
|
|
28
29
|
secret = _gen_secret(20)
|
29
30
|
handle = _gen_handle(128)
|
30
31
|
OpenID::Association.new(handle, secret, Time.now + issued, lifetime,
|
31
|
-
'HMAC-SHA1')
|
32
|
+
'HMAC-SHA1')
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
def _check_retrieve(url, handle=nil, expected=nil)
|
35
36
|
ret_assoc = @store.get_association(url, handle)
|
36
37
|
|
@@ -49,7 +50,6 @@ module OpenID
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def test_store
|
52
|
-
server_url = "http://www.myopenid.com/openid"
|
53
53
|
assoc = _gen_assoc(issued=0)
|
54
54
|
|
55
55
|
# Make sure that a missing association returns no result
|
@@ -117,7 +117,11 @@ module OpenID
|
|
117
117
|
_check_remove(server_url, assoc2.handle, false)
|
118
118
|
_check_remove(server_url, assoc3.handle, true)
|
119
119
|
|
120
|
-
|
120
|
+
ret_assoc = @store.get_association(server_url, nil)
|
121
|
+
unexpected = [assoc2.handle, assoc3.handle]
|
122
|
+
assert(ret_assoc.nil? || !unexpected.member?(ret_assoc.handle),
|
123
|
+
ret_assoc)
|
124
|
+
|
121
125
|
_check_retrieve(server_url, assoc.handle, assoc)
|
122
126
|
_check_retrieve(server_url, assoc2.handle, nil)
|
123
127
|
_check_retrieve(server_url, assoc3.handle, nil)
|
@@ -134,7 +138,9 @@ module OpenID
|
|
134
138
|
_check_remove(server_url, assoc2.handle, false)
|
135
139
|
_check_remove(server_url, assoc.handle, false)
|
136
140
|
_check_remove(server_url, assoc3.handle, false)
|
141
|
+
end
|
137
142
|
|
143
|
+
def test_assoc_cleanup
|
138
144
|
assocValid1 = _gen_assoc(-3600, 7200)
|
139
145
|
assocValid2 = _gen_assoc(-5)
|
140
146
|
assocExpired1 = _gen_assoc(-7200, 3600)
|
@@ -156,21 +162,26 @@ module OpenID
|
|
156
162
|
assert_equal(expected, actual, msg)
|
157
163
|
end
|
158
164
|
|
165
|
+
def server_url
|
166
|
+
"http://www.myopenid.com/openid"
|
167
|
+
end
|
168
|
+
|
159
169
|
def test_nonce
|
160
|
-
server_url = "http://www.myopenid.com/openid"
|
161
170
|
[server_url, ''].each{|url|
|
162
171
|
nonce1 = Nonce::mk_nonce
|
163
172
|
|
164
|
-
_check_use_nonce(nonce1, true, url, "#{url}: nonce allowed by default")
|
165
|
-
_check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed twice")
|
173
|
+
_check_use_nonce(nonce1, true, url, "#{url}: nonce allowed by default")
|
174
|
+
_check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed twice")
|
166
175
|
_check_use_nonce(nonce1, false, url, "#{url}: nonce not allowed third time")
|
167
|
-
|
176
|
+
|
168
177
|
# old nonces shouldn't pass
|
169
178
|
old_nonce = Nonce::mk_nonce(3600)
|
170
179
|
_check_use_nonce(old_nonce, false, url, "Old nonce #{old_nonce.inspect} passed")
|
171
180
|
|
172
181
|
}
|
182
|
+
end
|
173
183
|
|
184
|
+
def test_nonce_cleanup
|
174
185
|
now = Time.now.to_i
|
175
186
|
old_nonce1 = Nonce::mk_nonce(now - 20000)
|
176
187
|
old_nonce2 = Nonce::mk_nonce(now - 10000)
|
@@ -187,7 +198,6 @@ module OpenID
|
|
187
198
|
ts, salt = Nonce::split_nonce(recent_nonce)
|
188
199
|
assert(@store.use_nonce(server_url, ts, salt), "recent_nonce")
|
189
200
|
|
190
|
-
|
191
201
|
Nonce.skew = 1000
|
192
202
|
cleaned = @store.cleanup_nonces
|
193
203
|
assert_equal(2, cleaned, "Cleaned #{cleaned} nonces")
|
@@ -204,7 +214,7 @@ module OpenID
|
|
204
214
|
|
205
215
|
end
|
206
216
|
end
|
207
|
-
|
217
|
+
|
208
218
|
class FileStoreTestCase < Test::Unit::TestCase
|
209
219
|
include StoreTestCase
|
210
220
|
|
@@ -220,50 +230,69 @@ module OpenID
|
|
220
230
|
|
221
231
|
class MemoryStoreTestCase < Test::Unit::TestCase
|
222
232
|
include StoreTestCase
|
223
|
-
|
233
|
+
|
224
234
|
def setup
|
225
235
|
@store = Memory.new
|
226
236
|
end
|
227
237
|
end
|
228
238
|
|
239
|
+
begin
|
240
|
+
::TESTING_MEMCACHE
|
241
|
+
rescue NameError
|
242
|
+
else
|
243
|
+
class MemcacheStoreTestCase < Test::Unit::TestCase
|
244
|
+
include StoreTestCase
|
245
|
+
def setup
|
246
|
+
store_uniq = OpenID::CryptUtil.random_string(6, "0123456789")
|
247
|
+
store_namespace = "openid-store-#{store_uniq}:"
|
248
|
+
@store = Memcache.new(::TESTING_MEMCACHE, store_namespace)
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_nonce_cleanup
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_assoc_cleanup
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
229
259
|
class AbstractStoreTestCase < Test::Unit::TestCase
|
230
260
|
def test_abstract_class
|
231
261
|
# the abstract made concrete
|
232
262
|
abc = Interface.new()
|
233
263
|
server_url = "http://server.com/"
|
234
264
|
association = OpenID::Association.new("foo", "bar", Time.now, Time.now + 10, "dummy")
|
235
|
-
|
236
|
-
assert_raise(NotImplementedError) {
|
265
|
+
|
266
|
+
assert_raise(NotImplementedError) {
|
237
267
|
abc.store_association(server_url, association)
|
238
268
|
}
|
239
269
|
|
240
|
-
assert_raise(NotImplementedError) {
|
270
|
+
assert_raise(NotImplementedError) {
|
241
271
|
abc.get_association(server_url)
|
242
272
|
}
|
243
273
|
|
244
|
-
assert_raise(NotImplementedError) {
|
274
|
+
assert_raise(NotImplementedError) {
|
245
275
|
abc.remove_association(server_url, association.handle)
|
246
276
|
}
|
247
277
|
|
248
|
-
assert_raise(NotImplementedError) {
|
278
|
+
assert_raise(NotImplementedError) {
|
249
279
|
abc.use_nonce(server_url, Time.now.to_i, "foo")
|
250
280
|
}
|
251
281
|
|
252
|
-
assert_raise(NotImplementedError) {
|
282
|
+
assert_raise(NotImplementedError) {
|
253
283
|
abc.cleanup_nonces()
|
254
284
|
}
|
255
285
|
|
256
|
-
assert_raise(NotImplementedError) {
|
286
|
+
assert_raise(NotImplementedError) {
|
257
287
|
abc.cleanup_associations()
|
258
288
|
}
|
259
289
|
|
260
|
-
assert_raise(NotImplementedError) {
|
290
|
+
assert_raise(NotImplementedError) {
|
261
291
|
abc.cleanup()
|
262
292
|
}
|
263
|
-
|
293
|
+
|
264
294
|
end
|
265
295
|
|
266
296
|
end
|
267
297
|
end
|
268
298
|
end
|
269
|
-
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-openid
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 2.1.
|
7
|
-
date: 2009-
|
6
|
+
version: 2.1.7
|
7
|
+
date: 2009-07-01 00:00:00 -07:00
|
8
8
|
summary: A library for consuming and serving OpenID identities.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -168,6 +168,7 @@ files:
|
|
168
168
|
- lib/openid/store/interface.rb
|
169
169
|
- lib/openid/store/nonce.rb
|
170
170
|
- lib/openid/store/memory.rb
|
171
|
+
- lib/openid/store/memcache.rb
|
171
172
|
- lib/openid/extensions/sreg.rb
|
172
173
|
- lib/openid/extensions/ax.rb
|
173
174
|
- lib/openid/extensions/pape.rb
|