ruby-openid 2.1.8 → 2.2.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.
Potentially problematic release.
This version of ruby-openid might be problematic. Click here for more details.
- data/CHANGELOG.md +13 -0
- data/INSTALL.md +47 -0
- data/README.md +82 -0
- data/{UPGRADE → UPGRADE.md} +54 -55
- data/examples/active_record_openid_store/README +4 -2
- data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +1 -1
- data/examples/active_record_openid_store/lib/openid_ar_store.rb +1 -1
- data/examples/rails_openid/app/controllers/server_controller.rb +0 -6
- data/lib/openid.rb +2 -2
- data/lib/openid/consumer/responses.rb +2 -0
- data/lib/openid/dh.rb +1 -1
- data/lib/openid/extensions/ax.rb +44 -22
- data/lib/openid/extensions/ui.rb +53 -0
- data/lib/openid/message.rb +1 -1
- data/lib/openid/store/filesystem.rb +8 -9
- data/lib/openid/store/memcache.rb +10 -2
- data/lib/openid/trustroot.rb +1 -0
- data/lib/openid/util.rb +6 -0
- data/lib/openid/version.rb +3 -0
- data/test/data/trustroot.txt +2 -2
- data/test/test_accept.rb +1 -1
- data/test/test_associationmanager.rb +1 -1
- data/test/test_ax.rb +89 -19
- data/test/test_checkid_request.rb +1 -1
- data/test/test_consumer.rb +5 -2
- data/test/test_cryptutil.rb +1 -1
- data/test/test_dh.rb +1 -1
- data/test/test_discover.rb +2 -4
- data/test/test_discovery_manager.rb +1 -3
- data/test/test_extension.rb +2 -2
- data/test/test_fetchers.rb +3 -7
- data/test/test_filters.rb +25 -31
- data/test/test_idres.rb +17 -17
- data/test/test_kvpost.rb +2 -2
- data/test/test_message.rb +1 -2
- data/test/test_oauth.rb +3 -2
- data/test/test_openid_yadis.rb +0 -1
- data/test/test_pape.rb +7 -6
- data/test/test_parsehtml.rb +2 -2
- data/test/test_server.rb +17 -22
- data/test/test_sreg.rb +8 -8
- data/test/test_stores.rb +1 -2
- data/test/test_trustroot.rb +14 -15
- data/test/test_ui.rb +93 -0
- data/test/test_urinorm.rb +2 -3
- data/test/test_util.rb +2 -3
- data/test/test_xrds.rb +13 -15
- data/test/test_xrires.rb +27 -14
- data/test/test_yadis_discovery.rb +1 -3
- metadata +260 -189
- data/CHANGELOG +0 -215
- data/INSTALL +0 -47
- data/README +0 -81
- data/admin/runtests.rb +0 -45
@@ -0,0 +1,53 @@
|
|
1
|
+
# An implementation of the OpenID User Interface Extension 1.0 - DRAFT 0.5
|
2
|
+
# see: http://svn.openid.net/repos/specifications/user_interface/1.0/trunk/openid-user-interface-extension-1_0.html
|
3
|
+
|
4
|
+
require 'openid/extension'
|
5
|
+
|
6
|
+
module OpenID
|
7
|
+
|
8
|
+
module UI
|
9
|
+
NS_URI = "http://specs.openid.net/extensions/ui/1.0"
|
10
|
+
|
11
|
+
class Request < Extension
|
12
|
+
attr_accessor :lang, :icon, :mode, :ns_alias, :ns_uri
|
13
|
+
def initialize(mode = nil, icon = nil, lang = nil)
|
14
|
+
@ns_alias = 'ui'
|
15
|
+
@ns_uri = NS_URI
|
16
|
+
@lang = lang
|
17
|
+
@icon = icon
|
18
|
+
@mode = mode
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_extension_args
|
22
|
+
ns_args = {}
|
23
|
+
ns_args['lang'] = @lang if @lang
|
24
|
+
ns_args['icon'] = @icon if @icon
|
25
|
+
ns_args['mode'] = @mode if @mode
|
26
|
+
return ns_args
|
27
|
+
end
|
28
|
+
|
29
|
+
# Instantiate a Request object from the arguments in a
|
30
|
+
# checkid_* OpenID message
|
31
|
+
# return nil if the extension was not requested.
|
32
|
+
def self.from_openid_request(oid_req)
|
33
|
+
oauth_req = new
|
34
|
+
args = oid_req.message.get_args(NS_URI)
|
35
|
+
if args == {}
|
36
|
+
return nil
|
37
|
+
end
|
38
|
+
oauth_req.parse_extension_args(args)
|
39
|
+
return oauth_req
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set UI extension parameters
|
43
|
+
def parse_extension_args(args)
|
44
|
+
@lang = args["lang"]
|
45
|
+
@icon = args["icon"]
|
46
|
+
@mode = args["mode"]
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/lib/openid/message.rb
CHANGED
@@ -288,7 +288,7 @@ module OpenID
|
|
288
288
|
markup += ">\n"
|
289
289
|
|
290
290
|
to_post_args.each { |k,v|
|
291
|
-
markup += "<input type='hidden' name='#{k}' value='#{v}' />\n"
|
291
|
+
markup += "<input type='hidden' name='#{k}' value='#{OpenID::Util.html_encode(v)}' />\n"
|
292
292
|
}
|
293
293
|
markup += "<input type='submit' value='#{submit_text}' />\n"
|
294
294
|
markup += "\n</form>"
|
@@ -13,10 +13,9 @@ module OpenID
|
|
13
13
|
|
14
14
|
# Create a Filesystem store instance, putting all data in +directory+.
|
15
15
|
def initialize(directory)
|
16
|
-
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@temp_dir = p_dir.join('temp')
|
16
|
+
@nonce_dir = File.join(directory, 'nonces')
|
17
|
+
@association_dir = File.join(directory, 'associations')
|
18
|
+
@temp_dir = File.join(directory, 'temp')
|
20
19
|
|
21
20
|
self.ensure_dir(@nonce_dir)
|
22
21
|
self.ensure_dir(@association_dir)
|
@@ -40,7 +39,7 @@ module OpenID
|
|
40
39
|
handle_hash = ''
|
41
40
|
end
|
42
41
|
filename = [proto,domain,url_hash,handle_hash].join('-')
|
43
|
-
|
42
|
+
File.join(@association_dir, filename)
|
44
43
|
end
|
45
44
|
|
46
45
|
# Store an association in the assoc directory
|
@@ -155,7 +154,7 @@ module OpenID
|
|
155
154
|
|
156
155
|
nonce_fn = '%08x-%s-%s-%s-%s'%[timestamp, proto, domain, url_hash, salt_hash]
|
157
156
|
|
158
|
-
filename =
|
157
|
+
filename = File.join(@nonce_dir, nonce_fn)
|
159
158
|
|
160
159
|
begin
|
161
160
|
fd = File.new(filename, File::CREAT | File::EXCL | File::WRONLY, 0200)
|
@@ -174,7 +173,7 @@ module OpenID
|
|
174
173
|
end
|
175
174
|
|
176
175
|
def cleanup_associations
|
177
|
-
association_filenames = Dir[
|
176
|
+
association_filenames = Dir[File.join(@association_dir, "*")]
|
178
177
|
count = 0
|
179
178
|
association_filenames.each do |af|
|
180
179
|
begin
|
@@ -204,7 +203,7 @@ module OpenID
|
|
204
203
|
end
|
205
204
|
|
206
205
|
def cleanup_nonces
|
207
|
-
nonces = Dir[
|
206
|
+
nonces = Dir[File.join(@nonce_dir, "*")]
|
208
207
|
now = Time.now.to_i
|
209
208
|
|
210
209
|
count = 0
|
@@ -236,7 +235,7 @@ module OpenID
|
|
236
235
|
if @@FILENAME_ALLOWED.index(c)
|
237
236
|
filename_chunks << c
|
238
237
|
else
|
239
|
-
filename_chunks << sprintf("_%02X", c
|
238
|
+
filename_chunks << sprintf("_%02X", c.bytes.first)
|
240
239
|
end
|
241
240
|
end
|
242
241
|
filename_chunks.join("")
|
@@ -63,7 +63,11 @@ module OpenID
|
|
63
63
|
ts = timestamp.to_s # base 10 seconds since epoch
|
64
64
|
nonce_key = key_prefix + 'N' + server_url + '|' + ts + '|' + salt
|
65
65
|
result = @cache_client.add(nonce_key, '', expiry(Nonce.skew + 5))
|
66
|
-
|
66
|
+
if result.is_a? String
|
67
|
+
return !!(result =~ /^STORED/)
|
68
|
+
else
|
69
|
+
return result == true
|
70
|
+
end
|
67
71
|
end
|
68
72
|
|
69
73
|
def assoc_key(server_url, assoc_handle=nil)
|
@@ -87,7 +91,11 @@ module OpenID
|
|
87
91
|
|
88
92
|
def delete(key)
|
89
93
|
result = @cache_client.delete(key)
|
90
|
-
|
94
|
+
if result.is_a? String
|
95
|
+
return !!(result =~ /^DELETED/)
|
96
|
+
else
|
97
|
+
return result == true
|
98
|
+
end
|
91
99
|
end
|
92
100
|
|
93
101
|
def serialize(assoc)
|
data/lib/openid/trustroot.rb
CHANGED
data/lib/openid/util.rb
CHANGED
@@ -105,6 +105,12 @@ for (var i = 0; i < elements.length; i++) {
|
|
105
105
|
</html>
|
106
106
|
"
|
107
107
|
end
|
108
|
+
|
109
|
+
ESCAPE_TABLE = { '&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => ''' }
|
110
|
+
# Modified from ERb's html_encode
|
111
|
+
def Util.html_encode(s)
|
112
|
+
s.to_s.gsub(/[&<>"']/) {|s| ESCAPE_TABLE[s] }
|
113
|
+
end
|
108
114
|
end
|
109
115
|
|
110
116
|
end
|
data/test/data/trustroot.txt
CHANGED
data/test/test_accept.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "test/unit"
|
1
2
|
require "openid/consumer/associationmanager"
|
2
3
|
require "openid/association"
|
3
4
|
require "openid/dh"
|
@@ -5,7 +6,6 @@ require "openid/util"
|
|
5
6
|
require "openid/cryptutil"
|
6
7
|
require "openid/message"
|
7
8
|
require "openid/store/memory"
|
8
|
-
require "test/unit"
|
9
9
|
require "util"
|
10
10
|
require "time"
|
11
11
|
|
data/test/test_ax.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'test/unit'
|
1
2
|
require 'openid/extensions/ax'
|
2
3
|
require 'openid/message'
|
3
4
|
require 'openid/consumer/responses'
|
@@ -119,7 +120,7 @@ module OpenID
|
|
119
120
|
def test_invalid_count_value
|
120
121
|
msg = FetchRequest.new
|
121
122
|
assert_raises(Error) {
|
122
|
-
msg.parse_extension_args({'type.foo'=>'urn:foo',
|
123
|
+
msg.parse_extension_args({'type.foo'=>'urn:foo',
|
123
124
|
'count.foo' => 'bogus'})
|
124
125
|
}
|
125
126
|
end
|
@@ -216,7 +217,7 @@ module OpenID
|
|
216
217
|
'value.foo'=>'something',
|
217
218
|
},
|
218
219
|
{'urn:foo'=>['something']}
|
219
|
-
)
|
220
|
+
)
|
220
221
|
end
|
221
222
|
end
|
222
223
|
|
@@ -371,12 +372,12 @@ module OpenID
|
|
371
372
|
ax_req = FetchRequest.from_openid_request(openid_req)
|
372
373
|
assert(ax_req.nil?)
|
373
374
|
end
|
374
|
-
|
375
|
+
|
375
376
|
def test_from_openid_request_wrong_ax_mode
|
376
377
|
uri = 'http://under.the.sea/'
|
377
378
|
name = 'ext0'
|
378
379
|
value = 'snarfblat'
|
379
|
-
|
380
|
+
|
380
381
|
message = OpenID::Message.from_openid_args({
|
381
382
|
'mode' => 'id_res',
|
382
383
|
'ns' => OPENID2_NS,
|
@@ -392,7 +393,7 @@ module OpenID
|
|
392
393
|
ax_req = FetchRequest.from_openid_request(openid_req)
|
393
394
|
assert(ax_req.nil?)
|
394
395
|
end
|
395
|
-
|
396
|
+
|
396
397
|
def test_openid_update_url_verification_error
|
397
398
|
openid_req_msg = Message.from_openid_args({
|
398
399
|
'mode' => 'checkid_setup',
|
@@ -404,7 +405,7 @@ module OpenID
|
|
404
405
|
})
|
405
406
|
openid_req = Server::OpenIDRequest.new
|
406
407
|
openid_req.message = openid_req_msg
|
407
|
-
assert_raises(Error) {
|
408
|
+
assert_raises(Error) {
|
408
409
|
FetchRequest.from_openid_request(openid_req)
|
409
410
|
}
|
410
411
|
end
|
@@ -419,7 +420,7 @@ module OpenID
|
|
419
420
|
})
|
420
421
|
openid_req = Server::OpenIDRequest.new
|
421
422
|
openid_req.message = openid_req_msg
|
422
|
-
assert_raises(Error) {
|
423
|
+
assert_raises(Error) {
|
423
424
|
FetchRequest.from_openid_request(openid_req)
|
424
425
|
}
|
425
426
|
end
|
@@ -486,6 +487,7 @@ module OpenID
|
|
486
487
|
def setup
|
487
488
|
@msg = FetchResponse.new
|
488
489
|
@value_a = 'commodity'
|
490
|
+
@value_a1 = 'value2'
|
489
491
|
@type_a = 'http://blood.transfusion/'
|
490
492
|
@name_a = 'george'
|
491
493
|
@request_update_url = 'http://some.url.that.is.awesome/'
|
@@ -538,12 +540,13 @@ module OpenID
|
|
538
540
|
assert_equal(eargs, @msg.get_extension_args(req))
|
539
541
|
end
|
540
542
|
|
541
|
-
def
|
543
|
+
def test_get_extension_args_single_value_response
|
544
|
+
# Single values do NOT have a count, and
|
545
|
+
# do not use the array extension
|
542
546
|
eargs = {
|
543
547
|
'mode' => 'fetch_response',
|
544
548
|
'type.' + @name_a => @type_a,
|
545
|
-
'value.' + @name_a
|
546
|
-
'count.' + @name_a => '1'
|
549
|
+
'value.' + @name_a => @value_a
|
547
550
|
}
|
548
551
|
req = FetchRequest.new
|
549
552
|
req.add(AttrInfo.new(@type_a, @name_a))
|
@@ -551,6 +554,25 @@ module OpenID
|
|
551
554
|
assert_equal(eargs, @msg.get_extension_args(req))
|
552
555
|
end
|
553
556
|
|
557
|
+
def test_get_extension_args_array_value_response
|
558
|
+
# Multiple array values add the count, and array index
|
559
|
+
# to each value
|
560
|
+
eargs = {
|
561
|
+
'mode' => 'fetch_response',
|
562
|
+
'type.' + @name_a => @type_a,
|
563
|
+
'value.' + @name_a + ".1" => @value_a,
|
564
|
+
'value.' + @name_a + ".2" => @value_a1,
|
565
|
+
'count.' + @name_a => '2'
|
566
|
+
}
|
567
|
+
req = FetchRequest.new
|
568
|
+
# Specify that this URI should have a count of 2
|
569
|
+
req.add(AttrInfo.new(@type_a, @name_a, true, 2))
|
570
|
+
# Push both values onto the array
|
571
|
+
@msg.add_value(@type_a, @value_a)
|
572
|
+
@msg.add_value(@type_a, @value_a1)
|
573
|
+
assert_equal(eargs, @msg.get_extension_args(req))
|
574
|
+
end
|
575
|
+
|
554
576
|
def test_get_extension_args_some_not_request
|
555
577
|
req = FetchRequest.new
|
556
578
|
@msg.add_value(@type_a, @value_a)
|
@@ -572,7 +594,7 @@ module OpenID
|
|
572
594
|
assert_raises(Error) { @msg.get_single(@type_a) }
|
573
595
|
end
|
574
596
|
|
575
|
-
def
|
597
|
+
def test_from_unsigned_success_response
|
576
598
|
uri = 'http://under.the.sea/'
|
577
599
|
name = 'ext0'
|
578
600
|
value = 'snarfblat'
|
@@ -585,7 +607,7 @@ module OpenID
|
|
585
607
|
'ax.mode' => 'fetch_response',
|
586
608
|
'ax.type.' + name => uri,
|
587
609
|
'ax.count.' + name => '1',
|
588
|
-
'ax.value.' + name + '.1' => value
|
610
|
+
'ax.value.' + name + '.1' => value
|
589
611
|
})
|
590
612
|
|
591
613
|
e = OpenID::OpenIDServiceEndpoint.new()
|
@@ -597,7 +619,55 @@ module OpenID
|
|
597
619
|
assert_equal(values, [value])
|
598
620
|
end
|
599
621
|
|
600
|
-
def
|
622
|
+
def test_from_signed_success_response
|
623
|
+
uri = 'http://under.the.sea/'
|
624
|
+
name = 'ext0'
|
625
|
+
value = 'snarfblat'
|
626
|
+
oid_fields = {
|
627
|
+
'mode' => 'id_res',
|
628
|
+
'ns' => OPENID2_NS,
|
629
|
+
'ns.ax' => AXMessage::NS_URI,
|
630
|
+
'ax.update_url' => 'http://example.com/realm/update_path',
|
631
|
+
'ax.mode' => 'fetch_response',
|
632
|
+
'ax.type.' + name => uri,
|
633
|
+
'ax.count.' + name => '1',
|
634
|
+
'ax.value.' + name + '.1' => value
|
635
|
+
}
|
636
|
+
signed_fields = oid_fields.keys.map{|f| "openid.#{f}"}
|
637
|
+
|
638
|
+
m = OpenID::Message.from_openid_args(oid_fields)
|
639
|
+
e = OpenID::OpenIDServiceEndpoint.new()
|
640
|
+
resp = OpenID::Consumer::SuccessResponse.new(e, m, signed_fields)
|
641
|
+
|
642
|
+
ax_resp = FetchResponse.from_success_response(resp, true)
|
643
|
+
|
644
|
+
values = ax_resp[uri]
|
645
|
+
assert_equal(values, [value])
|
646
|
+
end
|
647
|
+
|
648
|
+
def test_from_signed_success_response_with_unsigned_attributes
|
649
|
+
uri = 'http://under.the.sea/'
|
650
|
+
name = 'ext0'
|
651
|
+
value = 'snarfblat'
|
652
|
+
|
653
|
+
m = OpenID::Message.from_openid_args({
|
654
|
+
'mode' => 'id_res',
|
655
|
+
'ns' => OPENID2_NS,
|
656
|
+
'ns.ax' => AXMessage::NS_URI,
|
657
|
+
'ax.update_url' => 'http://example.com/realm/update_path',
|
658
|
+
'ax.mode' => 'fetch_response',
|
659
|
+
'ax.type.' + name => uri,
|
660
|
+
'ax.count.' + name => '1',
|
661
|
+
'ax.value.' + name + '.1' => value
|
662
|
+
})
|
663
|
+
|
664
|
+
e = OpenID::OpenIDServiceEndpoint.new()
|
665
|
+
resp = OpenID::Consumer::SuccessResponse.new(e, m, [])
|
666
|
+
|
667
|
+
assert_nil FetchResponse.from_success_response(resp, true)
|
668
|
+
end
|
669
|
+
|
670
|
+
def test_from_empty_success_response
|
601
671
|
e = OpenID::OpenIDServiceEndpoint.new()
|
602
672
|
m = OpenID::Message.from_openid_args({'mode' => 'id_res'})
|
603
673
|
resp = OpenID::Consumer::SuccessResponse.new(e, m, [])
|
@@ -623,12 +693,12 @@ module OpenID
|
|
623
693
|
}
|
624
694
|
assert_equal(eargs, @msg.get_extension_args)
|
625
695
|
end
|
626
|
-
|
696
|
+
|
627
697
|
def test_from_openid_request_wrong_ax_mode
|
628
698
|
uri = 'http://under.the.sea/'
|
629
699
|
name = 'ext0'
|
630
700
|
value = 'snarfblat'
|
631
|
-
|
701
|
+
|
632
702
|
message = OpenID::Message.from_openid_args({
|
633
703
|
'mode' => 'id_res',
|
634
704
|
'ns' => OPENID2_NS,
|
@@ -644,7 +714,7 @@ module OpenID
|
|
644
714
|
ax_req = StoreRequest.from_openid_request(openid_req)
|
645
715
|
assert(ax_req.nil?)
|
646
716
|
end
|
647
|
-
|
717
|
+
|
648
718
|
def test_get_extension_args_nonempty
|
649
719
|
@msg.set_values(@type_a, ['foo','bar'])
|
650
720
|
aliases = NamespaceMap.new
|
@@ -665,7 +735,7 @@ module OpenID
|
|
665
735
|
msg = StoreResponse.new
|
666
736
|
assert(msg.succeeded?)
|
667
737
|
assert(!msg.error_message)
|
668
|
-
assert_equal({'mode' => 'store_response_success'},
|
738
|
+
assert_equal({'mode' => 'store_response_success'},
|
669
739
|
msg.get_extension_args)
|
670
740
|
end
|
671
741
|
|
@@ -673,7 +743,7 @@ module OpenID
|
|
673
743
|
msg = StoreResponse.new(false)
|
674
744
|
assert(! msg.succeeded? )
|
675
745
|
assert(! msg.error_message )
|
676
|
-
assert_equal({'mode' => 'store_response_failure'},
|
746
|
+
assert_equal({'mode' => 'store_response_failure'},
|
677
747
|
msg.get_extension_args)
|
678
748
|
end
|
679
749
|
|
@@ -682,7 +752,7 @@ module OpenID
|
|
682
752
|
msg = StoreResponse.new(false, reason)
|
683
753
|
assert(! msg.succeeded? )
|
684
754
|
assert_equal(reason, msg.error_message)
|
685
|
-
assert_equal({'mode' => 'store_response_failure', 'error' => reason},
|
755
|
+
assert_equal({'mode' => 'store_response_failure', 'error' => reason},
|
686
756
|
msg.get_extension_args)
|
687
757
|
end
|
688
758
|
end
|