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.

Files changed (54) hide show
  1. data/CHANGELOG.md +13 -0
  2. data/INSTALL.md +47 -0
  3. data/README.md +82 -0
  4. data/{UPGRADE → UPGRADE.md} +54 -55
  5. data/examples/active_record_openid_store/README +4 -2
  6. data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +1 -1
  7. data/examples/active_record_openid_store/lib/openid_ar_store.rb +1 -1
  8. data/examples/rails_openid/app/controllers/server_controller.rb +0 -6
  9. data/lib/openid.rb +2 -2
  10. data/lib/openid/consumer/responses.rb +2 -0
  11. data/lib/openid/dh.rb +1 -1
  12. data/lib/openid/extensions/ax.rb +44 -22
  13. data/lib/openid/extensions/ui.rb +53 -0
  14. data/lib/openid/message.rb +1 -1
  15. data/lib/openid/store/filesystem.rb +8 -9
  16. data/lib/openid/store/memcache.rb +10 -2
  17. data/lib/openid/trustroot.rb +1 -0
  18. data/lib/openid/util.rb +6 -0
  19. data/lib/openid/version.rb +3 -0
  20. data/test/data/trustroot.txt +2 -2
  21. data/test/test_accept.rb +1 -1
  22. data/test/test_associationmanager.rb +1 -1
  23. data/test/test_ax.rb +89 -19
  24. data/test/test_checkid_request.rb +1 -1
  25. data/test/test_consumer.rb +5 -2
  26. data/test/test_cryptutil.rb +1 -1
  27. data/test/test_dh.rb +1 -1
  28. data/test/test_discover.rb +2 -4
  29. data/test/test_discovery_manager.rb +1 -3
  30. data/test/test_extension.rb +2 -2
  31. data/test/test_fetchers.rb +3 -7
  32. data/test/test_filters.rb +25 -31
  33. data/test/test_idres.rb +17 -17
  34. data/test/test_kvpost.rb +2 -2
  35. data/test/test_message.rb +1 -2
  36. data/test/test_oauth.rb +3 -2
  37. data/test/test_openid_yadis.rb +0 -1
  38. data/test/test_pape.rb +7 -6
  39. data/test/test_parsehtml.rb +2 -2
  40. data/test/test_server.rb +17 -22
  41. data/test/test_sreg.rb +8 -8
  42. data/test/test_stores.rb +1 -2
  43. data/test/test_trustroot.rb +14 -15
  44. data/test/test_ui.rb +93 -0
  45. data/test/test_urinorm.rb +2 -3
  46. data/test/test_util.rb +2 -3
  47. data/test/test_xrds.rb +13 -15
  48. data/test/test_xrires.rb +27 -14
  49. data/test/test_yadis_discovery.rb +1 -3
  50. metadata +260 -189
  51. data/CHANGELOG +0 -215
  52. data/INSTALL +0 -47
  53. data/README +0 -81
  54. 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
@@ -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
- p_dir = Pathname.new(directory)
17
- @nonce_dir = p_dir.join('nonces')
18
- @association_dir = p_dir.join('associations')
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
- @association_dir.join(filename)
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 = @nonce_dir.join(nonce_fn)
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[@association_dir.join("*").to_s]
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[@nonce_dir.join("*").to_s]
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[0])
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
- return !!(result =~ /^STORED/)
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
- return !!(result =~ /^DELETED/)
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)
@@ -210,6 +210,7 @@ module OpenID
210
210
  return nil if parts.nil?
211
211
 
212
212
  proto, host, port, path = parts
213
+ return nil if host[0] == '.'
213
214
 
214
215
  # check for URI fragment
215
216
  if path and !path.index('#').nil?
@@ -105,6 +105,12 @@ for (var i = 0; i < elements.length; i++) {
105
105
  </html>
106
106
  "
107
107
  end
108
+
109
+ ESCAPE_TABLE = { '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', '"' => '&quot;', "'" => '&#039;' }
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
@@ -0,0 +1,3 @@
1
+ module OpenID
2
+ VERSION = "2.2.0"
3
+ end
@@ -25,8 +25,8 @@ http://foo.com\/
25
25
  http://π.pi.com/
26
26
  http://lambda.com/Λ
27
27
 
28
-
29
-
28
+
29
+
30
30
  5
31
31
 
32
32
  ----------------------------------------
@@ -1,5 +1,5 @@
1
-
2
1
  require 'test/unit'
2
+ require 'testutil'
3
3
  require 'openid/yadis/accept'
4
4
  require 'openid/extras'
5
5
  require 'openid/util'
@@ -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
 
@@ -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 test_get_extension_args_some_request
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 + '.1' => @value_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 test_from_success_response
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 test_from_success_response_empty
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
@@ -1,6 +1,6 @@
1
+ require "test/unit"
1
2
  require "openid/consumer/checkid_request"
2
3
  require "openid/message"
3
- require "test/unit"
4
4
  require "testutil"
5
5
  require "util"
6
6