ruby-openid 2.1.8 → 2.2.0
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.
- 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
|