ruby-openid 2.0.4 → 2.1.2

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 (58) hide show
  1. data/CHANGELOG +65 -28
  2. data/LICENSE +4 -1
  3. data/README +19 -12
  4. data/UPGRADE +5 -0
  5. data/examples/README +8 -22
  6. data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +6 -6
  7. data/examples/active_record_openid_store/lib/association.rb +2 -1
  8. data/examples/active_record_openid_store/lib/openid_ar_store.rb +3 -3
  9. data/examples/rails_openid/app/controllers/consumer_controller.rb +11 -5
  10. data/lib/openid.rb +4 -0
  11. data/lib/openid/association.rb +7 -7
  12. data/lib/openid/consumer/checkid_request.rb +11 -0
  13. data/lib/openid/consumer/discovery.rb +12 -3
  14. data/lib/openid/consumer/idres.rb +35 -43
  15. data/lib/openid/extension.rb +9 -1
  16. data/lib/openid/extensions/pape.rb +22 -25
  17. data/lib/openid/extensions/sreg.rb +1 -0
  18. data/lib/openid/fetchers.rb +25 -5
  19. data/lib/openid/kvform.rb +8 -5
  20. data/lib/openid/kvpost.rb +6 -5
  21. data/lib/openid/message.rb +53 -34
  22. data/lib/openid/server.rb +87 -52
  23. data/lib/openid/trustroot.rb +25 -17
  24. data/lib/openid/util.rb +19 -4
  25. data/lib/openid/yadis/discovery.rb +3 -3
  26. data/lib/openid/yadis/htmltokenizer.rb +8 -5
  27. data/lib/openid/yadis/parsehtml.rb +22 -14
  28. data/lib/openid/yadis/xrds.rb +6 -9
  29. data/test/data/linkparse.txt +1 -1
  30. data/test/data/test1-parsehtml.txt +24 -0
  31. data/test/data/trustroot.txt +8 -2
  32. data/test/test_association.rb +7 -7
  33. data/test/test_associationmanager.rb +1 -1
  34. data/test/test_extension.rb +46 -0
  35. data/test/test_idres.rb +81 -21
  36. data/test/test_kvform.rb +5 -5
  37. data/test/test_message.rb +61 -3
  38. data/test/test_pape.rb +36 -22
  39. data/test/test_server.rb +190 -12
  40. data/test/test_sreg.rb +0 -1
  41. data/test/test_trustroot.rb +1 -0
  42. data/test/test_yadis_discovery.rb +13 -0
  43. metadata +3 -19
  44. data/examples/rails_openid/app/views/consumer/start.rhtml +0 -8
  45. data/examples/rails_openid_login_generator/USAGE +0 -23
  46. data/examples/rails_openid_login_generator/gemspec +0 -13
  47. data/examples/rails_openid_login_generator/openid_login_generator.rb +0 -36
  48. data/examples/rails_openid_login_generator/templates/README +0 -116
  49. data/examples/rails_openid_login_generator/templates/controller.rb +0 -113
  50. data/examples/rails_openid_login_generator/templates/controller_test.rb +0 -0
  51. data/examples/rails_openid_login_generator/templates/helper.rb +0 -2
  52. data/examples/rails_openid_login_generator/templates/openid_login_system.rb +0 -87
  53. data/examples/rails_openid_login_generator/templates/user.rb +0 -14
  54. data/examples/rails_openid_login_generator/templates/user_test.rb +0 -0
  55. data/examples/rails_openid_login_generator/templates/users.yml +0 -0
  56. data/examples/rails_openid_login_generator/templates/view_login.rhtml +0 -15
  57. data/examples/rails_openid_login_generator/templates/view_logout.rhtml +0 -10
  58. data/examples/rails_openid_login_generator/templates/view_welcome.rhtml +0 -9
data/CHANGELOG CHANGED
@@ -1,41 +1,78 @@
1
- Tue Feb 12 18:02:31 PST 2008 Kevin Turner <kevin@janrain.com>
2
- tagged 2.0.4
1
+ Fri Jun 27 15:39:14 PDT 2008 Kevin Turner <kevin@janrain.com>
2
+ tagged 2.1.2
3
3
 
4
- Tue Feb 12 18:01:44 PST 2008 Kevin Turner <kevin@janrain.com>
5
- * set version to 2.0.4
4
+ Fri Jun 27 15:38:05 PDT 2008 Kevin Turner <kevin@janrain.com>
5
+ * update version to 2.1.2
6
6
 
7
- Tue Feb 12 17:49:53 PST 2008 Kevin Turner <kevin@janrain.com>
8
- * HTMLTokenizer: raise OpenIDError instead of RuntimeError
7
+ Fri Jun 27 15:01:35 PDT 2008 Kevin Turner <kevin@janrain.com>
8
+ * util: remove call to srand
9
+
10
+ From the Ruby FAQ:
11
+
12
+ 9.2 How do random number seeds work?
13
+
14
+ It depends. In Ruby versions prior to 1.5.2, the random number generator had
15
+ (by default) a constant seed, and so would produce the same series of numbers
16
+ each time a program was run. If you needed less deterministic behaviors, you
17
+ called srand to set up a less predictable seed.
18
+
19
+ Newer Rubys (Rubies?) have a different behavior. If rand is called without a
20
+ prior call to srand, Ruby will generate its own random(ish) seed. Successive
21
+ runs of a program that does not use srand will generate different sequences of
22
+ random numbers. To get the old, predictable, behavior (perhaps for testing),
23
+ call srand with a constant seed.
24
+
25
+ Fri Jun 27 13:34:43 PDT 2008 Kevin Turner <kevin@janrain.com>
26
+ * LICENSE: htmltokenizer is (c) 2004 Ben Giddings
27
+
28
+ Fri Jun 27 13:32:09 PDT 2008 Kevin Turner <kevin@janrain.com>
29
+ * Yadis.html_yadis_location: catch HTMLTokenizerError
9
30
 
10
- Thu Jan 31 11:34:11 PST 2008 Kevin Turner <kevin@janrain.com>
11
- * Consumer.IdResHandler.verify_return_to_args: include more details in exception messages.
31
+ Fri Jun 27 13:24:13 PDT 2008 Kevin Turner <kevin@janrain.com>
32
+ * htmltokenizer: define HTMLTokenizerError to raise
12
33
 
13
- Mon Jan 21 15:50:54 PST 2008 Kevin Turner <kevin@janrain.com>
14
- * StandardFetcher.fetch: catch more exceptions to wrap in to FetchingErrors.
34
+ Fri Jun 27 13:18:38 PDT 2008 Kevin Turner <kevin@janrain.com>
35
+ * htmltokenizer: Don't raise OpenIDError from htmltokenizer (it's not in the OpenID module namespace) #255
15
36
 
16
- Mon Jan 21 14:23:10 PST 2008 Kevin Turner <kevin@janrain.com>
17
- * OpenID::normalize_url: urinorm raises URI::Error, not ArgumentError.
37
+ Wed Jun 25 17:31:26 PDT 2008 Kevin Turner <kevin@janrain.com>
38
+ * OpenID::Server::CheckIDRequest.answer: document return type
18
39
 
19
- Tue Jan 15 11:48:49 PST 2008 rubys@intertwingly.net
20
- * The following set of changes gets ruby-openid to work with Ruby 1.9,
21
- revision 15006 and REXML revision 1301. The codebase with this
22
- patch continues to work on Ruby 1.8.6.
40
+ Wed Jun 25 17:06:35 PDT 2008 Kevin Turner <kevin@janrain.com>
41
+ * TrustRoot.check_sanity: don't fail if the trust root is not parseable
23
42
 
24
- Mon Jan 14 18:06:29 PST 2008 Kevin Turner <kevin@janrain.com>
25
- * Consumer.complete_id_res: catch all OpenIDError instead of just DiscoveryFailure and ProtocolError. Fixes #104.
43
+ Wed Jun 25 16:31:30 PDT 2008 Kevin Turner <kevin@janrain.com>
44
+ * Message.from_http_response: accept 206 code
45
+
46
+ Wed Jun 25 14:14:05 PDT 2008 Kevin Turner <kevin@janrain.com>
47
+ * move OpenID::VERSION definition in openid.rb, for #256
48
+
49
+ Wed Jun 25 13:55:18 PDT 2008 Kevin Turner <kevin@janrain.com>
50
+ * Add admin/gettlds.py to ease updating of TLD list in trust root validation
51
+
52
+ Wed Jun 25 13:50:22 PDT 2008 Kevin Turner <kevin@janrain.com>
53
+ * TrustRoot.TOP_LEVEL_DOMAINS: updated
54
+
55
+ Fri Jun 13 14:18:04 PDT 2008 Kevin Turner <kevin@janrain.com>
56
+ * xrds.rb: fix stray colon
57
+
58
+ Fri Jun 13 13:41:58 PDT 2008 Kevin Turner <kevin@janrain.com>
59
+ * Yadis::get_canonical_id: case-insensitive comparison
60
+
61
+ Porting a patch from =wil:
26
62
 
27
- This seems to be the desired behavior.
63
+ 1. There should only be a single CanonicalID in each XRD (in the latest XRI
64
+ resolution spec), so I made it use the first CID found instead of the last.
28
65
 
29
- IdResHandler.check_auth: don't bother casting an OpenIDError to another OpenIDError.
66
+ 2. Use case-insensitive comparison when comparing CanonicalIDs.
30
67
 
31
- Mon Jan 14 17:59:38 PST 2008 Kevin Turner <kevin@janrain.com>
32
- * OpenID::ServerError: add server_url to attributes.
68
+ Wed Jun 11 15:24:12 PDT 2008 Kevin Turner <kevin@janrain.com>
69
+ * Accept response code 206 from fetcher results. Fixes #260
33
70
 
34
- Mon Jan 14 17:21:10 PST 2008 Kevin Turner <kevin@janrain.com>
35
- * ProtocolError, ServerError: subclass OpenIDError
71
+ Wed Jun 11 11:27:25 PDT 2008 cygnus@janrain.com
72
+ * admin/fixperms: Fix stale entries
36
73
 
37
- Mon Jan 14 17:20:01 PST 2008 Kevin Turner <kevin@janrain.com>
38
- * UPGRADE: fix typo in example path
74
+ Wed Jun 11 11:08:11 PDT 2008 cygnus@janrain.com
75
+ * Add test cases for trust roots with non-ASCII characters in path or hostname
39
76
 
40
- Fri Jan 11 11:31:29 PST 2008 cygnus@janrain.com
41
- tagged 2.0.3
77
+ Fri Jun 6 15:50:12 PDT 2008 cygnus@janrain.com
78
+ tagged 2.1.1
data/LICENSE CHANGED
@@ -1,7 +1,10 @@
1
1
  The code in lib/hmac/ is Copyright 2001 by Daiki Ueno, and distributed under
2
2
  the terms of the Ruby license. See http://www.ruby-lang.org/en/LICENSE.txt
3
3
 
4
- The remainder of this package is Copyright 2006-2007 by JanRain, Inc. and
4
+ lib/openid/yadis/htmltokenizer.rb is Copyright 2004 by Ben Giddings and
5
+ distributed under the terms of the Ruby license.
6
+
7
+ The remainder of this package is Copyright 2006-2008 by JanRain, Inc. and
5
8
  distributed under the terms of license below:
6
9
 
7
10
  Apache License
data/README CHANGED
@@ -31,20 +31,21 @@ Check the installation:
31
31
  The library is known to work with Ruby 1.8.4 on Unix, Max OSX and
32
32
  Win32. Examples have been tested with Rails 1.1 and 1.2, and 2.0.
33
33
 
34
- ==Getting Started with OpenID::Consumer
35
- OpenID::Consumer is the place to start if you'd like to support OpenID
36
- authentication on your website. The examples directory contains
37
- several working examples to help you get started, and the
38
- OpenID::Consumer class is well-documented.
34
+ ==Getting Started
35
+ The best way to start is to look at the rails_openid example.
36
+ You can run it with:
37
+ cd examples/rails_openid
38
+ script/server
39
39
 
40
- Also, check out the OpenIDLoginGenerator! Read examples/README for
41
- more info.
40
+ If you are writing an OpenID Relying Party, a good place to start is:
41
+ examples/rails_openid/app/controllers/consumer_controller.rb
42
42
 
43
- ==Serving OpenID with OpenID::Server
44
- The examples directory contains a fully-functional OpenID server that
45
- uses the Ruby on Rails framework. Start by reading about the
46
- OpenID::Server interface documentation and looking at the example.
43
+ And if you are writing an OpenID provider:
44
+ examples/rails_openid/app/controllers/server_controller.rb
47
45
 
46
+ The library code is quite well documented, so don't be squeamish, and
47
+ look at the library itself if there's anything you don't understand in
48
+ the examples.
48
49
 
49
50
  ==Homepage
50
51
  http://openidenabled.com/ruby-openid/
@@ -64,8 +65,14 @@ Please join this list to discuss, ask implementation questions, report
64
65
  bugs, etc. Also check out the openid channel on the freenode IRC
65
66
  network.
66
67
 
68
+ If you have a bugfix or feature you'd like to contribute, don't
69
+ hesitate to send it to us. For more detailed information on how to
70
+ contribute, see
71
+
72
+ http://openidenabled.com/contribute/
73
+
67
74
  ==Author
68
- Copyright 2006-2007, JanRain, Inc.
75
+ Copyright 2006-2008, JanRain, Inc.
69
76
 
70
77
  Contact openid@janrain.com or visit the OpenID channel on pibb.com:
71
78
 
data/UPGRADE CHANGED
@@ -57,6 +57,11 @@ additional arguments to the return_to url, use
57
57
  Generating the redirect is the same as before, but add any extensions
58
58
  first.
59
59
 
60
+ If you need to set up an SSL certificate authority list for the fetcher,
61
+ use the 'ca_file' attr_accessor on the OpenID::StandardFetcher. This has
62
+ changed from 'ca_path' in the 1.x.x series library. That is, set
63
+ OpenID.fetcher.ca_file = '/path/to/ca.list'
64
+ before calling consumer.begin.
60
65
 
61
66
  === Requesting Simple Registration Data
62
67
 
data/examples/README CHANGED
@@ -15,28 +15,14 @@ Rails installed, and then:
15
15
 
16
16
  Open a web browser to http://localhost:3000/ and follow the instructions.
17
17
 
18
-
19
- ==Rails OpenidLoginGenerator
20
-
21
- A port of the standard LoginGenerator OpenID authentication instead of
22
- passwords. Use this generator as a *starting point* for your OpenID
23
- enabled rails app.
24
-
25
- You can read about LoginGenerator at
26
- http://wiki.rubyonrails.com/rails/pages/LoginGenerator
27
-
28
- ===Running the generator
29
-
30
- * Copy the contents of rails_openid_login_generator into
31
- ~/.rails/generators/openid_login
32
- (or symlink: ln -s examples/rails_openid_login_generator
33
- ~/.rails/generators/openid_login)
34
- * run script/generate openid_login openid
35
-
36
- You will now have an openid_controller.rb in app/controllers. You'll
37
- need to create your 'users' database table before running the
38
- application. For schemas and more details about this generator, read
39
- README_LOGIN in you rails root directory.
18
+ The relevant code to work from when writing your Rails OpenID Relying
19
+ Party is:
20
+ rails_openid/app/controllers/consumer_controller.rb
21
+ If you are working on an OpenID provider, check out
22
+ rails_openid/app/controllers/server_controller.rb
23
+
24
+ Since the library and examples are Apache-licensed, don't be shy about
25
+ copy-and-paste.
40
26
 
41
27
  ==Rails ActiveRecord OpenIDStore plugin
42
28
 
@@ -2,12 +2,12 @@
2
2
  class AddOpenIdStoreToDb < ActiveRecord::Migration
3
3
  def self.up
4
4
  create_table "open_id_associations", :force => true do |t|
5
- t.column "server_url", :binary
6
- t.column "handle", :string
7
- t.column "secret", :binary
8
- t.column "issued", :integer
9
- t.column "lifetime", :integer
10
- t.column "assoc_type", :string
5
+ t.column "server_url", :binary, :null => false
6
+ t.column "handle", :string, :null => false
7
+ t.column "secret", :binary, :null => false
8
+ t.column "issued", :integer, :null => false
9
+ t.column "lifetime", :integer, :null => false
10
+ t.column "assoc_type", :string, :null => false
11
11
  end
12
12
 
13
13
  create_table "open_id_nonces", :force => true do |t|
@@ -1,9 +1,10 @@
1
1
  require 'openid/association'
2
+ require 'time'
2
3
 
3
4
  class Association < ActiveRecord::Base
4
5
  set_table_name 'open_id_associations'
5
6
  def from_record
6
- OpenID::Association.new(handle, secret, issued, lifetime, assoc_type)
7
+ OpenID::Association.new(handle, secret, Time.at(issued), lifetime, assoc_type)
7
8
  end
8
9
  end
9
10
 
@@ -6,10 +6,10 @@ require 'openid/store/interface'
6
6
  class ActiveRecordStore < OpenID::Store::Interface
7
7
  def store_association(server_url, assoc)
8
8
  remove_association(server_url, assoc.handle)
9
- Association.create(:server_url => server_url,
9
+ Association.create!(:server_url => server_url,
10
10
  :handle => assoc.handle,
11
11
  :secret => assoc.secret,
12
- :issued => assoc.issued,
12
+ :issued => assoc.issued.to_i,
13
13
  :lifetime => assoc.lifetime,
14
14
  :assoc_type => assoc.assoc_type)
15
15
  end
@@ -40,7 +40,7 @@ class ActiveRecordStore < OpenID::Store::Interface
40
40
  def use_nonce(server_url, timestamp, salt)
41
41
  return false if Nonce.find_by_server_url_and_timestamp_and_salt(server_url, timestamp, salt)
42
42
  return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
43
- Nonce.create(:server_url => server_url, :timestamp => timestamp, :salt => salt)
43
+ Nonce.create!(:server_url => server_url, :timestamp => timestamp, :salt => salt)
44
44
  return true
45
45
  end
46
46
 
@@ -14,9 +14,15 @@ class ConsumerController < ApplicationController
14
14
 
15
15
  def start
16
16
  begin
17
- oidreq = consumer.begin(params[:openid_identifier])
17
+ identifier = params[:openid_identifier]
18
+ if identifier.nil?
19
+ flash[:error] = "Enter an OpenID identifier"
20
+ redirect_to :action => 'index'
21
+ return
22
+ end
23
+ oidreq = consumer.begin(identifier)
18
24
  rescue OpenID::OpenIDError => e
19
- flash[:error] = "Discovery failed for #{params[:openid_identifier]}: #{e}"
25
+ flash[:error] = "Discovery failed for #{identifier}: #{e}"
20
26
  redirect_to :action => 'index'
21
27
  return
22
28
  end
@@ -45,7 +51,7 @@ class ConsumerController < ApplicationController
45
51
  if oidreq.send_redirect?(realm, return_to, params[:immediate])
46
52
  redirect_to oidreq.redirect_url(realm, return_to, params[:immediate])
47
53
  else
48
- @form_text = oidreq.form_markup(realm, return_to, params[:immediate], {'id' => 'openid_form'})
54
+ render :text => oidreq.html_markup(realm, return_to, params[:immediate], {'id' => 'openid_form'})
49
55
  end
50
56
  end
51
57
 
@@ -86,8 +92,8 @@ class ConsumerController < ApplicationController
86
92
  else
87
93
  pape_message << ", but the server did not report one."
88
94
  end
89
- if pape_resp.auth_age
90
- pape_message << "<br><b>Authentication age:</b> #{pape_resp.auth_age} seconds"
95
+ if pape_resp.auth_time
96
+ pape_message << "<br><b>Authentication time:</b> #{pape_resp.auth_time} seconds"
91
97
  end
92
98
  if pape_resp.nist_auth_level
93
99
  pape_message << "<br><b>NIST Auth Level:</b> #{pape_resp.nist_auth_level}"
data/lib/openid.rb CHANGED
@@ -12,5 +12,9 @@
12
12
  # implied. See the License for the specific language governing
13
13
  # permissions and limitations under the License.
14
14
 
15
+ module OpenID
16
+ VERSION = "2.1.2"
17
+ end
18
+
15
19
  require "openid/consumer"
16
20
  require 'openid/server'
@@ -28,13 +28,13 @@ module OpenID
28
28
  parsed = Util.kv_to_seq(serialized)
29
29
  parsed_fields = parsed.map{|k, v| k.to_sym}
30
30
  if parsed_fields != FIELD_ORDER
31
- raise StandardError, 'Unexpected fields in serialized association'\
31
+ raise ProtocolError, 'Unexpected fields in serialized association'\
32
32
  " (Expected #{FIELD_ORDER.inspect}, got #{parsed_fields.inspect})"
33
33
  end
34
34
  version, handle, secret64, issued_s, lifetime_s, assoc_type =
35
35
  parsed.map {|field, value| value}
36
36
  if version != '2'
37
- raise StandardError, "Attempted to deserialize unsupported version "\
37
+ raise ProtocolError, "Attempted to deserialize unsupported version "\
38
38
  "(#{parsed[0][1].inspect})"
39
39
  end
40
40
 
@@ -101,7 +101,7 @@ module OpenID
101
101
  when 'HMAC-SHA256'
102
102
  CryptUtil.hmac_sha256(@secret, kv)
103
103
  else
104
- raise StandardError, "Association has unknown type: "\
104
+ raise ProtocolError, "Association has unknown type: "\
105
105
  "#{assoc_type.inspect}"
106
106
  end
107
107
  end
@@ -111,7 +111,7 @@ module OpenID
111
111
  def make_pairs(message)
112
112
  signed = message.get_arg(OPENID_NS, 'signed')
113
113
  if signed.nil?
114
- raise StandardError, 'Missing signed list'
114
+ raise ProtocolError, 'Missing signed list'
115
115
  end
116
116
  signed_fields = signed.split(',', -1)
117
117
  data = message.to_post_args
@@ -122,7 +122,7 @@ module OpenID
122
122
  def check_message_signature(message)
123
123
  message_sig = message.get_arg(OPENID_NS, 'sig')
124
124
  if message_sig.nil?
125
- raise StandardError, "#{message} has no sig."
125
+ raise ProtocolError, "#{message} has no sig."
126
126
  end
127
127
  calculated_sig = get_message_signature(message)
128
128
  return calculated_sig == message_sig
@@ -190,13 +190,13 @@ module OpenID
190
190
  when 'HMAC-SHA256'
191
191
  ['DH-SHA256', 'no-encryption']
192
192
  else
193
- raise StandardError, "Unknown association type #{assoc_type.inspect}"
193
+ raise ProtocolError, "Unknown association type #{assoc_type.inspect}"
194
194
  end
195
195
  end
196
196
 
197
197
  def self.check_session_type(assoc_type, session_type)
198
198
  if !get_session_types(assoc_type).include?(session_type)
199
- raise StandardError, "Session type #{session_type.inspect} not "\
199
+ raise ProtocolError, "Session type #{session_type.inspect} not "\
200
200
  "valid for association type #{assoc_type.inspect}"
201
201
  end
202
202
  end
@@ -158,6 +158,17 @@ module OpenID
158
158
  return message.to_form_markup(@endpoint.server_url, form_tag_attrs)
159
159
  end
160
160
 
161
+ # Get a complete HTML document that autosubmits the request to the IDP
162
+ # with javascript. This method wraps form_markup - see that method's
163
+ # documentation for help with the parameters.
164
+ def html_markup(realm, return_to=nil, immediate=false,
165
+ form_tag_attrs=nil)
166
+ Util.auto_submit_html(form_markup(realm,
167
+ return_to,
168
+ immediate,
169
+ form_tag_attrs))
170
+ end
171
+
161
172
  # Should this OpenID authentication request be sent as a HTTP
162
173
  # redirect or as a POST (form submission)?
163
174
  #
@@ -57,9 +57,18 @@ module OpenID
57
57
 
58
58
  def display_identifier
59
59
  return @display_identifier if @display_identifier
60
- return @claimed_id if @claimed_id.nil? or not URI.parse(@claimed_id).fragment
61
60
 
62
- disp = URI.parse(@claimed_id)
61
+ return @claimed_id if @claimed_id.nil?
62
+
63
+ begin
64
+ parsed_identifier = URI.parse(@claimed_id)
65
+ rescue URI::InvalidURIError
66
+ raise ProtocolError, "Claimed identifier #{claimed_id} is not a valid URI"
67
+ end
68
+
69
+ return @claimed_id if not parsed_identifier.fragment
70
+
71
+ disp = parsed_identifier
63
72
  disp.fragment = nil
64
73
 
65
74
  return disp.to_s
@@ -434,7 +443,7 @@ module OpenID
434
443
 
435
444
  def self.discover_no_yadis(uri)
436
445
  http_resp = OpenID.fetch(uri)
437
- if http_resp.code != "200"
446
+ if http_resp.code != "200" and http_resp.code != "206"
438
447
  raise DiscoveryFailure.new(
439
448
  "HTTP Response status from identity URL host is not \"200\". "\
440
449
  "Got status #{http_resp.code.inspect}", http_resp)
@@ -2,6 +2,7 @@ require "openid/message"
2
2
  require "openid/protocolerror"
3
3
  require "openid/kvpost"
4
4
  require "openid/consumer/discovery"
5
+ require "openid/urinorm"
5
6
 
6
7
  module OpenID
7
8
  class TypeURIMismatch < ProtocolError
@@ -138,7 +139,7 @@ module OpenID
138
139
 
139
140
  def verify_return_to
140
141
  begin
141
- msg_return_to = URI.parse(fetch('return_to'))
142
+ msg_return_to = URI.parse(URINorm::urinorm(fetch('return_to')))
142
143
  rescue URI::InvalidURIError
143
144
  raise ProtocolError, ("return_to is not a valid URI")
144
145
  end
@@ -188,7 +189,7 @@ module OpenID
188
189
 
189
190
  def verify_return_to_base(msg_return_to)
190
191
  begin
191
- app_parsed = URI.parse(@current_url)
192
+ app_parsed = URI.parse(URINorm::urinorm(@current_url))
192
193
  rescue URI::InvalidURIError
193
194
  raise ProtocolError, "current_url is not a valid URI: #{@current_url}"
194
195
  end
@@ -239,24 +240,17 @@ module OpenID
239
240
  end
240
241
 
241
242
  def create_check_auth_request
242
- check_args = {}
243
-
244
- # Arguments that are always passed to the server and not
245
- # included in the signature.
246
- for k in ['assoc_handle', 'sig', 'signed', 'invalidate_handle']
247
- val = fetch(k, nil)
248
- if !val.nil?
249
- check_args[k] = val
250
- end
251
- end
243
+ signed_list = @message.get_arg(OPENID_NS, 'signed', NO_DEFAULT).split(',')
252
244
 
253
- for k in signed_list
254
- val = @message.get_aliased_arg(k, NO_DEFAULT)
255
- check_args[k] = val
256
- end
245
+ # check that we got all the signed arguments
246
+ signed_list.each {|k|
247
+ @message.get_aliased_arg(k, NO_DEFAULT)
248
+ }
257
249
 
258
- check_args['mode'] = 'check_authentication'
259
- return Message.from_openid_args(check_args)
250
+ ca_message = @message.copy
251
+ ca_message.set_arg(OPENID_NS, 'mode', 'check_authentication')
252
+
253
+ return ca_message
260
254
  end
261
255
 
262
256
  # Process the response message from a check_authentication
@@ -352,7 +346,7 @@ module OpenID
352
346
 
353
347
  if @endpoint.nil?
354
348
  Util.log('No pre-discovered information supplied')
355
- discover_and_verify(to_match)
349
+ discover_and_verify(to_match.claimed_id, [to_match])
356
350
  else
357
351
  begin
358
352
  verify_discovery_single(@endpoint, to_match)
@@ -360,7 +354,7 @@ module OpenID
360
354
  Util.log("Error attempting to use stored discovery "\
361
355
  "information: #{why.message}")
362
356
  Util.log("Attempting discovery to verify endpoint")
363
- discover_and_verify(to_match)
357
+ discover_and_verify(to_match.claimed_id, [to_match])
364
358
  end
365
359
  end
366
360
 
@@ -376,7 +370,7 @@ module OpenID
376
370
 
377
371
  if claimed_id.nil?
378
372
  if @endpoint.nil?
379
- raise StandardError, ("When using OpenID 1, the claimed ID must "\
373
+ raise ProtocolError, ("When using OpenID 1, the claimed ID must "\
380
374
  "be supplied, either by passing it through "\
381
375
  "as a return_to parameter or by using a "\
382
376
  "session, and supplied to the IdResHandler "\
@@ -414,55 +408,53 @@ module OpenID
414
408
  # Either no endpoint was supplied or OpenID 1.x verification
415
409
  # of the information that's in the message failed on that
416
410
  # endpoint.
417
- begin
418
- discover_and_verify(to_match)
419
- rescue TypeURIMismatch
420
- discover_and_verify(to_match_1_0)
421
- end
411
+ discover_and_verify(to_match.claimed_id, [to_match, to_match_1_0])
422
412
  end
423
413
 
424
414
  # Given an endpoint object created from the information in an
425
415
  # OpenID response, perform discovery and verify the discovery
426
416
  # results, returning the matching endpoint that is the result of
427
417
  # doing that discovery.
428
- def discover_and_verify(to_match)
429
- Util.log("Performing discovery on #{to_match.claimed_id}")
430
- _, services = OpenID.discover(to_match.claimed_id)
418
+ def discover_and_verify(claimed_id, to_match_endpoints)
419
+ Util.log("Performing discovery on #{claimed_id}")
420
+ _, services = OpenID.discover(claimed_id)
431
421
  if services.length == 0
432
422
  # XXX: this might want to be something other than
433
423
  # ProtocolError. In Python, it's DiscoveryFailure
434
424
  raise ProtocolError, ("No OpenID information found at "\
435
- "#{to_match.claimed_id}")
425
+ "#{claimed_id}")
436
426
  end
437
- verify_discovered_services(services, to_match)
427
+ verify_discovered_services(claimed_id, services, to_match_endpoints)
438
428
  end
439
429
 
440
430
 
441
- def verify_discovered_services(services, to_match)
431
+ def verify_discovered_services(claimed_id, services, to_match_endpoints)
442
432
  # Search the services resulting from discovery to find one
443
433
  # that matches the information from the assertion
444
434
  failure_messages = []
445
435
  for endpoint in services
446
- begin
447
- verify_discovery_single(endpoint, to_match)
448
- rescue ProtocolError => why
449
- failure_messages << why.message
450
- else
451
- # It matches, so discover verification has
452
- # succeeded. Return this endpoint.
453
- @endpoint = endpoint
454
- return
436
+ for to_match_endpoint in to_match_endpoints
437
+ begin
438
+ verify_discovery_single(endpoint, to_match_endpoint)
439
+ rescue ProtocolError => why
440
+ failure_messages << why.message
441
+ else
442
+ # It matches, so discover verification has
443
+ # succeeded. Return this endpoint.
444
+ @endpoint = endpoint
445
+ return
446
+ end
455
447
  end
456
448
  end
457
449
 
458
- Util.log("Discovery verification failure for #{to_match.claimed_id}")
450
+ Util.log("Discovery verification failure for #{claimed_id}")
459
451
  failure_messages.each do |failure_message|
460
452
  Util.log(" * Endpoint mismatch: " + failure_message)
461
453
  end
462
454
 
463
455
  # XXX: is DiscoveryFailure in Python OpenID
464
456
  raise ProtocolError, ("No matching endpoint found after "\
465
- "discovering #{to_match.claimed_id}")
457
+ "discovering #{claimed_id}")
466
458
  end
467
459
 
468
460
  def verify_discovery_single(endpoint, to_match)