entp-ruby-openid 2.2
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.
- data/CHANGELOG +215 -0
- data/INSTALL +47 -0
- data/LICENSE +210 -0
- data/NOTICE +2 -0
- data/README +85 -0
- data/UPGRADE +127 -0
- data/admin/runtests.rb +45 -0
- data/examples/README +32 -0
- data/examples/active_record_openid_store/README +58 -0
- data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +24 -0
- data/examples/active_record_openid_store/XXX_upgrade_open_id_store.rb +26 -0
- data/examples/active_record_openid_store/init.rb +8 -0
- data/examples/active_record_openid_store/lib/association.rb +10 -0
- data/examples/active_record_openid_store/lib/nonce.rb +3 -0
- data/examples/active_record_openid_store/lib/open_id_setting.rb +4 -0
- data/examples/active_record_openid_store/lib/openid_ar_store.rb +57 -0
- data/examples/active_record_openid_store/test/store_test.rb +212 -0
- data/examples/discover +49 -0
- data/examples/rails_openid/README +153 -0
- data/examples/rails_openid/Rakefile +10 -0
- data/examples/rails_openid/app/controllers/application.rb +4 -0
- data/examples/rails_openid/app/controllers/consumer_controller.rb +125 -0
- data/examples/rails_openid/app/controllers/login_controller.rb +45 -0
- data/examples/rails_openid/app/controllers/server_controller.rb +265 -0
- data/examples/rails_openid/app/helpers/application_helper.rb +3 -0
- data/examples/rails_openid/app/helpers/login_helper.rb +2 -0
- data/examples/rails_openid/app/helpers/server_helper.rb +9 -0
- data/examples/rails_openid/app/views/consumer/index.rhtml +81 -0
- data/examples/rails_openid/app/views/layouts/server.rhtml +68 -0
- data/examples/rails_openid/app/views/login/index.rhtml +56 -0
- data/examples/rails_openid/app/views/server/decide.rhtml +26 -0
- data/examples/rails_openid/config/boot.rb +19 -0
- data/examples/rails_openid/config/database.yml +74 -0
- data/examples/rails_openid/config/environment.rb +54 -0
- data/examples/rails_openid/config/environments/development.rb +19 -0
- data/examples/rails_openid/config/environments/production.rb +19 -0
- data/examples/rails_openid/config/environments/test.rb +19 -0
- data/examples/rails_openid/config/routes.rb +24 -0
- data/examples/rails_openid/doc/README_FOR_APP +2 -0
- data/examples/rails_openid/public/404.html +8 -0
- data/examples/rails_openid/public/500.html +8 -0
- data/examples/rails_openid/public/dispatch.cgi +12 -0
- data/examples/rails_openid/public/dispatch.fcgi +26 -0
- data/examples/rails_openid/public/dispatch.rb +12 -0
- data/examples/rails_openid/public/favicon.ico +0 -0
- data/examples/rails_openid/public/images/openid_login_bg.gif +0 -0
- data/examples/rails_openid/public/javascripts/controls.js +750 -0
- data/examples/rails_openid/public/javascripts/dragdrop.js +584 -0
- data/examples/rails_openid/public/javascripts/effects.js +854 -0
- data/examples/rails_openid/public/javascripts/prototype.js +1785 -0
- data/examples/rails_openid/public/robots.txt +1 -0
- data/examples/rails_openid/script/about +3 -0
- data/examples/rails_openid/script/breakpointer +3 -0
- data/examples/rails_openid/script/console +3 -0
- data/examples/rails_openid/script/destroy +3 -0
- data/examples/rails_openid/script/generate +3 -0
- data/examples/rails_openid/script/performance/benchmarker +3 -0
- data/examples/rails_openid/script/performance/profiler +3 -0
- data/examples/rails_openid/script/plugin +3 -0
- data/examples/rails_openid/script/process/reaper +3 -0
- data/examples/rails_openid/script/process/spawner +3 -0
- data/examples/rails_openid/script/process/spinner +3 -0
- data/examples/rails_openid/script/runner +3 -0
- data/examples/rails_openid/script/server +3 -0
- data/examples/rails_openid/test/functional/login_controller_test.rb +18 -0
- data/examples/rails_openid/test/functional/server_controller_test.rb +18 -0
- data/examples/rails_openid/test/test_helper.rb +28 -0
- data/lib/hmac/hmac.rb +112 -0
- data/lib/hmac/sha1.rb +11 -0
- data/lib/hmac/sha2.rb +25 -0
- data/lib/openid.rb +22 -0
- data/lib/openid/association.rb +249 -0
- data/lib/openid/consumer.rb +395 -0
- data/lib/openid/consumer/associationmanager.rb +344 -0
- data/lib/openid/consumer/checkid_request.rb +186 -0
- data/lib/openid/consumer/discovery.rb +497 -0
- data/lib/openid/consumer/discovery_manager.rb +123 -0
- data/lib/openid/consumer/html_parse.rb +134 -0
- data/lib/openid/consumer/idres.rb +523 -0
- data/lib/openid/consumer/responses.rb +150 -0
- data/lib/openid/cryptutil.rb +115 -0
- data/lib/openid/dh.rb +89 -0
- data/lib/openid/extension.rb +39 -0
- data/lib/openid/extensions/ax.rb +539 -0
- data/lib/openid/extensions/oauth.rb +91 -0
- data/lib/openid/extensions/pape.rb +179 -0
- data/lib/openid/extensions/sreg.rb +277 -0
- data/lib/openid/extras.rb +11 -0
- data/lib/openid/fetchers.rb +258 -0
- data/lib/openid/kvform.rb +136 -0
- data/lib/openid/kvpost.rb +58 -0
- data/lib/openid/message.rb +553 -0
- data/lib/openid/protocolerror.rb +12 -0
- data/lib/openid/server.rb +1544 -0
- data/lib/openid/store.rb +10 -0
- data/lib/openid/store/filesystem.rb +272 -0
- data/lib/openid/store/interface.rb +75 -0
- data/lib/openid/store/memcache.rb +109 -0
- data/lib/openid/store/memory.rb +84 -0
- data/lib/openid/store/nonce.rb +68 -0
- data/lib/openid/trustroot.rb +349 -0
- data/lib/openid/urinorm.rb +75 -0
- data/lib/openid/util.rb +119 -0
- data/lib/openid/version.rb +3 -0
- data/lib/openid/yadis.rb +15 -0
- data/lib/openid/yadis/accept.rb +148 -0
- data/lib/openid/yadis/constants.rb +21 -0
- data/lib/openid/yadis/discovery.rb +153 -0
- data/lib/openid/yadis/filters.rb +205 -0
- data/lib/openid/yadis/htmltokenizer.rb +305 -0
- data/lib/openid/yadis/parsehtml.rb +45 -0
- data/lib/openid/yadis/services.rb +42 -0
- data/lib/openid/yadis/xrds.rb +155 -0
- data/lib/openid/yadis/xri.rb +90 -0
- data/lib/openid/yadis/xrires.rb +91 -0
- data/test/data/test_discover/openid_utf8.html +11 -0
- data/test/support/test_data_mixin.rb +127 -0
- data/test/support/test_util.rb +53 -0
- data/test/support/yadis_data.rb +131 -0
- data/test/support/yadis_data/accept.txt +124 -0
- data/test/support/yadis_data/dh.txt +29 -0
- data/test/support/yadis_data/example-xrds.xml +14 -0
- data/test/support/yadis_data/linkparse.txt +587 -0
- data/test/support/yadis_data/n2b64 +650 -0
- data/test/support/yadis_data/test1-discover.txt +137 -0
- data/test/support/yadis_data/test1-parsehtml.txt +152 -0
- data/test/support/yadis_data/test_discover/malformed_meta_tag.html +19 -0
- data/test/support/yadis_data/test_discover/openid.html +11 -0
- data/test/support/yadis_data/test_discover/openid2.html +11 -0
- data/test/support/yadis_data/test_discover/openid2_xrds.xml +12 -0
- data/test/support/yadis_data/test_discover/openid2_xrds_no_local_id.xml +11 -0
- data/test/support/yadis_data/test_discover/openid_1_and_2.html +11 -0
- data/test/support/yadis_data/test_discover/openid_1_and_2_xrds.xml +16 -0
- data/test/support/yadis_data/test_discover/openid_1_and_2_xrds_bad_delegate.xml +17 -0
- data/test/support/yadis_data/test_discover/openid_and_yadis.html +12 -0
- data/test/support/yadis_data/test_discover/openid_no_delegate.html +10 -0
- data/test/support/yadis_data/test_discover/openid_utf8.html +11 -0
- data/test/support/yadis_data/test_discover/yadis_0entries.xml +12 -0
- data/test/support/yadis_data/test_discover/yadis_2_bad_local_id.xml +15 -0
- data/test/support/yadis_data/test_discover/yadis_2entries_delegate.xml +22 -0
- data/test/support/yadis_data/test_discover/yadis_2entries_idp.xml +21 -0
- data/test/support/yadis_data/test_discover/yadis_another_delegate.xml +14 -0
- data/test/support/yadis_data/test_discover/yadis_idp.xml +12 -0
- data/test/support/yadis_data/test_discover/yadis_idp_delegate.xml +13 -0
- data/test/support/yadis_data/test_discover/yadis_no_delegate.xml +11 -0
- data/test/support/yadis_data/test_xrds/=j3h.2007.11.14.xrds +25 -0
- data/test/support/yadis_data/test_xrds/README +12 -0
- data/test/support/yadis_data/test_xrds/delegated-20060809-r1.xrds +34 -0
- data/test/support/yadis_data/test_xrds/delegated-20060809-r2.xrds +34 -0
- data/test/support/yadis_data/test_xrds/delegated-20060809.xrds +34 -0
- data/test/support/yadis_data/test_xrds/no-xrd.xml +7 -0
- data/test/support/yadis_data/test_xrds/not-xrds.xml +2 -0
- data/test/support/yadis_data/test_xrds/prefixsometimes.xrds +34 -0
- data/test/support/yadis_data/test_xrds/ref.xrds +109 -0
- data/test/support/yadis_data/test_xrds/sometimesprefix.xrds +34 -0
- data/test/support/yadis_data/test_xrds/spoof1.xrds +25 -0
- data/test/support/yadis_data/test_xrds/spoof2.xrds +25 -0
- data/test/support/yadis_data/test_xrds/spoof3.xrds +37 -0
- data/test/support/yadis_data/test_xrds/status222.xrds +9 -0
- data/test/support/yadis_data/test_xrds/subsegments.xrds +58 -0
- data/test/support/yadis_data/test_xrds/valid-populated-xrds.xml +39 -0
- data/test/support/yadis_data/trustroot.txt +153 -0
- data/test/support/yadis_data/urinorm.txt +79 -0
- data/test/test_accept.rb +170 -0
- data/test/test_association.rb +268 -0
- data/test/test_associationmanager.rb +918 -0
- data/test/test_ax.rb +690 -0
- data/test/test_checkid_request.rb +293 -0
- data/test/test_consumer.rb +260 -0
- data/test/test_cryptutil.rb +119 -0
- data/test/test_dh.rb +85 -0
- data/test/test_discover.rb +848 -0
- data/test/test_discovery_manager.rb +259 -0
- data/test/test_extension.rb +46 -0
- data/test/test_extras.rb +35 -0
- data/test/test_fetchers.rb +554 -0
- data/test/test_filters.rb +269 -0
- data/test/test_helper.rb +4 -0
- data/test/test_idres.rb +961 -0
- data/test/test_kvform.rb +164 -0
- data/test/test_kvpost.rb +64 -0
- data/test/test_linkparse.rb +100 -0
- data/test/test_message.rb +1115 -0
- data/test/test_nonce.rb +89 -0
- data/test/test_oauth.rb +176 -0
- data/test/test_openid_yadis.rb +177 -0
- data/test/test_pape.rb +248 -0
- data/test/test_parsehtml.rb +79 -0
- data/test/test_responses.rb +63 -0
- data/test/test_server.rb +2455 -0
- data/test/test_sreg.rb +479 -0
- data/test/test_stores.rb +292 -0
- data/test/test_trustroot.rb +111 -0
- data/test/test_urinorm.rb +34 -0
- data/test/test_util.rb +145 -0
- data/test/test_xrds.rb +167 -0
- data/test/test_xri.rb +48 -0
- data/test/test_xrires.rb +67 -0
- data/test/test_yadis_discovery.rb +218 -0
- metadata +268 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module OpenID
|
|
2
|
+
class Consumer
|
|
3
|
+
|
|
4
|
+
# A set of discovered services, for tracking which providers have
|
|
5
|
+
# been attempted for an OpenID identifier
|
|
6
|
+
class DiscoveredServices
|
|
7
|
+
attr_reader :current
|
|
8
|
+
|
|
9
|
+
def initialize(starting_url, yadis_url, services)
|
|
10
|
+
@starting_url = starting_url
|
|
11
|
+
@yadis_url = yadis_url
|
|
12
|
+
@services = services.dup
|
|
13
|
+
@current = nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def next
|
|
17
|
+
@current = @services.shift
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def for_url?(url)
|
|
21
|
+
[@starting_url, @yadis_url].member?(url)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def started?
|
|
25
|
+
!@current.nil?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def empty?
|
|
29
|
+
@services.empty?
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Manages calling discovery and tracking which endpoints have
|
|
34
|
+
# already been attempted.
|
|
35
|
+
class DiscoveryManager
|
|
36
|
+
def initialize(session, url, session_key_suffix=nil)
|
|
37
|
+
@url = url
|
|
38
|
+
|
|
39
|
+
@session = session
|
|
40
|
+
@session_key_suffix = session_key_suffix || 'auth'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def get_next_service
|
|
44
|
+
manager = get_manager
|
|
45
|
+
if !manager.nil? && manager.empty?
|
|
46
|
+
destroy_manager
|
|
47
|
+
manager = nil
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if manager.nil?
|
|
51
|
+
yadis_url, services = yield @url
|
|
52
|
+
manager = create_manager(yadis_url, services)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if !manager.nil?
|
|
56
|
+
service = manager.next
|
|
57
|
+
store(manager)
|
|
58
|
+
else
|
|
59
|
+
service = nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
return service
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def cleanup(force=false)
|
|
66
|
+
manager = get_manager(force)
|
|
67
|
+
if !manager.nil?
|
|
68
|
+
service = manager.current
|
|
69
|
+
destroy_manager(force)
|
|
70
|
+
else
|
|
71
|
+
service = nil
|
|
72
|
+
end
|
|
73
|
+
return service
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
protected
|
|
77
|
+
|
|
78
|
+
def get_manager(force=false)
|
|
79
|
+
manager = load
|
|
80
|
+
if force || manager.nil? || manager.for_url?(@url)
|
|
81
|
+
return manager
|
|
82
|
+
else
|
|
83
|
+
return nil
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def create_manager(yadis_url, services)
|
|
88
|
+
manager = get_manager
|
|
89
|
+
if !manager.nil?
|
|
90
|
+
raise StandardError, "There is already a manager for #{yadis_url}"
|
|
91
|
+
end
|
|
92
|
+
if services.empty?
|
|
93
|
+
return nil
|
|
94
|
+
end
|
|
95
|
+
manager = DiscoveredServices.new(@url, yadis_url, services)
|
|
96
|
+
store(manager)
|
|
97
|
+
return manager
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def destroy_manager(force=false)
|
|
101
|
+
if !get_manager(force).nil?
|
|
102
|
+
destroy!
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def session_key
|
|
107
|
+
'OpenID::Consumer::DiscoveredServices::' + @session_key_suffix
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def store(manager)
|
|
111
|
+
@session[session_key] = manager
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def load
|
|
115
|
+
@session[session_key]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def destroy!
|
|
119
|
+
@session[session_key] = nil
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require "openid/yadis/htmltokenizer"
|
|
2
|
+
|
|
3
|
+
module OpenID
|
|
4
|
+
|
|
5
|
+
# Stuff to remove before we start looking for tags
|
|
6
|
+
REMOVED_RE = /
|
|
7
|
+
# Comments
|
|
8
|
+
<!--.*?-->
|
|
9
|
+
|
|
10
|
+
# CDATA blocks
|
|
11
|
+
| <!\[CDATA\[.*?\]\]>
|
|
12
|
+
|
|
13
|
+
# script blocks
|
|
14
|
+
| <script\b
|
|
15
|
+
|
|
16
|
+
# make sure script is not an XML namespace
|
|
17
|
+
(?!:)
|
|
18
|
+
|
|
19
|
+
[^>]*>.*?<\/script>
|
|
20
|
+
|
|
21
|
+
/mix
|
|
22
|
+
|
|
23
|
+
def OpenID.openid_unescape(s)
|
|
24
|
+
s.gsub('&','&').gsub('<','<').gsub('>','>').gsub('"','"')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def OpenID.unescape_hash(h)
|
|
28
|
+
newh = {}
|
|
29
|
+
h.map{|k,v|
|
|
30
|
+
newh[k]=openid_unescape(v)
|
|
31
|
+
}
|
|
32
|
+
newh
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def OpenID.parse_link_attrs(html)
|
|
37
|
+
stripped = html.gsub(REMOVED_RE,'')
|
|
38
|
+
parser = HTMLTokenizer.new(stripped)
|
|
39
|
+
|
|
40
|
+
links = []
|
|
41
|
+
# to keep track of whether or not we are in the head element
|
|
42
|
+
in_head = false
|
|
43
|
+
in_html = false
|
|
44
|
+
saw_head = false
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
while el = parser.getTag('head', '/head', 'link', 'body', '/body',
|
|
48
|
+
'html', '/html')
|
|
49
|
+
|
|
50
|
+
# we are leaving head or have reached body, so we bail
|
|
51
|
+
return links if ['/head', 'body', '/body', '/html'].member?(el.tag_name)
|
|
52
|
+
|
|
53
|
+
# enforce html > head > link
|
|
54
|
+
if el.tag_name == 'html'
|
|
55
|
+
in_html = true
|
|
56
|
+
end
|
|
57
|
+
next unless in_html
|
|
58
|
+
if el.tag_name == 'head'
|
|
59
|
+
if saw_head
|
|
60
|
+
return links #only allow one head
|
|
61
|
+
end
|
|
62
|
+
saw_head = true
|
|
63
|
+
unless el.to_s[-2] == 47 # tag ends with a /: a short tag
|
|
64
|
+
in_head = true
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
next unless in_head
|
|
68
|
+
|
|
69
|
+
return links if el.tag_name == 'html'
|
|
70
|
+
|
|
71
|
+
if el.tag_name == 'link'
|
|
72
|
+
links << unescape_hash(el.attr_hash)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
rescue Exception # just stop parsing if there's an error
|
|
77
|
+
end
|
|
78
|
+
return links
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def OpenID.rel_matches(rel_attr, target_rel)
|
|
82
|
+
# Does this target_rel appear in the rel_str?
|
|
83
|
+
# XXX: TESTME
|
|
84
|
+
rels = rel_attr.strip().split()
|
|
85
|
+
rels.each { |rel|
|
|
86
|
+
rel = rel.downcase
|
|
87
|
+
if rel == target_rel
|
|
88
|
+
return true
|
|
89
|
+
end
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return false
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def OpenID.link_has_rel(link_attrs, target_rel)
|
|
96
|
+
# Does this link have target_rel as a relationship?
|
|
97
|
+
|
|
98
|
+
# XXX: TESTME
|
|
99
|
+
rel_attr = link_attrs['rel']
|
|
100
|
+
return (rel_attr and rel_matches(rel_attr, target_rel))
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def OpenID.find_links_rel(link_attrs_list, target_rel)
|
|
104
|
+
# Filter the list of link attributes on whether it has target_rel
|
|
105
|
+
# as a relationship.
|
|
106
|
+
|
|
107
|
+
# XXX: TESTME
|
|
108
|
+
matchesTarget = lambda { |attrs| link_has_rel(attrs, target_rel) }
|
|
109
|
+
result = []
|
|
110
|
+
|
|
111
|
+
link_attrs_list.each { |item|
|
|
112
|
+
if matchesTarget.call(item)
|
|
113
|
+
result << item
|
|
114
|
+
end
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return result
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def OpenID.find_first_href(link_attrs_list, target_rel)
|
|
121
|
+
# Return the value of the href attribute for the first link tag in
|
|
122
|
+
# the list that has target_rel as a relationship.
|
|
123
|
+
|
|
124
|
+
# XXX: TESTME
|
|
125
|
+
matches = find_links_rel(link_attrs_list, target_rel)
|
|
126
|
+
if !matches or matches.empty?
|
|
127
|
+
return nil
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
first = matches[0]
|
|
131
|
+
return first['href']
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
require "openid/message"
|
|
2
|
+
require "openid/protocolerror"
|
|
3
|
+
require "openid/kvpost"
|
|
4
|
+
require "openid/consumer/discovery"
|
|
5
|
+
require "openid/urinorm"
|
|
6
|
+
|
|
7
|
+
module OpenID
|
|
8
|
+
class TypeURIMismatch < ProtocolError
|
|
9
|
+
attr_reader :type_uri, :endpoint
|
|
10
|
+
|
|
11
|
+
def initialize(type_uri, endpoint)
|
|
12
|
+
@type_uri = type_uri
|
|
13
|
+
@endpoint = endpoint
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Consumer
|
|
18
|
+
@openid1_return_to_nonce_name = 'rp_nonce'
|
|
19
|
+
@openid1_return_to_claimed_id_name = 'openid1_claimed_id'
|
|
20
|
+
|
|
21
|
+
# Set the name of the query parameter that this library will use
|
|
22
|
+
# to thread a nonce through an OpenID 1 transaction. It will be
|
|
23
|
+
# appended to the return_to URL.
|
|
24
|
+
def self.openid1_return_to_nonce_name=(query_arg_name)
|
|
25
|
+
@openid1_return_to_nonce_name = query_arg_name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# See openid1_return_to_nonce_name= documentation
|
|
29
|
+
def self.openid1_return_to_nonce_name
|
|
30
|
+
@openid1_return_to_nonce_name
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Set the name of the query parameter that this library will use
|
|
34
|
+
# to thread the requested URL through an OpenID 1 transaction (for
|
|
35
|
+
# use when verifying discovered information). It will be appended
|
|
36
|
+
# to the return_to URL.
|
|
37
|
+
def self.openid1_return_to_claimed_id_name=(query_arg_name)
|
|
38
|
+
@openid1_return_to_claimed_id_name = query_arg_name
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# See openid1_return_to_claimed_id_name=
|
|
42
|
+
def self.openid1_return_to_claimed_id_name
|
|
43
|
+
@openid1_return_to_claimed_id_name
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Handles an openid.mode=id_res response. This object is
|
|
47
|
+
# instantiated and used by the Consumer.
|
|
48
|
+
class IdResHandler
|
|
49
|
+
attr_reader :endpoint, :message
|
|
50
|
+
|
|
51
|
+
def initialize(message, current_url, store=nil, endpoint=nil)
|
|
52
|
+
@store = store # Fer the nonce and invalidate_handle
|
|
53
|
+
@message = message
|
|
54
|
+
@endpoint = endpoint
|
|
55
|
+
@current_url = current_url
|
|
56
|
+
@signed_list = nil
|
|
57
|
+
|
|
58
|
+
# Start the verification process
|
|
59
|
+
id_res
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def signed_fields
|
|
63
|
+
signed_list.map {|x| 'openid.' + x}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
protected
|
|
67
|
+
|
|
68
|
+
# This method will raise ProtocolError unless the request is a
|
|
69
|
+
# valid id_res response. Once it has been verified, the methods
|
|
70
|
+
# 'endpoint', 'message', and 'signed_fields' contain the
|
|
71
|
+
# verified information.
|
|
72
|
+
def id_res
|
|
73
|
+
check_for_fields
|
|
74
|
+
verify_return_to
|
|
75
|
+
verify_discovery_results
|
|
76
|
+
check_signature
|
|
77
|
+
check_nonce
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def server_url
|
|
81
|
+
@endpoint.nil? ? nil : @endpoint.server_url
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def openid_namespace
|
|
85
|
+
@message.get_openid_namespace
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def fetch(field, default=NO_DEFAULT)
|
|
89
|
+
@message.get_arg(OPENID_NS, field, default)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def signed_list
|
|
93
|
+
if @signed_list.nil?
|
|
94
|
+
signed_list_str = fetch('signed', nil)
|
|
95
|
+
if signed_list_str.nil?
|
|
96
|
+
raise ProtocolError, 'Response missing signed list'
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
@signed_list = signed_list_str.split(',', -1)
|
|
100
|
+
end
|
|
101
|
+
@signed_list
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def check_for_fields
|
|
105
|
+
# XXX: if a field is missing, we should not have to explicitly
|
|
106
|
+
# check that it's present, just make sure that the fields are
|
|
107
|
+
# actually being used by the rest of the code in
|
|
108
|
+
# tests. Although, which fields are signed does need to be
|
|
109
|
+
# checked somewhere.
|
|
110
|
+
basic_fields = ['return_to', 'assoc_handle', 'sig', 'signed']
|
|
111
|
+
basic_sig_fields = ['return_to', 'identity']
|
|
112
|
+
|
|
113
|
+
case openid_namespace
|
|
114
|
+
when OPENID2_NS
|
|
115
|
+
require_fields = basic_fields + ['op_endpoint']
|
|
116
|
+
require_sigs = basic_sig_fields +
|
|
117
|
+
['response_nonce', 'claimed_id', 'assoc_handle', 'op_endpoint']
|
|
118
|
+
when OPENID1_NS, OPENID11_NS
|
|
119
|
+
require_fields = basic_fields + ['identity']
|
|
120
|
+
require_sigs = basic_sig_fields
|
|
121
|
+
else
|
|
122
|
+
raise RuntimeError, "check_for_fields doesn't know about "\
|
|
123
|
+
"namespace #{openid_namespace.inspect}"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
require_fields.each do |field|
|
|
127
|
+
if !@message.has_key?(OPENID_NS, field)
|
|
128
|
+
raise ProtocolError, "Missing required field #{field}"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
require_sigs.each do |field|
|
|
133
|
+
# Field is present and not in signed list
|
|
134
|
+
if @message.has_key?(OPENID_NS, field) && !signed_list.member?(field)
|
|
135
|
+
raise ProtocolError, "#{field.inspect} not signed"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def verify_return_to
|
|
141
|
+
begin
|
|
142
|
+
msg_return_to = URI.parse(URINorm::urinorm(fetch('return_to')))
|
|
143
|
+
rescue URI::InvalidURIError
|
|
144
|
+
raise ProtocolError, ("return_to is not a valid URI")
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
verify_return_to_args(msg_return_to)
|
|
148
|
+
if !@current_url.nil?
|
|
149
|
+
verify_return_to_base(msg_return_to)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def verify_return_to_args(msg_return_to)
|
|
154
|
+
return_to_parsed_query = {}
|
|
155
|
+
if !msg_return_to.query.nil?
|
|
156
|
+
CGI.parse(msg_return_to.query).each_pair do |k, vs|
|
|
157
|
+
return_to_parsed_query[k] = vs[0]
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
query = @message.to_post_args
|
|
161
|
+
return_to_parsed_query.each_pair do |rt_key, rt_val|
|
|
162
|
+
msg_val = query[rt_key]
|
|
163
|
+
if msg_val.nil?
|
|
164
|
+
raise ProtocolError, "Message missing return_to argument '#{rt_key}'"
|
|
165
|
+
elsif msg_val != rt_val
|
|
166
|
+
raise ProtocolError, ("Parameter '#{rt_key}' value "\
|
|
167
|
+
"#{msg_val.inspect} does not match "\
|
|
168
|
+
"return_to's value #{rt_val.inspect}")
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
@message.get_args(BARE_NS).each_pair do |bare_key, bare_val|
|
|
172
|
+
rt_val = return_to_parsed_query[bare_key]
|
|
173
|
+
if not return_to_parsed_query.has_key? bare_key
|
|
174
|
+
# This may be caused by your web framework throwing extra
|
|
175
|
+
# entries in to your parameters hash that were not GET or
|
|
176
|
+
# POST parameters. For example, Rails has been known to
|
|
177
|
+
# add "controller" and "action" keys; another server adds
|
|
178
|
+
# at least a "format" key.
|
|
179
|
+
raise ProtocolError, ("Unexpected parameter (not on return_to): "\
|
|
180
|
+
"'#{bare_key}'=#{rt_val.inspect})")
|
|
181
|
+
end
|
|
182
|
+
if rt_val != bare_val
|
|
183
|
+
raise ProtocolError, ("Parameter '#{bare_key}' value "\
|
|
184
|
+
"#{bare_val.inspect} does not match "\
|
|
185
|
+
"return_to's value #{rt_val.inspect}")
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def verify_return_to_base(msg_return_to)
|
|
191
|
+
begin
|
|
192
|
+
app_parsed = URI.parse(URINorm::urinorm(@current_url))
|
|
193
|
+
rescue URI::InvalidURIError
|
|
194
|
+
raise ProtocolError, "current_url is not a valid URI: #{@current_url}"
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
[:scheme, :host, :port, :path].each do |meth|
|
|
198
|
+
if msg_return_to.send(meth) != app_parsed.send(meth)
|
|
199
|
+
raise ProtocolError, "return_to #{meth.to_s} does not match"
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Raises ProtocolError if the signature is bad
|
|
205
|
+
def check_signature
|
|
206
|
+
if @store.nil?
|
|
207
|
+
assoc = nil
|
|
208
|
+
else
|
|
209
|
+
assoc = @store.get_association(server_url, fetch('assoc_handle'))
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
if assoc.nil?
|
|
213
|
+
check_auth
|
|
214
|
+
else
|
|
215
|
+
if assoc.expires_in <= 0
|
|
216
|
+
# XXX: It might be a good idea sometimes to re-start the
|
|
217
|
+
# authentication with a new association. Doing it
|
|
218
|
+
# automatically opens the possibility for
|
|
219
|
+
# denial-of-service by a server that just returns expired
|
|
220
|
+
# associations (or really short-lived associations)
|
|
221
|
+
raise ProtocolError, "Association with #{server_url} expired"
|
|
222
|
+
elsif !assoc.check_message_signature(@message)
|
|
223
|
+
raise ProtocolError, "Bad signature in response from #{server_url}"
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def check_auth
|
|
229
|
+
Util.log("Using 'check_authentication' with #{server_url}")
|
|
230
|
+
begin
|
|
231
|
+
request = create_check_auth_request
|
|
232
|
+
rescue Message::KeyNotFound => why
|
|
233
|
+
raise ProtocolError, "Could not generate 'check_authentication' "\
|
|
234
|
+
"request: #{why.message}"
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
response = OpenID.make_kv_post(request, server_url)
|
|
238
|
+
|
|
239
|
+
process_check_auth_response(response)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def create_check_auth_request
|
|
243
|
+
signed_list = @message.get_arg(OPENID_NS, 'signed', NO_DEFAULT).split(',')
|
|
244
|
+
|
|
245
|
+
# check that we got all the signed arguments
|
|
246
|
+
signed_list.each {|k|
|
|
247
|
+
@message.get_aliased_arg(k, NO_DEFAULT)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
ca_message = @message.copy
|
|
251
|
+
ca_message.set_arg(OPENID_NS, 'mode', 'check_authentication')
|
|
252
|
+
|
|
253
|
+
return ca_message
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Process the response message from a check_authentication
|
|
257
|
+
# request, invalidating associations if requested.
|
|
258
|
+
def process_check_auth_response(response)
|
|
259
|
+
is_valid = response.get_arg(OPENID_NS, 'is_valid', 'false')
|
|
260
|
+
|
|
261
|
+
invalidate_handle = response.get_arg(OPENID_NS, 'invalidate_handle')
|
|
262
|
+
if !invalidate_handle.nil?
|
|
263
|
+
Util.log("Received 'invalidate_handle' from server #{server_url}")
|
|
264
|
+
if @store.nil?
|
|
265
|
+
Util.log('Unexpectedly got "invalidate_handle" without a store!')
|
|
266
|
+
else
|
|
267
|
+
@store.remove_association(server_url, invalidate_handle)
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
if is_valid != 'true'
|
|
272
|
+
raise ProtocolError, ("Server #{server_url} responds that the "\
|
|
273
|
+
"'check_authentication' call is not valid")
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def check_nonce
|
|
278
|
+
case openid_namespace
|
|
279
|
+
when OPENID1_NS, OPENID11_NS
|
|
280
|
+
nonce =
|
|
281
|
+
@message.get_arg(BARE_NS, Consumer.openid1_return_to_nonce_name)
|
|
282
|
+
|
|
283
|
+
# We generated the nonce, so it uses the empty string as the
|
|
284
|
+
# server URL
|
|
285
|
+
server_url = ''
|
|
286
|
+
when OPENID2_NS
|
|
287
|
+
nonce = @message.get_arg(OPENID2_NS, 'response_nonce')
|
|
288
|
+
server_url = self.server_url
|
|
289
|
+
else
|
|
290
|
+
raise StandardError, 'Not reached'
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
if nonce.nil?
|
|
294
|
+
raise ProtocolError, 'Nonce missing from response'
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
begin
|
|
298
|
+
time, extra = Nonce.split_nonce(nonce)
|
|
299
|
+
rescue ArgumentError => why
|
|
300
|
+
raise ProtocolError, "Malformed nonce: #{nonce.inspect}"
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
if !@store.nil? && !@store.use_nonce(server_url, time, extra)
|
|
304
|
+
raise ProtocolError, ("Nonce already used or out of range: "\
|
|
305
|
+
"#{nonce.inspect}")
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def verify_discovery_results
|
|
310
|
+
begin
|
|
311
|
+
case openid_namespace
|
|
312
|
+
when OPENID1_NS, OPENID11_NS
|
|
313
|
+
verify_discovery_results_openid1
|
|
314
|
+
when OPENID2_NS
|
|
315
|
+
verify_discovery_results_openid2
|
|
316
|
+
else
|
|
317
|
+
raise StandardError, "Not reached: #{openid_namespace}"
|
|
318
|
+
end
|
|
319
|
+
rescue Message::KeyNotFound => why
|
|
320
|
+
raise ProtocolError, "Missing required field: #{why.message}"
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def verify_discovery_results_openid2
|
|
325
|
+
to_match = OpenIDServiceEndpoint.new
|
|
326
|
+
to_match.type_uris = [OPENID_2_0_TYPE]
|
|
327
|
+
to_match.claimed_id = fetch('claimed_id', nil)
|
|
328
|
+
to_match.local_id = fetch('identity', nil)
|
|
329
|
+
to_match.server_url = fetch('op_endpoint')
|
|
330
|
+
|
|
331
|
+
if to_match.claimed_id.nil? && !to_match.local_id.nil?
|
|
332
|
+
raise ProtocolError, ('openid.identity is present without '\
|
|
333
|
+
'openid.claimed_id')
|
|
334
|
+
elsif !to_match.claimed_id.nil? && to_match.local_id.nil?
|
|
335
|
+
raise ProtocolError, ('openid.claimed_id is present without '\
|
|
336
|
+
'openid.identity')
|
|
337
|
+
|
|
338
|
+
# This is a response without identifiers, so there's really no
|
|
339
|
+
# checking that we can do, so return an endpoint that's for
|
|
340
|
+
# the specified `openid.op_endpoint'
|
|
341
|
+
elsif to_match.claimed_id.nil?
|
|
342
|
+
@endpoint =
|
|
343
|
+
OpenIDServiceEndpoint.from_op_endpoint_url(to_match.server_url)
|
|
344
|
+
return
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
if @endpoint.nil?
|
|
348
|
+
Util.log('No pre-discovered information supplied')
|
|
349
|
+
discover_and_verify(to_match.claimed_id, [to_match])
|
|
350
|
+
else
|
|
351
|
+
begin
|
|
352
|
+
verify_discovery_single(@endpoint, to_match)
|
|
353
|
+
rescue ProtocolError => why
|
|
354
|
+
Util.log("Error attempting to use stored discovery "\
|
|
355
|
+
"information: #{why.message}")
|
|
356
|
+
Util.log("Attempting discovery to verify endpoint")
|
|
357
|
+
discover_and_verify(to_match.claimed_id, [to_match])
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
if @endpoint.claimed_id != to_match.claimed_id
|
|
362
|
+
@endpoint = @endpoint.dup
|
|
363
|
+
@endpoint.claimed_id = to_match.claimed_id
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def verify_discovery_results_openid1
|
|
368
|
+
claimed_id =
|
|
369
|
+
@message.get_arg(BARE_NS, Consumer.openid1_return_to_claimed_id_name)
|
|
370
|
+
|
|
371
|
+
if claimed_id.nil?
|
|
372
|
+
if @endpoint.nil?
|
|
373
|
+
raise ProtocolError, ("When using OpenID 1, the claimed ID must "\
|
|
374
|
+
"be supplied, either by passing it through "\
|
|
375
|
+
"as a return_to parameter or by using a "\
|
|
376
|
+
"session, and supplied to the IdResHandler "\
|
|
377
|
+
"when it is constructed.")
|
|
378
|
+
else
|
|
379
|
+
claimed_id = @endpoint.claimed_id
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
to_match = OpenIDServiceEndpoint.new
|
|
384
|
+
to_match.type_uris = [OPENID_1_1_TYPE]
|
|
385
|
+
to_match.local_id = fetch('identity')
|
|
386
|
+
# Restore delegate information from the initiation phase
|
|
387
|
+
to_match.claimed_id = claimed_id
|
|
388
|
+
|
|
389
|
+
to_match_1_0 = to_match.dup
|
|
390
|
+
to_match_1_0.type_uris = [OPENID_1_0_TYPE]
|
|
391
|
+
|
|
392
|
+
if !@endpoint.nil?
|
|
393
|
+
begin
|
|
394
|
+
begin
|
|
395
|
+
verify_discovery_single(@endpoint, to_match)
|
|
396
|
+
rescue TypeURIMismatch
|
|
397
|
+
verify_discovery_single(@endpoint, to_match_1_0)
|
|
398
|
+
end
|
|
399
|
+
rescue ProtocolError => why
|
|
400
|
+
Util.log('Error attempting to use stored discovery information: ' +
|
|
401
|
+
why.message)
|
|
402
|
+
Util.log('Attempting discovery to verify endpoint')
|
|
403
|
+
else
|
|
404
|
+
return @endpoint
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Either no endpoint was supplied or OpenID 1.x verification
|
|
409
|
+
# of the information that's in the message failed on that
|
|
410
|
+
# endpoint.
|
|
411
|
+
discover_and_verify(to_match.claimed_id, [to_match, to_match_1_0])
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# Given an endpoint object created from the information in an
|
|
415
|
+
# OpenID response, perform discovery and verify the discovery
|
|
416
|
+
# results, returning the matching endpoint that is the result of
|
|
417
|
+
# doing that discovery.
|
|
418
|
+
def discover_and_verify(claimed_id, to_match_endpoints)
|
|
419
|
+
Util.log("Performing discovery on #{claimed_id}")
|
|
420
|
+
_, services = OpenID.discover(claimed_id)
|
|
421
|
+
if services.length == 0
|
|
422
|
+
# XXX: this might want to be something other than
|
|
423
|
+
# ProtocolError. In Python, it's DiscoveryFailure
|
|
424
|
+
raise ProtocolError, ("No OpenID information found at "\
|
|
425
|
+
"#{claimed_id}")
|
|
426
|
+
end
|
|
427
|
+
verify_discovered_services(claimed_id, services, to_match_endpoints)
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def verify_discovered_services(claimed_id, services, to_match_endpoints)
|
|
432
|
+
# Search the services resulting from discovery to find one
|
|
433
|
+
# that matches the information from the assertion
|
|
434
|
+
failure_messages = []
|
|
435
|
+
for endpoint in services
|
|
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
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
Util.log("Discovery verification failure for #{claimed_id}")
|
|
451
|
+
failure_messages.each do |failure_message|
|
|
452
|
+
Util.log(" * Endpoint mismatch: " + failure_message)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
# XXX: is DiscoveryFailure in Python OpenID
|
|
456
|
+
raise ProtocolError, ("No matching endpoint found after "\
|
|
457
|
+
"discovering #{claimed_id}")
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
def verify_discovery_single(endpoint, to_match)
|
|
461
|
+
# Every type URI that's in the to_match endpoint has to be
|
|
462
|
+
# present in the discovered endpoint.
|
|
463
|
+
for type_uri in to_match.type_uris
|
|
464
|
+
if !endpoint.uses_extension(type_uri)
|
|
465
|
+
raise TypeURIMismatch.new(type_uri, endpoint)
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
# Fragments do not influence discovery, so we can't compare a
|
|
470
|
+
# claimed identifier with a fragment to discovered information.
|
|
471
|
+
defragged_claimed_id =
|
|
472
|
+
case Yadis::XRI.identifier_scheme(to_match.claimed_id)
|
|
473
|
+
when :xri
|
|
474
|
+
to_match.claimed_id
|
|
475
|
+
when :uri
|
|
476
|
+
begin
|
|
477
|
+
parsed = URI.parse(to_match.claimed_id)
|
|
478
|
+
rescue URI::InvalidURIError
|
|
479
|
+
to_match.claimed_id
|
|
480
|
+
else
|
|
481
|
+
parsed.fragment = nil
|
|
482
|
+
parsed.to_s
|
|
483
|
+
end
|
|
484
|
+
else
|
|
485
|
+
raise StandardError, 'Not reached'
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
if defragged_claimed_id != endpoint.claimed_id
|
|
489
|
+
raise ProtocolError, ("Claimed ID does not match (different "\
|
|
490
|
+
"subjects!), Expected "\
|
|
491
|
+
"#{defragged_claimed_id}, got "\
|
|
492
|
+
"#{endpoint.claimed_id}")
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
if to_match.claimed_id != endpoint.claimed_id
|
|
496
|
+
raise ProtocolError, ("claimed_id mismatch. Expected "\
|
|
497
|
+
"#{to_match.claimed_id}, got "\
|
|
498
|
+
"#{endpoint.claimed_id}")
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
# If the server URL is nil, this must be an OpenID 1
|
|
502
|
+
# response, because op_endpoint is a required parameter in
|
|
503
|
+
# OpenID 2. In that case, we don't actually care what the
|
|
504
|
+
# discovered server_url is, because signature checking or
|
|
505
|
+
# check_auth should take care of that check for us.
|
|
506
|
+
if to_match.server_url.nil?
|
|
507
|
+
if to_match.preferred_namespace != OPENID1_NS
|
|
508
|
+
raise StandardError,
|
|
509
|
+
"The code calling this must ensure that OpenID 2 "\
|
|
510
|
+
"responses have a non-none `openid.op_endpoint' and "\
|
|
511
|
+
"that it is set as the `server_url' attribute of the "\
|
|
512
|
+
"`to_match' endpoint."
|
|
513
|
+
end
|
|
514
|
+
elsif to_match.server_url != endpoint.server_url
|
|
515
|
+
raise ProtocolError, ("OP Endpoint mismatch. Expected "\
|
|
516
|
+
"#{to_match.server_url}, got "\
|
|
517
|
+
"#{endpoint.server_url}")
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
end
|