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.

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