ruby-openid-2.7.0debian.orig/ 0000755 0001750 0001750 00000000000 12512544714 015314 5 ustar sbadia sbadia ruby-openid-2.7.0debian.orig/LICENSE 0000644 0001750 0001750 00000026752 12512544714 016335 0 ustar sbadia sbadia The code in lib/hmac/ is Copyright 2001 by Daiki Ueno, and distributed under
the terms of the Ruby license. See http://www.ruby-lang.org/en/LICENSE.txt
lib/openid/yadis/htmltokenizer.rb is Copyright 2004 by Ben Giddings and
distributed under the terms of the Ruby license.
The remainder of this package is Copyright 2006-2008 by JanRain, Inc. and
distributed under the terms of license below:
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
ruby-openid-2.7.0debian.orig/UPGRADE.md 0000644 0001750 0001750 00000010637 12512544714 016734 0 ustar sbadia sbadia # Upgrading from the OpenID 1.x series library
## Consumer Upgrade
The flow is largely the same, however there are a number of significant
changes. The consumer example is helpful to look at:
`examples/rails_openid/app/controllers/consumer_controller.rb`
### Stores
You will need to require the file for the store that you are using.
For the filesystem store, this is 'openid/stores/filesystem'
They are also now in modules. The filesystem store is
`OpenID::Store::Filesystem`
The format has changed, and you should remove your old store directory.
The ActiveRecord store (`examples/active_record_openid_store`) still needs
to be put in a plugin directory for your rails app. There's a migration
that needs to be run; examine the `README` in that directory.
Also, note that the stores now can be garbage collected with the method
`store.cleanup`
### Starting the OpenID transaction
The OpenIDRequest object no longer has status codes. Instead,
consumer.begin raises an OpenID::OpenIDError if there is a problem
initiating the transaction, so you'll want something along the lines of:
begin
openid_request = consumer.begin(params[:openid_identifier])
rescue OpenID::OpenIDError => e
# display error e
return
end
#success case
Data regarding the OpenID server once lived in
`openid_request.service`
The corresponding object in the 2.0 lib can be retrieved with
`openid_request.endpoint`
Getting the unverified identifier: Where you once had
`openid_request.identity_url`
you will now want
`openid_request.endpoint.claimed_id`
which might be different from what you get at the end of the transaction,
since it is now possible for users to enter their server's url directly.
Arguments on the return_to URL are now verified, so if you want to add
additional arguments to the return_to url, use
`openid_request.return_to_args['param'] = value`
Generating the redirect is the same as before, but add any extensions
first.
If you need to set up an SSL certificate authority list for the fetcher,
use the 'ca_file' attr_accessor on the `OpenID::StandardFetcher`. This has
changed from 'ca_path' in the 1.x.x series library. That is, set
`OpenID.fetcher.ca_file = '/path/to/ca.list'`
before calling consumer.begin.
### Requesting Simple Registration Data
You'll need to require the code for the extension
require 'openid/extensions/sreg'
The new code for adding an SReg request now looks like:
sreg_request = OpenID::SReg::Request.new
sreg_request.request_fields(['email', 'dob'], true) # required
sreg_request.request_fields(['nickname', 'fullname'], false) # optional
sreg_request.policy_url = policy_url
openid_request.add_extension(sreg_request)
The code for adding other extensions is similar. Code for the Attribute
Exchange (AX) and Provider Authentication Policy Extension (PAPE) are
included with the library, and additional extensions can be implemented
subclassing `OpenID::Extension`.
### Completing the transaction
The return_to and its arguments are verified, so you need to pass in
the base URL and the arguments. With Rails, the params method mashes
together parameters from GET, POST, and the path, so you'll need to pull
off the path "parameters" with something like
return_to = url_for(:only_path => false,
:controller => 'openid',
:action => 'complete')
parameters = params.reject{|k,v| request.path_parameters[k] }
openid_response = consumer.complete(parameters, return_to)
The response still uses the status codes, but they are now namespaced
slightly differently, for example `OpenID::Consumer::SUCCESS`
In the case of failure, the error message is now found in
`openid_response.message`
The identifier to display to the user can be found in
`openid_response.endpoint.display_identifier`
The Simple Registration response can be read from the OpenID response
with
sreg_response = OpenID::SReg::Response.from_success_response(openid_response)
nickname = sreg_response['nickname']
# etc.
## Server Upgrade
The server code is mostly the same as before, with the exception of
extensions. Also, you must pass in the endpoint URL to the server
constructor:
@server = OpenID::Server.new(store, server_url)
I recommend looking at
`examples/rails_openid/app/controllers/server_controller.rb`
for an example of the new way of doing extensions.
--
Dag Arneson, JanRain Inc.
Please direct questions to openid@janrain.com
ruby-openid-2.7.0debian.orig/test/ 0000755 0001750 0001750 00000000000 12512544714 016273 5 ustar sbadia sbadia ruby-openid-2.7.0debian.orig/test/test_filters.rb 0000644 0001750 0001750 00000020135 12512544714 021330 0 ustar sbadia sbadia require "minitest/autorun"
require "testutil"
require "rexml/document"
require "openid/yadis/xrds"
require "openid/yadis/filters"
module OpenID
class BasicServiceEndpointTest < Minitest::Test
def test_match_types
# Make sure the match_types operation returns the expected
# results with various inputs.
types = ["urn:bogus", "urn:testing"]
yadis_url = "http://yadis/"
no_types_endpoint = Yadis::BasicServiceEndpoint.new(yadis_url, [], nil, nil)
some_types_endpoint = Yadis::BasicServiceEndpoint.new(yadis_url, types, nil, nil)
assert(no_types_endpoint.match_types([]) == [])
assert(no_types_endpoint.match_types(["urn:absent"]) == [])
assert(some_types_endpoint.match_types([]) == [])
assert(some_types_endpoint.match_types(["urn:absent"]) == [])
assert(some_types_endpoint.match_types(types) == types)
assert(some_types_endpoint.match_types([types[1], types[0]]) == types)
assert(some_types_endpoint.match_types([types[0]]) == [types[0]])
assert(some_types_endpoint.match_types(types + ["urn:absent"]) == types)
end
def test_from_basic_service_endpoint
# Check BasicServiceEndpoint.from_basic_service_endpoint
endpoint = "unused"
e = Yadis::BasicServiceEndpoint.new(nil, [], nil, nil)
assert(Yadis::BasicServiceEndpoint.from_basic_service_endpoint(endpoint) ==
endpoint)
assert(e.from_basic_service_endpoint(endpoint) ==
endpoint)
end
end
class TransformFilterMakerTest < Minitest::Test
def make_service_element(types, uris)
service = REXML::Element.new('Service')
types.each { |type_text|
service.add_element('Type').text = type_text
}
uris.each { |uri_text|
service.add_element('URI').text = uri_text
}
return service
end
def test_get_service_endpoints
yadis_url = "http://yad.is/"
uri = "http://uri/"
type_uris = ["urn:type1", "urn:type2"]
element = make_service_element(type_uris, [uri])
filters = [Proc.new { |endpoint|
if endpoint.service_element == element
endpoint
else
nil
end
}
]
tf = Yadis::TransformFilterMaker.new(filters)
result = tf.get_service_endpoints(yadis_url, element)
assert_equal(result[0].yadis_url, yadis_url, result)
assert_equal(result[0].uri, uri, result)
end
def test_empty_transform_filter
# A transform filter with no filter procs should return nil.
endpoint = "unused"
t = Yadis::TransformFilterMaker.new([])
assert(t.apply_filters(endpoint).nil?)
end
def test_nil_filter
# A transform filter with a single nil filter should return nil.
nil_filter = Proc.new { |endpoint| nil }
t = Yadis::TransformFilterMaker.new([nil_filter])
endpoint = "unused"
assert(t.apply_filters(endpoint).nil?)
end
def test_identity_filter
# A transform filter with an identity filter should return the
# input.
identity_filter = Proc.new { |endpoint| endpoint }
t = Yadis::TransformFilterMaker.new([identity_filter])
endpoint = "unused"
assert(t.apply_filters(endpoint) == endpoint)
end
def test_return_different_endpoint
# Make sure the result of the filter is returned, rather than
# the input.
returned_endpoint = "returned endpoint"
filter = Proc.new { |endpoint| returned_endpoint }
t = Yadis::TransformFilterMaker.new([filter])
endpoint = "unused"
assert(t.apply_filters(endpoint) == returned_endpoint)
end
def test_multiple_filters
# Check filter fallback behavior on different inputs.
odd, odd_result = 45, "odd"
even, even_result = 46, "even"
filter_odd = Proc.new { |endpoint|
if endpoint % 2 == 1
odd_result
else
nil
end
}
filter_even = Proc.new { |endpoint|
if endpoint % 2 == 0
even_result
else
nil
end
}
t = Yadis::TransformFilterMaker.new([filter_odd, filter_even])
assert(t.apply_filters(odd) == odd_result)
assert(t.apply_filters(even) == even_result)
end
end
class BogusServiceEndpointExtractor
def initialize(data)
@data = data
end
def get_service_endpoints(yadis_url, service_element)
return @data
end
end
class CompoundFilterTest < Minitest::Test
def test_get_service_endpoints
first = ["bogus", "test"]
second = ["third"]
all = first + second
subfilters = [
BogusServiceEndpointExtractor.new(first),
BogusServiceEndpointExtractor.new(second),
]
cf = Yadis::CompoundFilter.new(subfilters)
assert cf.get_service_endpoints("unused", "unused") == all
end
end
class MakeFilterTest < Minitest::Test
def test_parts_nil
result = Yadis.make_filter(nil)
assert result.is_a?(Yadis::TransformFilterMaker)
end
def test_parts_array
e1 = Yadis::BasicServiceEndpoint.new(nil, [], nil, nil)
e2 = Yadis::BasicServiceEndpoint.new(nil, [], nil, nil)
result = Yadis.make_filter([e1, e2])
assert result.is_a?(Yadis::TransformFilterMaker)
assert result.filter_procs[0] == e1.method('from_basic_service_endpoint')
assert result.filter_procs[1] == e2.method('from_basic_service_endpoint')
end
def test_parts_single
e = Yadis::BasicServiceEndpoint.new(nil, [], nil, nil)
result = Yadis.make_filter(e)
assert result.is_a?(Yadis::TransformFilterMaker)
end
end
class MakeCompoundFilterTest < Minitest::Test
def test_no_filters
result = Yadis.mk_compound_filter([])
assert result.subfilters == []
end
def test_single_transform_filter
f = Yadis::TransformFilterMaker.new([])
assert_equal f, Yadis.mk_compound_filter([f])
end
def test_single_endpoint
e = Yadis::BasicServiceEndpoint.new(nil, [], nil, nil)
result = Yadis.mk_compound_filter([e])
assert result.is_a?(Yadis::TransformFilterMaker)
# Expect the transform filter to call
# from_basic_service_endpoint on the endpoint
filter = result.filter_procs[0]
assert_equal filter, e.method('from_basic_service_endpoint')
end
def test_single_proc
# Create a proc that just returns nil for any endpoint
p = Proc.new { |endpoint| nil }
result = Yadis.mk_compound_filter([p])
assert result.is_a?(Yadis::TransformFilterMaker)
# Expect the transform filter to call
# from_basic_service_endpoint on the endpoint
assert_equal result.filter_procs[0], p
end
def test_multiple_filters_same_type
f1 = Yadis::TransformFilterMaker.new([])
f2 = Yadis::TransformFilterMaker.new([])
# Expect mk_compound_filter to actually make a CompoundFilter
# from f1 and f2.
result = Yadis.mk_compound_filter([f1, f2])
assert result.is_a?(Yadis::CompoundFilter)
assert result.subfilters == [f1, f2]
end
def test_multiple_filters_different_type
f1 = Yadis::TransformFilterMaker.new([])
f2 = Yadis::BasicServiceEndpoint.new(nil, [], nil, nil)
f3 = Proc.new { |endpoint| nil }
e = Yadis::BasicServiceEndpoint.new(nil, [], nil, nil)
f4 = [e]
# Expect mk_compound_filter to actually make a CompoundFilter
# from f1 and f2.
result = Yadis.mk_compound_filter([f1, f2, f3, f4])
assert result.is_a?(Yadis::CompoundFilter)
assert result.subfilters[0] == f1
assert result.subfilters[1].filter_procs[0] == e.method('from_basic_service_endpoint')
assert result.subfilters[2].filter_procs[0] == f2.method('from_basic_service_endpoint')
assert result.subfilters[2].filter_procs[1] == f3
end
def test_filter_type_error
# Pass various non-filter objects and make sure the filter
# machinery explodes.
[nil, ["bogus"], [1], [nil, "bogus"]].each { |thing|
assert_raises(TypeError) {
Yadis.mk_compound_filter(thing)
}
}
end
end
end
ruby-openid-2.7.0debian.orig/test/test_extension.rb 0000644 0001750 0001750 00000002540 12512544714 021674 0 ustar sbadia sbadia require 'minitest/autorun'
require 'openid/extension'
require 'openid/message'
module OpenID
class DummyExtension < OpenID::Extension
TEST_URI = 'http://an.extension'
TEST_ALIAS = 'dummy'
def initialize
@ns_uri = TEST_URI
@ns_alias = TEST_ALIAS
end
def get_extension_args
return {}
end
end
class ToMessageTest < Minitest::Test
def test_OpenID1
oid1_msg = Message.new(OPENID1_NS)
ext = DummyExtension.new
ext.to_message(oid1_msg)
namespaces = oid1_msg.namespaces
assert(namespaces.implicit?(DummyExtension::TEST_URI))
assert_equal(
DummyExtension::TEST_URI,
namespaces.get_namespace_uri(DummyExtension::TEST_ALIAS))
assert_equal(DummyExtension::TEST_ALIAS,
namespaces.get_alias(DummyExtension::TEST_URI))
end
def test_OpenID2
oid2_msg = Message.new(OPENID2_NS)
ext = DummyExtension.new
ext.to_message(oid2_msg)
namespaces = oid2_msg.namespaces
assert(!namespaces.implicit?(DummyExtension::TEST_URI))
assert_equal(
DummyExtension::TEST_URI,
namespaces.get_namespace_uri(DummyExtension::TEST_ALIAS))
assert_equal(DummyExtension::TEST_ALIAS,
namespaces.get_alias(DummyExtension::TEST_URI))
end
end
end
ruby-openid-2.7.0debian.orig/test/test_discover.rb 0000644 0001750 0001750 00000057601 12512544714 021506 0 ustar sbadia sbadia require 'minitest/autorun'
require 'testutil'
require 'util'
require 'openid/fetchers'
require 'openid/yadis/discovery'
require 'openid/consumer/discovery'
require 'openid/yadis/xrires'
require 'openid/yadis/xri'
require 'openid/message'
require 'openid/util'
### Tests for conditions that trigger DiscoveryFailure
module OpenID
class SimpleMockFetcher
def initialize(test, responses)
@test = test
@responses = responses.dup
end
def fetch(url, body=nil, headers=nil, limit=nil)
response = @responses.shift
@test.assert(body.nil?)
@test.assert_equal(response.final_url, url)
return response
end
end
class TestDiscoveryFailure < Minitest::Test
def initialize(*args)
super(*args)
@responses = [
[HTTPResponse._from_raw_data(nil, nil, {}, 'http://network.error/')],
[HTTPResponse._from_raw_data(404, nil, {}, 'http://not.found/')],
[HTTPResponse._from_raw_data(400, nil, {}, 'http://bad.request/')],
[HTTPResponse._from_raw_data(500, nil, {}, 'http://server.error/')],
[HTTPResponse._from_raw_data(200, nil, {'x-xrds-location' => 'http://xrds.missing/'},
'http://header.found/'),
HTTPResponse._from_raw_data(404, nil, {}, 'http://xrds.missing/')],
]
end
def test_discovery_failure
@responses.each { |response_set|
@url = response_set[0].final_url
OpenID.fetcher = SimpleMockFetcher.new(self, response_set)
expected_status = response_set[-1].code
begin
OpenID.discover(@url)
rescue DiscoveryFailure => why
assert_equal(why.http_response.code, expected_status)
else
flunk('Did not raise DiscoveryFailure')
end
OpenID.fetcher = nil
}
end
end
### Tests for raising/catching exceptions from the fetcher through
### the discover function
class ErrorRaisingFetcher
# Just raise an exception when fetch is called
def initialize(thing_to_raise)
@thing_to_raise = thing_to_raise
end
def fetch(url, body=nil, headers=nil, limit=nil)
raise @thing_to_raise
end
end
class DidFetch < Exception
# Custom exception just to make sure it's not handled differently
end
class TestFetchException < Minitest::Test
# Discovery should only raise DiscoveryFailure
def initialize(*args)
super(*args)
@cases = [
DidFetch.new(),
Exception.new(),
ArgumentError.new(),
RuntimeError.new(),
]
end
def test_fetch_exception
@cases.each { |exc|
OpenID.fetcher = ErrorRaisingFetcher.new(exc)
assert_raises(DiscoveryFailure) {
OpenID.discover('http://doesnt.matter/')
}
OpenID.fetcher = nil
}
end
end
### Tests for openid.consumer.discover.discover
class TestNormalization < Minitest::Test
def test_addingProtocol
f = ErrorRaisingFetcher.new(RuntimeError.new())
OpenID.fetcher = f
begin
OpenID.discover('users.stompy.janrain.com:8000/x')
rescue DiscoveryFailure => why
assert why.to_s.match("Failed to fetch")
rescue RuntimeError
end
OpenID.fetcher = nil
end
end
class DiscoveryMockFetcher
def initialize(documents)
@redirect = nil
@documents = documents
@fetchlog = []
end
def fetch(url, body=nil, headers=nil, limit=nil)
@fetchlog << [url, body, headers]
if @redirect
final_url = @redirect
else
final_url = url
end
begin
ctype, body = @documents.fetch(url)
rescue IndexError
status = 404
ctype = 'text/plain'
body = ''
else
status = 200
end
return HTTPResponse._from_raw_data(status, body, {'content-type' => ctype}, final_url)
end
end
class BaseTestDiscovery < Minitest::Test
attr_accessor :id_url, :fetcher_class
def initialize(*args)
super(*args)
@id_url = "http://someuser.unittest/"
@documents = {}
@fetcher_class = DiscoveryMockFetcher
end
def _checkService(s, server_url, claimed_id=nil,
local_id=nil, canonical_id=nil,
types=nil, used_yadis=false,
display_identifier=nil)
assert_equal(server_url, s.server_url)
if types == ['2.0 OP']
assert(!claimed_id)
assert(!local_id)
assert(!s.claimed_id)
assert(!s.local_id)
assert(!s.get_local_id())
assert(!s.compatibility_mode())
assert(s.is_op_identifier())
assert_equal(s.preferred_namespace(),
OPENID_2_0_MESSAGE_NS)
else
assert_equal(claimed_id, s.claimed_id)
assert_equal(local_id, s.get_local_id())
end
if used_yadis
assert(s.used_yadis, "Expected to use Yadis")
else
assert(!s.used_yadis,
"Expected to use old-style discovery")
end
openid_types = {
'1.1' => OPENID_1_1_TYPE,
'1.0' => OPENID_1_0_TYPE,
'2.0' => OPENID_2_0_TYPE,
'2.0 OP' => OPENID_IDP_2_0_TYPE,
}
type_uris = types.collect { |t| openid_types[t] }
assert_equal(type_uris, s.type_uris)
assert_equal(canonical_id, s.canonical_id)
if canonical_id.nil?
assert_equal(claimed_id, s.display_identifier)
else
assert_equal(display_identifier, s.display_identifier)
end
end
def setup
# @documents = @documents.dup
@fetcher = @fetcher_class.new(@documents)
OpenID.fetcher = @fetcher
end
def teardown
OpenID.fetcher = nil
end
def test_blank
# XXX to avoid > 0 test requirement
end
end
# def readDataFile(filename):
# module_directory = os.path.dirname(os.path.abspath(__file__))
# filename = os.path.join(
# module_directory, 'data', 'test_discover', filename)
# return file(filename).read()
class TestDiscovery < BaseTestDiscovery
include TestDataMixin
def _discover(content_type, data,
expected_services, expected_id=nil)
if expected_id.nil?
expected_id = @id_url
end
@documents[@id_url] = [content_type, data]
id_url, services = OpenID.discover(@id_url)
assert_equal(expected_services, services.length)
assert_equal(expected_id, id_url)
return services
end
def test_404
assert_raises(DiscoveryFailure) {
OpenID.discover(@id_url + '/404')
}
end
def test_noOpenID
services = _discover('text/plain',
"junk", 0)
services = _discover(
'text/html',
read_data_file('test_discover/openid_no_delegate.html', false),
1)
_checkService(
services[0],
"http://www.myopenid.com/server",
@id_url,
@id_url,
nil,
['1.1'],
false)
end
def test_malformed_meta_tag
@id_url = "http://user.myopenid.com/"
services = _discover(
'text/html',
read_data_file('test_discover/malformed_meta_tag.html', false),
2)
_checkService(
services[0],
"http://www.myopenid.com/server",
@id_url,
@id_url,
nil,
['2.0'],
false)
_checkService(
services[1],
"http://www.myopenid.com/server",
@id_url,
@id_url,
nil,
['1.1'],
false)
end
def test_html1
services = _discover('text/html',
read_data_file('test_discover/openid.html', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
@id_url,
'http://smoker.myopenid.com/',
nil,
['1.1'],
false)
end
def test_html1Fragment
# Ensure that the Claimed Identifier does not have a fragment if
# one is supplied in the User Input.
content_type = 'text/html'
data = read_data_file('test_discover/openid.html', false)
expected_services = 1
@documents[@id_url] = [content_type, data]
expected_id = @id_url
@id_url = @id_url + '#fragment'
id_url, services = OpenID.discover(@id_url)
assert_equal(expected_services, services.length)
assert_equal(expected_id, id_url)
_checkService(services[0],
"http://www.myopenid.com/server",
expected_id,
'http://smoker.myopenid.com/',
nil,
['1.1'],
false)
end
def test_html2
services = _discover('text/html',
read_data_file('test_discover/openid2.html', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
@id_url,
'http://smoker.myopenid.com/',
nil,
['2.0'],
false)
end
def test_html1And2
services = _discover(
'text/html',
read_data_file('test_discover/openid_1_and_2.html', false),
2)
services.zip(['2.0', '1.1']).each { |s, t|
_checkService(s,
"http://www.myopenid.com/server",
@id_url,
'http://smoker.myopenid.com/',
nil,
[t],
false)
}
end
def test_html_utf8
utf8_html = read_data_file('test_discover/openid_utf8.html', false)
utf8_html.force_encoding("UTF-8") if utf8_html.respond_to?(:force_encoding)
services = _discover('text/html', utf8_html, 1)
_checkService(services[0],
"http://www.myopenid.com/server",
@id_url,
'http://smoker.myopenid.com/',
nil,
['1.1'],
false)
end
def test_yadisEmpty
_discover('application/xrds+xml',
read_data_file('test_discover/yadis_0entries.xml', false),
0)
end
def test_htmlEmptyYadis
# HTML document has discovery information, but points to an
# empty Yadis document. The XRDS document pointed to by
# "openid_and_yadis.html"
@documents[@id_url + 'xrds'] = ['application/xrds+xml',
read_data_file('test_discover/yadis_0entries.xml', false)]
services = _discover('text/html',
read_data_file('test_discover/openid_and_yadis.html', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
@id_url,
'http://smoker.myopenid.com/',
nil,
['1.1'],
false)
end
def test_yadis1NoDelegate
services = _discover('application/xrds+xml',
read_data_file('test_discover/yadis_no_delegate.xml', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
@id_url,
@id_url,
nil,
['1.0'],
true)
end
def test_yadis2NoLocalID
services = _discover('application/xrds+xml',
read_data_file('test_discover/openid2_xrds_no_local_id.xml', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
@id_url,
@id_url,
nil,
['2.0'],
true)
end
def test_yadis2
services = _discover('application/xrds+xml',
read_data_file('test_discover/openid2_xrds.xml', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
@id_url,
'http://smoker.myopenid.com/',
nil,
['2.0'],
true)
end
def test_yadis2OP
services = _discover('application/xrds+xml',
read_data_file('test_discover/yadis_idp.xml', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
nil, nil, nil,
['2.0 OP'],
true)
end
def test_yadis2OPDelegate
# The delegate tag isn't meaningful for OP entries.
services = _discover('application/xrds+xml',
read_data_file('test_discover/yadis_idp_delegate.xml', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
nil, nil, nil,
['2.0 OP'],
true)
end
def test_yadis2BadLocalID
assert_raises(DiscoveryFailure) {
_discover('application/xrds+xml',
read_data_file('test_discover/yadis_2_bad_local_id.xml', false),
1)
}
end
def test_yadis1And2
services = _discover('application/xrds+xml',
read_data_file('test_discover/openid_1_and_2_xrds.xml', false),
1)
_checkService(services[0],
"http://www.myopenid.com/server",
@id_url,
'http://smoker.myopenid.com/',
nil,
['2.0', '1.1'],
true)
end
def test_yadis1And2BadLocalID
assert_raises(DiscoveryFailure) {
_discover('application/xrds+xml',
read_data_file('test_discover/openid_1_and_2_xrds_bad_delegate.xml', false),
1)
}
end
end
class MockFetcherForXRIProxy
def initialize(documents, proxy_url=Yadis::XRI::ProxyResolver::DEFAULT_PROXY)
@documents = documents
@fetchlog = []
@proxy_url = nil
end
def fetch(url, body=nil, headers=nil, limit=nil)
@fetchlog << [url, body, headers]
u = URI::parse(url)
xri = u.path
query = u.query
if !headers and !query
raise ArgumentError.new("No headers or query; you probably didn't " +
"mean to do that.")
end
if xri.start_with?('/')
xri = xri[1..-1]
end
begin
ctype, body = @documents.fetch(xri)
rescue IndexError
status = 404
ctype = 'text/plain'
body = ''
else
status = 200
end
return HTTPResponse._from_raw_data(status, body,
{'content-type' => ctype}, url)
end
end
class TestXRIDiscovery < BaseTestDiscovery
include TestDataMixin
include TestUtil
def initialize(*args)
super(*args)
@fetcher_class = MockFetcherForXRIProxy
@documents = {'=smoker' => ['application/xrds+xml',
read_data_file('test_discover/yadis_2entries_delegate.xml', false)],
'=smoker*bad' => ['application/xrds+xml',
read_data_file('test_discover/yadis_another_delegate.xml', false)]}
end
def test_xri
_, services = OpenID.discover_xri('=smoker')
_checkService(services[0],
"http://www.myopenid.com/server",
Yadis::XRI.make_xri("=!1000"),
'http://smoker.myopenid.com/',
Yadis::XRI.make_xri("=!1000"),
['1.0'],
true,
'=smoker')
_checkService(services[1],
"http://www.livejournal.com/openid/server.bml",
Yadis::XRI.make_xri("=!1000"),
'http://frank.livejournal.com/',
Yadis::XRI.make_xri("=!1000"),
['1.0'],
true,
'=smoker')
end
def test_xri_normalize
_, services = OpenID.discover_xri('xri://=smoker')
_checkService(services[0],
"http://www.myopenid.com/server",
Yadis::XRI.make_xri("=!1000"),
'http://smoker.myopenid.com/',
Yadis::XRI.make_xri("=!1000"),
['1.0'],
true,
'=smoker')
_checkService(services[1],
"http://www.livejournal.com/openid/server.bml",
Yadis::XRI.make_xri("=!1000"),
'http://frank.livejournal.com/',
Yadis::XRI.make_xri("=!1000"),
['1.0'],
true,
'=smoker')
end
def test_xriNoCanonicalID
silence_logging {
_, services = OpenID.discover_xri('=smoker*bad')
assert(services.empty?)
}
end
def test_useCanonicalID
# When there is no delegate, the CanonicalID should be used with
# XRI.
endpoint = OpenIDServiceEndpoint.new()
endpoint.claimed_id = Yadis::XRI.make_xri("=!1000")
endpoint.canonical_id = Yadis::XRI.make_xri("=!1000")
assert_equal(endpoint.get_local_id, Yadis::XRI.make_xri("=!1000"))
end
end
class TestXRIDiscoveryIDP < BaseTestDiscovery
include TestDataMixin
def initialize(*args)
super(*args)
@fetcher_class = MockFetcherForXRIProxy
@documents = {'=smoker' => ['application/xrds+xml',
read_data_file('test_discover/yadis_2entries_idp.xml', false)] }
end
def test_xri
_, services = OpenID.discover_xri('=smoker')
assert(!services.empty?, "Expected services, got zero")
assert_equal(services[0].server_url,
"http://www.livejournal.com/openid/server.bml")
end
end
class TestPreferredNamespace < Minitest::Test
def initialize(*args)
super(*args)
@cases = [
[OPENID1_NS, []],
[OPENID1_NS, ['http://jyte.com/']],
[OPENID1_NS, [OPENID_1_0_TYPE]],
[OPENID1_NS, [OPENID_1_1_TYPE]],
[OPENID2_NS, [OPENID_2_0_TYPE]],
[OPENID2_NS, [OPENID_IDP_2_0_TYPE]],
[OPENID2_NS, [OPENID_2_0_TYPE,
OPENID_1_0_TYPE]],
[OPENID2_NS, [OPENID_1_0_TYPE,
OPENID_2_0_TYPE]],
]
end
def test_preferred_namespace
@cases.each { |expected_ns, type_uris|
endpoint = OpenIDServiceEndpoint.new()
endpoint.type_uris = type_uris
actual_ns = endpoint.preferred_namespace()
assert_equal(actual_ns, expected_ns)
}
end
end
class TestIsOPIdentifier < Minitest::Test
def setup
@endpoint = OpenIDServiceEndpoint.new()
end
def test_none
assert(!@endpoint.is_op_identifier())
end
def test_openid1_0
@endpoint.type_uris = [OPENID_1_0_TYPE]
assert(!@endpoint.is_op_identifier())
end
def test_openid1_1
@endpoint.type_uris = [OPENID_1_1_TYPE]
assert(!@endpoint.is_op_identifier())
end
def test_openid2
@endpoint.type_uris = [OPENID_2_0_TYPE]
assert(!@endpoint.is_op_identifier())
end
def test_openid2OP
@endpoint.type_uris = [OPENID_IDP_2_0_TYPE]
assert(@endpoint.is_op_identifier())
end
def test_multipleMissing
@endpoint.type_uris = [OPENID_2_0_TYPE,
OPENID_1_0_TYPE]
assert(!@endpoint.is_op_identifier())
end
def test_multiplePresent
@endpoint.type_uris = [OPENID_2_0_TYPE,
OPENID_1_0_TYPE,
OPENID_IDP_2_0_TYPE]
assert(@endpoint.is_op_identifier())
end
end
class TestFromOPEndpointURL < Minitest::Test
def setup
@op_endpoint_url = 'http://example.com/op/endpoint'
@endpoint = OpenIDServiceEndpoint.from_op_endpoint_url(@op_endpoint_url)
end
def test_isOPEndpoint
assert(@endpoint.is_op_identifier())
end
def test_noIdentifiers
assert_equal(@endpoint.get_local_id, nil)
assert_equal(@endpoint.claimed_id, nil)
end
def test_compatibility
assert(!@endpoint.compatibility_mode())
end
def test_canonical_id
assert_equal(@endpoint.canonical_id, nil)
end
def test_serverURL
assert_equal(@endpoint.server_url, @op_endpoint_url)
end
end
class TestDiscoverFunction < Minitest::Test
def test_discover_function
# XXX these were all different tests in python, but they're
# combined here so I only have to use with_method_overridden
# once.
discoverXRI = Proc.new { |identifier| 'XRI' }
discoverURI = Proc.new { |identifier| 'URI' }
OpenID.extend(OverrideMethodMixin)
OpenID.with_method_overridden(:discover_uri, discoverURI) do
OpenID.with_method_overridden(:discover_xri, discoverXRI) do
assert_equal('URI', OpenID.discover('http://woo!'))
assert_equal('URI', OpenID.discover('not a URL or XRI'))
assert_equal('XRI', OpenID.discover('xri://=something'))
assert_equal('XRI', OpenID.discover('=something'))
end
end
end
end
class TestEndpointSupportsType < Minitest::Test
def setup
@endpoint = OpenIDServiceEndpoint.new()
end
def failUnlessSupportsOnly(*types)
['foo',
OPENID_1_1_TYPE,
OPENID_1_0_TYPE,
OPENID_2_0_TYPE,
OPENID_IDP_2_0_TYPE].each { |t|
if types.member?(t)
assert(@endpoint.supports_type(t),
sprintf("Must support %s", t))
else
assert(!@endpoint.supports_type(t),
sprintf("Shouldn't support %s", t))
end
}
end
def test_supportsNothing
failUnlessSupportsOnly()
end
def test_openid2
@endpoint.type_uris = [OPENID_2_0_TYPE]
failUnlessSupportsOnly(OPENID_2_0_TYPE)
end
def test_openid2provider
@endpoint.type_uris = [OPENID_IDP_2_0_TYPE]
failUnlessSupportsOnly(OPENID_IDP_2_0_TYPE,
OPENID_2_0_TYPE)
end
def test_openid1_0
@endpoint.type_uris = [OPENID_1_0_TYPE]
failUnlessSupportsOnly(OPENID_1_0_TYPE)
end
def test_openid1_1
@endpoint.type_uris = [OPENID_1_1_TYPE]
failUnlessSupportsOnly(OPENID_1_1_TYPE)
end
def test_multiple
@endpoint.type_uris = [OPENID_1_1_TYPE,
OPENID_2_0_TYPE]
failUnlessSupportsOnly(OPENID_1_1_TYPE,
OPENID_2_0_TYPE)
end
def test_multipleWithProvider
@endpoint.type_uris = [OPENID_1_1_TYPE,
OPENID_2_0_TYPE,
OPENID_IDP_2_0_TYPE]
failUnlessSupportsOnly(OPENID_1_1_TYPE,
OPENID_2_0_TYPE,
OPENID_IDP_2_0_TYPE)
end
end
class TestEndpointDisplayIdentifier < Minitest::Test
def test_strip_fragment
@endpoint = OpenIDServiceEndpoint.new()
@endpoint.claimed_id = 'http://recycled.invalid/#123'
assert_equal 'http://recycled.invalid/', @endpoint.display_identifier
end
end
class TestNormalizeURL < Minitest::Test
def test_no_host
assert_raises(DiscoveryFailure) {
OpenID::normalize_url('http:///too-many.invalid/slashes')
}
end
end
end
ruby-openid-2.7.0debian.orig/test/test_urinorm.rb 0000644 0001750 0001750 00000001335 12512544714 021354 0 ustar sbadia sbadia require "minitest/autorun"
require "testutil"
require "openid/urinorm"
class URINormTestCase < Minitest::Test
include OpenID::TestDataMixin
def test_normalize
lines = read_data_file('urinorm.txt')
while lines.length > 0
case_name = lines.shift.strip
actual = lines.shift.strip
expected = lines.shift.strip
lines.shift #=> newline
if expected == 'fail'
begin
OpenID::URINorm.urinorm(actual)
rescue URI::InvalidURIError
assert true
else
raise 'Should have gotten URI error'
end
else
normalized = OpenID::URINorm.urinorm(actual)
assert_equal(expected, normalized, case_name)
end
end
end
end
ruby-openid-2.7.0debian.orig/test/test_discovery_manager.rb 0000644 0001750 0001750 00000017522 12512544714 023367 0 ustar sbadia sbadia require 'minitest/autorun'
require 'openid/consumer'
require 'testutil'
module OpenID
class TestDiscoveredServices < Minitest::Test
def setup
@starting_url = "http://starting.url.com/"
@yadis_url = "http://starting.url.com/xrds"
@services = ["bogus", "not_a_service"]
@disco_services = Consumer::DiscoveredServices.new(@starting_url,
@yadis_url,
@services.dup)
end
def test_next
assert_equal(@disco_services.next, @services[0])
assert_equal(@disco_services.current, @services[0])
assert_equal(@disco_services.next, @services[1])
assert_equal(@disco_services.current, @services[1])
assert_equal(@disco_services.next, nil)
assert_equal(@disco_services.current, nil)
end
def test_for_url
assert(@disco_services.for_url?(@starting_url))
assert(@disco_services.for_url?(@yadis_url))
assert(!@disco_services.for_url?(nil))
assert(!@disco_services.for_url?("invalid"))
end
def test_started
assert(!@disco_services.started?)
@disco_services.next
assert(@disco_services.started?)
@disco_services.next
assert(@disco_services.started?)
@disco_services.next
assert(!@disco_services.started?)
end
def test_empty
assert(Consumer::DiscoveredServices.new(nil, nil, []).empty?)
assert(!@disco_services.empty?)
@disco_services.next
@disco_services.next
assert(@disco_services.started?)
end
end
# I need to be able to test the protected methods; this lets me do
# that.
class PassthroughDiscoveryManager < Consumer::DiscoveryManager
def method_missing(m, *args)
method(m).call(*args)
end
end
class TestDiscoveryManager < Minitest::Test
def setup
session = {}
@session = OpenID::Consumer::Session.new(session, OpenID::Consumer::DiscoveredServices)
@url = "http://unittest.com/"
@key_suffix = "testing"
@yadis_url = "http://unittest.com/xrds"
@manager = PassthroughDiscoveryManager.new(session, @url, @key_suffix)
@key = @manager.session_key
end
def test_construct
# Make sure the default session key suffix is not nil.
m = Consumer::DiscoveryManager.new(nil, nil)
assert(!m.instance_variable_get("@session_key_suffix").nil?)
m = Consumer::DiscoveryManager.new(nil, nil, "override")
assert_equal(m.instance_variable_get("@session_key_suffix"), "override")
end
def test_get_next_service
assert_equal(@session[@key], nil)
next_service = @manager.get_next_service {
[@yadis_url, ["one", "two", "three"]]
}
disco = @session[@key]
assert_equal(disco.current, "one")
assert_equal(next_service, "one")
assert(disco.for_url?(@url))
assert(disco.for_url?(@yadis_url))
# The first two calls to get_next_service should return the
# services in @disco.
assert_equal(@manager.get_next_service, "two")
assert_equal(@manager.get_next_service, "three")
disco = @session[@key]
assert_equal(disco.current, "three")
# The manager is exhausted and should be deleted and a new one
# should be created.
@manager.get_next_service {
[@yadis_url, ["four"]]
}
disco2 = @session[@key]
assert_equal(disco2.current, "four")
# create_manager may return a nil manager, in which case the
# next service should be nil.
@manager.extend(OpenID::InstanceDefExtension)
@manager.instance_def(:create_manager) do |yadis_url, services|
nil
end
result = @manager.get_next_service { |url|
["unused", []]
}
assert_equal(result, nil)
end
def test_cleanup
# With no preexisting manager, cleanup() returns nil.
assert_equal(@manager.cleanup, nil)
# With a manager, it returns the manager's current service.
disco = Consumer::DiscoveredServices.new(@url, @yadis_url, ["one", "two"])
@session[@key] = disco
assert_equal(@manager.cleanup, nil)
assert_equal(@session[@key], nil)
disco.next
@session[@key] = disco
assert_equal(@manager.cleanup, "one")
assert_equal(@session[@key], nil)
# The force parameter should be passed through to get_manager
# and destroy_manager.
force_value = "yo"
testcase = self
m = Consumer::DiscoveredServices.new(nil, nil, ["inner"])
m.next
@manager.extend(OpenID::InstanceDefExtension)
@manager.instance_def(:get_manager) do |force|
testcase.assert_equal(force, force_value)
m
end
@manager.instance_def(:destroy_manager) do |force|
testcase.assert_equal(force, force_value)
end
assert_equal("inner", @manager.cleanup(force_value))
end
def test_get_manager
# get_manager should always return the loaded manager when
# forced.
@session[@key] = "bogus"
assert_equal("bogus", @manager.get_manager(true))
# When not forced, only managers for @url should be returned.
disco = Consumer::DiscoveredServices.new(@url, @yadis_url, ["one"])
@session[@key] = disco
assert_equal(@manager.get_manager, disco)
# Try to get_manager for a manger that doesn't manage @url:
disco2 = Consumer::DiscoveredServices.new("http://not.this.url.com/",
"http://other.yadis.url/", ["one"])
@session[@key] = disco2
assert_equal(@manager.get_manager, nil)
assert_equal(@manager.get_manager(true), disco2)
end
def test_create_manager
assert(@session[@key].nil?)
services = ["created", "manager"]
returned_disco = @manager.create_manager(@yadis_url, services)
stored_disco = @session[@key]
assert_equal(stored_disco, returned_disco)
assert(stored_disco.for_url?(@yadis_url))
assert_equal(stored_disco.next, "created")
# Calling create_manager with a preexisting manager should
# result in StandardError.
assert_raises(StandardError) {
@manager.create_manager(@yadis_url, services)
}
# create_manager should do nothing (and return nil) if given no
# services.
@session[@key] = nil
result = @manager.create_manager(@yadis_url, [])
assert(result.nil?)
assert(@session[@key].nil?)
end
class DestroyCalledException < StandardError; end
def test_destroy_manager
# destroy_manager should remove the manager from the session,
# forcibly if necessary.
valid_disco = Consumer::DiscoveredServices.new(@url, @yadis_url, ["serv"])
invalid_disco = Consumer::DiscoveredServices.new("http://not.mine.com/",
"http://different.url.com/",
["serv"])
@session[@key] = valid_disco
@manager.destroy_manager
assert(@session[@key].nil?)
@session[@key] = invalid_disco
@manager.destroy_manager
assert_equal(@session[@key], invalid_disco)
# Force destruction of manager, no matter which URLs it's for.
@manager.destroy_manager(true)
assert(@session[@key].nil?)
end
def test_session_key
assert(@manager.session_key.end_with?(
@manager.instance_variable_get("@session_key_suffix")))
end
def test_store
thing = "opaque"
assert(@session[@key].nil?)
@manager.store(thing)
assert_equal(@session[@key], thing)
end
def test_load
thing = "opaque"
@session[@key] = thing
assert_equal(@manager.load, thing)
end
def test_destroy!
thing = "opaque"
@manager.store(thing)
assert_equal(@manager.load, thing)
@manager.destroy!
assert(@session[@key].nil?)
assert(@manager.load.nil?)
end
end
end
ruby-openid-2.7.0debian.orig/test/test_responses.rb 0000644 0001750 0001750 00000004153 12512544714 021703 0 ustar sbadia sbadia require "minitest/autorun"
require "openid/consumer/discovery"
require "openid/consumer/responses"
module OpenID
class Consumer
module TestResponses
class TestSuccessResponse < Minitest::Test
def setup
@endpoint = OpenIDServiceEndpoint.new
@endpoint.claimed_id = 'identity_url'
end
def test_extension_response
q = {
'ns.sreg' => 'urn:sreg',
'ns.unittest' => 'urn:unittest',
'unittest.one' => '1',
'unittest.two' => '2',
'sreg.nickname' => 'j3h',
'return_to' => 'return_to',
}
signed_list = q.keys.map { |k| 'openid.' + k }
msg = Message.from_openid_args(q)
resp = SuccessResponse.new(@endpoint, msg, signed_list)
utargs = resp.extension_response('urn:unittest', false)
assert_equal(utargs, {'one' => '1', 'two' => '2'})
sregargs = resp.extension_response('urn:sreg', false)
assert_equal(sregargs, {'nickname' => 'j3h'})
end
def test_extension_response_signed
args = {
'ns.sreg' => 'urn:sreg',
'ns.unittest' => 'urn:unittest',
'unittest.one' => '1',
'unittest.two' => '2',
'sreg.nickname' => 'j3h',
'sreg.dob' => 'yesterday',
'return_to' => 'return_to',
'signed' => 'sreg.nickname,unittest.one,sreg.dob',
}
signed_list = ['openid.sreg.nickname',
'openid.unittest.one',
'openid.sreg.dob',]
msg = Message.from_openid_args(args)
resp = SuccessResponse.new(@endpoint, msg, signed_list)
# All args in this NS are signed, so expect all.
sregargs = resp.extension_response('urn:sreg', true)
assert_equal(sregargs, {'nickname' => 'j3h', 'dob' => 'yesterday'})
# Not all args in this NS are signed, so expect nil when
# asking for them.
utargs = resp.extension_response('urn:unittest', true)
assert_equal(nil, utargs)
end
end
end
end
end
ruby-openid-2.7.0debian.orig/test/test_ax.rb 0000644 0001750 0001750 00000061137 12512544714 020277 0 ustar sbadia sbadia require 'minitest/autorun'
require 'openid/extensions/ax'
require 'openid/message'
require 'openid/consumer/responses'
require 'openid/consumer/discovery'
require 'openid/consumer/checkid_request'
module OpenID
module AX
class BogusAXMessage < AXMessage
@mode = 'bogus'
def get_extension_args
new_args
end
def do_check_mode(args)
check_mode(args)
end
def do_check_mode_new_args
check_mode(new_args)
end
end
class AXMessageTest < Minitest::Test
def setup
@bax = BogusAXMessage.new
end
def test_check_mode
assert_raises(Error) { @bax.do_check_mode({'mode' => 'fetch_request'})}
@bax.do_check_mode({'mode' => @bax.mode})
end
def test_check_mode_new_args
@bax.do_check_mode_new_args
end
end
class AttrInfoTest < Minitest::Test
def test_construct
assert_raises(ArgumentError) { AttrInfo.new }
type_uri = 'uri geller'
ainfo = AttrInfo.new(type_uri)
assert_equal(type_uri, ainfo.type_uri)
assert_equal(1, ainfo.count)
assert_equal(false, ainfo.required)
assert_equal(nil, ainfo.ns_alias)
end
end
class ToTypeURIsTest < Minitest::Test
def setup
@aliases = NamespaceMap.new
end
def test_empty
[nil, ''].each{|empty|
uris = AX.to_type_uris(@aliases, empty)
assert_equal([], uris)
}
end
def test_undefined
assert_raises(IndexError) {
AX.to_type_uris(@aliases, 'http://janrain.com/')
}
end
def test_one
uri = 'http://janrain.com/'
name = 'openid_hackers'
@aliases.add_alias(uri, name)
uris = AX::to_type_uris(@aliases, name)
assert_equal([uri], uris)
end
def test_two
uri1 = 'http://janrain.com/'
name1 = 'openid_hackers'
@aliases.add_alias(uri1, name1)
uri2 = 'http://jyte.com/'
name2 = 'openid_hack'
@aliases.add_alias(uri2, name2)
uris = AX.to_type_uris(@aliases, [name1, name2].join(','))
assert_equal([uri1, uri2], uris)
end
end
class ParseAXValuesTest < Minitest::Test
def ax_values(ax_args, expected_args)
msg = KeyValueMessage.new
msg.parse_extension_args(ax_args)
assert_equal(expected_args, msg.data)
end
def ax_error(ax_args, error)
msg = KeyValueMessage.new
assert_raises(error) {
msg.parse_extension_args(ax_args)
}
end
def test_empty_is_valid
ax_values({}, {})
end
def test_missing_value_for_alias_explodes
ax_error({'type.foo'=>'urn:foo'}, IndexError)
end
def test_count_present_but_not_value
ax_error({'type.foo'=>'urn:foo', 'count.foo' => '1'}, IndexError)
end
def test_invalid_count_value
msg = FetchRequest.new
assert_raises(Error) {
msg.parse_extension_args({'type.foo'=>'urn:foo',
'count.foo' => 'bogus'})
}
end
def test_request_unlimited_values
msg = FetchRequest.new
args = {'mode' => 'fetch_request',
'required' => 'foo',
'type.foo' => 'urn:foo',
'count.foo' => UNLIMITED_VALUES
}
msg.parse_extension_args(args)
foo = msg.attributes[0]
assert_equal(UNLIMITED_VALUES, foo.count)
assert(foo.wants_unlimited_values?)
end
def test_long_alias
# spec says we must support at least 32 character-long aliases
name = 'x' * MINIMUM_SUPPORTED_ALIAS_LENGTH
msg = KeyValueMessage.new
args = {
"type.#{name}" => 'urn:foo',
"count.#{name}" => '1',
"value.#{name}.1" => 'first',
}
msg.parse_extension_args(args)
assert_equal(['first'],msg['urn:foo'])
end
def test_invalid_alias
types = [
KeyValueMessage,
FetchRequest
]
inputs = [
{'type.a.b'=>'urn:foo',
'count.a.b'=>'1'},
{'type.a,b'=>'urn:foo',
'count.a,b'=>'1'},
]
types.each{|t|
inputs.each{|input|
msg = t.new
assert_raises(Error) {msg.parse_extension_args(input)}
}
}
end
def test_count_present_and_is_zero
ax_values(
{'type.foo'=>'urn:foo',
'count.foo'=>'0',
},
{'urn:foo'=>[]}
)
end
def test_singleton_empty
ax_values(
{'type.foo'=>'urn:foo',
'value.foo'=>'',
},
{'urn:foo'=>[]}
)
end
def test_double_alias
ax_error(
{'type.foo'=>'urn:foo',
'value.foo'=>'',
'type.bar'=>'urn:foo',
'value.bar'=>'',
},
IndexError
)
end
def test_double_singleton
ax_values(
{'type.foo'=>'urn:foo',
'value.foo'=>'',
'type.bar'=>'urn:bar',
'value.bar'=>'',
},
{'urn:foo'=>[],'urn:bar'=>[]}
)
end
def singleton_value
ax_values(
{'type.foo'=>'urn:foo',
'value.foo'=>'something',
},
{'urn:foo'=>['something']}
)
end
end
class FetchRequestTest < Minitest::Test
def setup
@msg = FetchRequest.new
@type_a = 'http://janrain.example.com/a'
@name_a = 'a'
end
def test_mode
assert_equal('fetch_request', @msg.mode)
end
def test_construct
assert_equal({}, @msg.requested_attributes)
assert_equal(nil, @msg.update_url)
msg = FetchRequest.new('hailstorm')
assert_equal({}, msg.requested_attributes)
assert_equal('hailstorm', msg.update_url)
end
def test_add
uri = 'mud://puddle'
assert(! @msg.member?(uri))
a = AttrInfo.new(uri)
@msg.add(a)
assert(@msg.member?(uri))
end
def test_add_twice
uri = 'its://raining'
a = AttrInfo.new(uri)
@msg.add(a)
assert_raises(IndexError) {@msg.add(a)}
end
def do_extension_args(expected_args)
expected_args['mode'] = @msg.mode
assert_equal(expected_args, @msg.get_extension_args)
end
def test_get_extension_args_empty
do_extension_args({})
end
def test_get_extension_args_no_alias
a = AttrInfo.new('foo://bar')
@msg.add(a)
ax_args = @msg.get_extension_args
ax_args.each{|k,v|
if v == a.type_uri and k.index('type.') == 0
@name = k[5..-1]
break
end
}
do_extension_args({'type.'+@name => a.type_uri,
'if_available' => @name})
end
def test_get_extension_args_alias_if_available
a = AttrInfo.new('type://of.transportation',
'transport')
@msg.add(a)
do_extension_args({'type.'+a.ns_alias => a.type_uri,
'if_available' => a.ns_alias})
end
def test_get_extension_args_alias_req
a = AttrInfo.new('type://of.transportation',
'transport',
true)
@msg.add(a)
do_extension_args({'type.'+a.ns_alias => a.type_uri,
'required' => a.ns_alias})
end
def test_get_required_attrs_empty
assert_equal([], @msg.get_required_attrs)
end
def test_parse_extension_args_extra_type
args = {
'mode' => 'fetch_request',
'type.' + @name_a => @type_a
}
assert_raises(Error) {@msg.parse_extension_args(args)}
end
def test_parse_extension_args
args = {
'mode' => 'fetch_request',
'type.' + @name_a => @type_a,
'if_available' => @name_a
}
@msg.parse_extension_args(args)
assert(@msg.member?(@type_a) )
assert_equal([@type_a], @msg.requested_types)
ai = @msg.requested_attributes[@type_a]
assert(ai.is_a?(AttrInfo))
assert(!ai.required)
assert_equal(@type_a, ai.type_uri)
assert_equal(@name_a, ai.ns_alias)
assert_equal([ai], @msg.attributes)
end
def test_extension_args_idempotent
args = {
'mode' => 'fetch_request',
'type.' + @name_a => @type_a,
'if_available' => @name_a
}
@msg.parse_extension_args(args)
assert_equal(args, @msg.get_extension_args)
assert(!@msg.requested_attributes[@type_a].required)
end
def test_extension_args_idempotent_count_required
args = {
'mode' => 'fetch_request',
'type.' + @name_a => @type_a,
'count.' + @name_a => '2',
'required' => @name_a
}
@msg.parse_extension_args(args)
assert_equal(args, @msg.get_extension_args)
assert(@msg.requested_attributes[@type_a].required)
end
def test_extension_args_count1
args = {
'mode' => 'fetch_request',
'type.' + @name_a => @type_a,
'count.' + @name_a => '1',
'if_available' => @name_a
}
norm_args = {
'mode' => 'fetch_request',
'type.' + @name_a => @type_a,
'if_available' => @name_a
}
@msg.parse_extension_args(args)
assert_equal(norm_args, @msg.get_extension_args)
end
def test_from_openid_request_no_ax
message = Message.new
openid_req = Server::OpenIDRequest.new
openid_req.message = message
ax_req = FetchRequest.from_openid_request(openid_req)
assert(ax_req.nil?)
end
def test_from_openid_request_wrong_ax_mode
uri = 'http://under.the.sea/'
name = 'ext0'
value = 'snarfblat'
message = OpenID::Message.from_openid_args({
'mode' => 'id_res',
'ns' => OPENID2_NS,
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://example.com/realm/update_path',
'ax.mode' => 'store_request',
'ax.type.' + name => uri,
'ax.count.' + name => '1',
'ax.value.' + name + '.1' => value
})
openid_req = Server::OpenIDRequest.new
openid_req.message = message
ax_req = FetchRequest.from_openid_request(openid_req)
assert(ax_req.nil?)
end
def test_openid_update_url_verification_error
openid_req_msg = Message.from_openid_args({
'mode' => 'checkid_setup',
'ns' => OPENID2_NS,
'realm' => 'http://example.com/realm',
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://different.site/path',
'ax.mode' => 'fetch_request',
})
openid_req = Server::OpenIDRequest.new
openid_req.message = openid_req_msg
assert_raises(Error) {
FetchRequest.from_openid_request(openid_req)
}
end
def test_openid_no_realm
openid_req_msg = Message.from_openid_args({
'mode' => 'checkid_setup',
'ns' => OPENID2_NS,
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://different.site/path',
'ax.mode' => 'fetch_request',
})
openid_req = Server::OpenIDRequest.new
openid_req.message = openid_req_msg
assert_raises(Error) {
FetchRequest.from_openid_request(openid_req)
}
end
def test_openid_update_url_verification_success
openid_req_msg = Message.from_openid_args({
'mode' => 'checkid_setup',
'ns' => OPENID2_NS,
'realm' => 'http://example.com/realm',
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://example.com/realm/update_path',
'ax.mode' => 'fetch_request',
})
openid_req = Server::OpenIDRequest.new
openid_req.message = openid_req_msg
fr = FetchRequest.from_openid_request(openid_req)
assert(fr.is_a?(FetchRequest))
end
def test_openid_update_url_verification_success_return_to
openid_req_msg = Message.from_openid_args({
'mode' => 'checkid_setup',
'ns' => OPENID2_NS,
'return_to' => 'http://example.com/realm',
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://example.com/realm/update_path',
'ax.mode' => 'fetch_request',
})
openid_req = Server::OpenIDRequest.new
openid_req.message = openid_req_msg
fr = FetchRequest.from_openid_request(openid_req)
assert(fr.is_a?(FetchRequest))
end
def test_add_extension
openid_req_msg = Message.from_openid_args({
'mode' => 'checkid_setup',
'ns' => OPENID2_NS,
'return_to' => 'http://example.com/realm',
})
e = OpenID::OpenIDServiceEndpoint.new
openid_req = Consumer::CheckIDRequest.new(nil, e)
openid_req.message = openid_req_msg
fr = FetchRequest.new
fr.add(AttrInfo.new("urn:bogus"))
openid_req.add_extension(fr)
expected = {
'mode' => 'fetch_request',
'if_available' => 'ext0',
'type.ext0' => 'urn:bogus',
}
expected.each { |k,v|
assert(openid_req.message.get_arg(AXMessage::NS_URI, k) == v)
}
end
end
class FetchResponseTest < Minitest::Test
def setup
@msg = FetchResponse.new
@value_a = 'commodity'
@value_a1 = 'value2'
@type_a = 'http://blood.transfusion/'
@name_a = 'george'
@request_update_url = 'http://some.url.that.is.awesome/'
end
def test_construct
assert_equal(nil, @msg.update_url)
assert_equal({}, @msg.data)
end
def test_get_extension_args_empty
eargs = {
'mode' => 'fetch_response'
}
assert_equal(eargs, @msg.get_extension_args)
end
def test_get_extension_args_empty_request
eargs = {
'mode' => 'fetch_response'
}
req = FetchRequest.new
assert_equal(eargs, @msg.get_extension_args(req))
end
def test_get_extension_args_empty_request_some
uri = 'http://not.found/'
name = 'ext0'
eargs = {
'mode' => 'fetch_response',
'type.' + name => uri,
'count.' + name => '0'
}
req = FetchRequest.new
req.add(AttrInfo.new(uri))
assert_equal(eargs, @msg.get_extension_args(req))
end
def test_update_url_in_response
uri = 'http://not.found/'
name = 'ext0'
eargs = {
'mode' => 'fetch_response',
'update_url' => @request_update_url,
'type.' + name => uri,
'count.' + name => '0'
}
req = FetchRequest.new(@request_update_url)
req.add(AttrInfo.new(uri))
assert_equal(eargs, @msg.get_extension_args(req))
end
def test_get_extension_args_single_value_response
# Single values do NOT have a count, and
# do not use the array extension
eargs = {
'mode' => 'fetch_response',
'type.' + @name_a => @type_a,
'value.' + @name_a => @value_a
}
req = FetchRequest.new
req.add(AttrInfo.new(@type_a, @name_a))
@msg.add_value(@type_a, @value_a)
assert_equal(eargs, @msg.get_extension_args(req))
end
def test_get_extension_args_array_value_response
# Multiple array values add the count, and array index
# to each value
eargs = {
'mode' => 'fetch_response',
'type.' + @name_a => @type_a,
'value.' + @name_a + ".1" => @value_a,
'value.' + @name_a + ".2" => @value_a1,
'count.' + @name_a => '2'
}
req = FetchRequest.new
# Specify that this URI should have a count of 2
req.add(AttrInfo.new(@type_a, @name_a, true, 2))
# Push both values onto the array
@msg.add_value(@type_a, @value_a)
@msg.add_value(@type_a, @value_a1)
assert_equal(eargs, @msg.get_extension_args(req))
end
def test_get_extension_args_some_not_request
req = FetchRequest.new
@msg.add_value(@type_a, @value_a)
assert_raises(IndexError) {@msg.get_extension_args(req)}
end
def test_get_single_success
@msg.add_value(@type_a, @value_a)
assert_equal(@value_a, @msg.get_single(@type_a))
end
def test_get_single_none
assert_equal(nil, @msg.get_single(@type_a))
end
def test_get_single_extra
@msg.set_values(@type_a, ['x', 'y'])
assert_raises(Error) { @msg.get_single(@type_a) }
end
def test_from_unsigned_success_response
uri = 'http://under.the.sea/'
name = 'ext0'
value = 'snarfblat'
m = OpenID::Message.from_openid_args({
'mode' => 'id_res',
'ns' => OPENID2_NS,
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://example.com/realm/update_path',
'ax.mode' => 'fetch_response',
'ax.type.' + name => uri,
'ax.count.' + name => '1',
'ax.value.' + name + '.1' => value
})
e = OpenID::OpenIDServiceEndpoint.new()
resp = OpenID::Consumer::SuccessResponse.new(e, m, [])
ax_resp = FetchResponse.from_success_response(resp, false)
values = ax_resp[uri]
assert_equal(values, [value])
end
def test_from_signed_success_response
uri = 'http://under.the.sea/'
name = 'ext0'
value = 'snarfblat'
oid_fields = {
'mode' => 'id_res',
'ns' => OPENID2_NS,
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://example.com/realm/update_path',
'ax.mode' => 'fetch_response',
'ax.type.' + name => uri,
'ax.count.' + name => '1',
'ax.value.' + name + '.1' => value
}
signed_fields = oid_fields.keys.map{|f| "openid.#{f}"}
m = OpenID::Message.from_openid_args(oid_fields)
e = OpenID::OpenIDServiceEndpoint.new()
resp = OpenID::Consumer::SuccessResponse.new(e, m, signed_fields)
ax_resp = FetchResponse.from_success_response(resp, true)
values = ax_resp[uri]
assert_equal(values, [value])
end
def test_from_signed_success_response_with_unsigned_attributes
uri = 'http://under.the.sea/'
name = 'ext0'
value = 'snarfblat'
m = OpenID::Message.from_openid_args({
'mode' => 'id_res',
'ns' => OPENID2_NS,
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://example.com/realm/update_path',
'ax.mode' => 'fetch_response',
'ax.type.' + name => uri,
'ax.count.' + name => '1',
'ax.value.' + name + '.1' => value
})
e = OpenID::OpenIDServiceEndpoint.new()
resp = OpenID::Consumer::SuccessResponse.new(e, m, [])
assert_nil FetchResponse.from_success_response(resp, true)
end
def test_from_empty_success_response
e = OpenID::OpenIDServiceEndpoint.new()
m = OpenID::Message.from_openid_args({'mode' => 'id_res'})
resp = OpenID::Consumer::SuccessResponse.new(e, m, [])
ax_resp = FetchResponse.from_success_response(resp)
assert(ax_resp.nil?)
end
end
class StoreRequestTest < Minitest::Test
def setup
@msg = StoreRequest.new
@type_a = 'http://oranges.are.for/'
@name_a = 'juggling'
end
def test_construct
assert_equal({}, @msg.data)
end
def test_get_extension_args_empty
eargs = {
'mode' => 'store_request'
}
assert_equal(eargs, @msg.get_extension_args)
end
def test_from_openid_request_wrong_ax_mode
uri = 'http://under.the.sea/'
name = 'ext0'
value = 'snarfblat'
message = OpenID::Message.from_openid_args({
'mode' => 'id_res',
'ns' => OPENID2_NS,
'ns.ax' => AXMessage::NS_URI,
'ax.update_url' => 'http://example.com/realm/update_path',
'ax.mode' => 'fetch_request',
'ax.type.' + name => uri,
'ax.count.' + name => '1',
'ax.value.' + name + '.1' => value
})
openid_req = Server::OpenIDRequest.new
openid_req.message = message
ax_req = StoreRequest.from_openid_request(openid_req)
assert(ax_req.nil?)
end
def test_get_extension_args_nonempty
@msg.set_values(@type_a, ['foo','bar'])
aliases = NamespaceMap.new
aliases.add_alias(@type_a, @name_a)
eargs = {
'mode' => 'store_request',
'type.' + @name_a => @type_a,
'value.' + @name_a + '.1' => 'foo',
'value.' + @name_a + '.2' => 'bar',
'count.' + @name_a => '2'
}
assert_equal(eargs, @msg.get_extension_args(aliases))
end
end
class StoreResponseTest < Minitest::Test
def test_success
msg = StoreResponse.new
assert(msg.succeeded?)
assert(!msg.error_message)
assert_equal({'mode' => 'store_response_success'},
msg.get_extension_args)
end
def test_fail_nomsg
msg = StoreResponse.new(false)
assert(! msg.succeeded? )
assert(! msg.error_message )
assert_equal({'mode' => 'store_response_failure'},
msg.get_extension_args)
end
def test_fail_msg
reason = "because I said so"
msg = StoreResponse.new(false, reason)
assert(! msg.succeeded? )
assert_equal(reason, msg.error_message)
assert_equal({'mode' => 'store_response_failure', 'error' => reason},
msg.get_extension_args)
end
end
end
end
ruby-openid-2.7.0debian.orig/test/test_checkid_request.rb 0000644 0001750 0001750 00000022400 12512544714 023017 0 ustar sbadia sbadia require "minitest/autorun"
require "openid/consumer/checkid_request"
require "openid/message"
require "testutil"
require "util"
module OpenID
class Consumer
class CheckIDRequest
class DummyEndpoint
attr_accessor :preferred_namespace, :local_id, :server_url,
:is_op_identifier, :claimed_id
def initialize
@preferred_namespace = nil
@local_id = nil
@server_url = nil
@is_op_identifier = false
end
def get_local_id
@local_id
end
def compatibility_mode
@preferred_namespace == OPENID1_NS
end
end
module CheckIDTestMixin
include TestUtil
def setup
@endpoint = DummyEndpoint.new
@endpoint.local_id = 'http://server.unittest/joe'
@endpoint.claimed_id = 'http://joe.vanity.example/'
@endpoint.server_url = 'http://server.unittest/'
@endpoint.preferred_namespace = preferred_namespace
@realm = 'http://example/'
@return_to = 'http://example/return/'
@assoc = GoodAssoc.new
@checkid_req = CheckIDRequest.new(@assoc, @endpoint)
end
def assert_has_identifiers(msg, local_id, claimed_id)
assert_openid_value_equal(msg, 'identity', local_id)
assert_openid_value_equal(msg, 'claimed_id', claimed_id)
end
def assert_openid_key_exists(msg, key)
assert(msg.get_arg(OPENID_NS, key),
"#{key} not present in #{msg.get_args(OPENID_NS).inspect}")
end
def assert_openid_key_absent(msg, key)
assert(msg.get_arg(OPENID_NS, key).nil?)
end
def assert_openid_value_equal(msg, key, expected)
actual = msg.get_arg(OPENID_NS, key, NO_DEFAULT)
error_text = ("Expected #{expected.inspect} for openid.#{key} "\
"but got #{actual.inspect}: #{msg.inspect}")
assert_equal(expected, actual, error_text)
end
def assert_anonymous(msg)
['claimed_id', 'identity'].each do |key|
assert_openid_key_absent(msg, key)
end
end
def assert_has_required_fields(msg)
internal_message = @checkid_req.instance_variable_get(:@message)
assert_equal(preferred_namespace,
internal_message.get_openid_namespace)
assert_equal(preferred_namespace, msg.get_openid_namespace)
assert_openid_value_equal(msg, 'mode', expected_mode)
# Implement these in subclasses because they depend on
# protocol differences!
assert_has_realm(msg)
assert_identifiers_present(msg)
end
# TESTS
def test_check_no_assoc_handle
@checkid_req.instance_variable_set('@assoc', nil)
msg = assert_log_matches("Generated checkid") {
@checkid_req.get_message(@realm, @return_to, immediate)
}
assert_openid_key_absent(msg, 'assoc_handle')
end
def test_add_extension_arg
@checkid_req.add_extension_arg('bag:', 'color', 'brown')
@checkid_req.add_extension_arg('bag:', 'material', 'paper')
assert(@checkid_req.message.namespaces.member?('bag:'))
assert_equal(@checkid_req.message.get_args('bag:'),
{'color' => 'brown', 'material' => 'paper'})
msg = assert_log_matches("Generated checkid") {
@checkid_req.get_message(@realm, @return_to, immediate)
}
# XXX: this depends on the way that Message assigns
# namespaces. Really it doesn't care that it has alias "0",
# but that is tested anyway
post_args = msg.to_post_args()
assert_equal('brown', post_args['openid.ext0.color'])
assert_equal('paper', post_args['openid.ext0.material'])
end
def test_standard
msg = assert_log_matches('Generated checkid') {
@checkid_req.get_message(@realm, @return_to, immediate)
}
assert_has_identifiers(msg, @endpoint.local_id, @endpoint.claimed_id)
end
def test_send_redirect?
silence_logging {
url = @checkid_req.redirect_url(@realm, @return_to, immediate)
assert(url.length < OPENID1_URL_LIMIT)
assert(@checkid_req.send_redirect?(@realm, @return_to, immediate))
@return_to << '/foo' * 1000
url = @checkid_req.redirect_url(@realm, @return_to, immediate)
assert(url.length > OPENID1_URL_LIMIT)
actual = @checkid_req.send_redirect?(@realm, @return_to, immediate)
expected = preferred_namespace != OPENID2_NS
assert_equal(expected, actual)
}
end
end
class TestCheckIDRequestOpenID2 < Minitest::Test
include CheckIDTestMixin
def immediate
false
end
def expected_mode
'checkid_setup'
end
def preferred_namespace
OPENID2_NS
end
# check presence of proper realm key and absence of the wrong
# one.
def assert_has_realm(msg)
assert_openid_value_equal(msg, 'realm', @realm)
assert_openid_key_absent(msg, 'trust_root')
end
def assert_identifiers_present(msg)
identity_present = msg.has_key?(OPENID_NS, 'identity')
claimed_present = msg.has_key?(OPENID_NS, 'claimed_id')
assert_equal(claimed_present, identity_present)
end
# OpenID Checkid_Requests should be able to set 'anonymous' to true.
def test_set_anonymous_works_for_openid2
assert(@checkid_req.message.is_openid2)
@checkid_req.anonymous = true
@checkid_req.anonymous = false
end
def test_user_anonymous_ignores_identfier
@checkid_req.anonymous = true
msg = assert_log_matches('Generated checkid') {
@checkid_req.get_message(@realm, @return_to, immediate)
}
assert_has_required_fields(msg)
assert_anonymous(msg)
end
def test_op_anonymous_ignores_identifier
@endpoint.is_op_identifier = true
@checkid_req.anonymous = true
msg = assert_log_matches('Generated checkid') {
@checkid_req.get_message(@realm, @return_to, immediate)
}
assert_has_required_fields(msg)
assert_anonymous(msg)
end
def test_op_identifier_sends_identifier_select
@endpoint.is_op_identifier = true
msg = assert_log_matches('Generated checkid') {
@checkid_req.get_message(@realm, @return_to, immediate)
}
assert_has_required_fields(msg)
assert_has_identifiers(msg, IDENTIFIER_SELECT, IDENTIFIER_SELECT)
end
def test_no_assoc_handle
msg = assert_log_matches("Generated checkid") {
@checkid_req.get_message(@realm, @return_to, immediate)
}
assert_openid_key_absent(msg, 'assoc_handle')
end
end
class TestCheckIDRequestOpenID1 < Minitest::Test
include CheckIDTestMixin
def immediate
false
end
def preferred_namespace
OPENID1_NS
end
def expected_mode
'checkid_setup'
end
# Make sure claimed_is is *absent* in request.
def assert_has_identifiers(msg, op_specific_id, claimed_id)
assert_openid_value_equal(msg, 'identity', op_specific_id)
assert_openid_key_absent(msg, 'claimed_id')
end
def assert_identifiers_present(msg)
assert_openid_key_absent(msg, 'claimed_id')
assert(msg.has_key?(OPENID_NS, 'identity'))
end
# check presence of proper realm key and absence of the wrong
# one.
def assert_has_realm(msg)
assert_openid_value_equal(msg, 'trust_root', @realm)
assert_openid_key_absent(msg, 'realm')
end
# TESTS
# OpenID 1 requests MUST NOT be able to set anonymous to true
def test_set_anonymous_fails_for_openid1
assert(@checkid_req.message.is_openid1)
assert_raises(ArgumentError) {
@checkid_req.anonymous = true
}
@checkid_req.anonymous = false
end
# Identfier select SHOULD NOT be sent, but this pathway is in
# here in case some special discovery stuff is done to trigger
# it with OpenID 1. If it is triggered, it will send
# identifier_select just like OpenID 2.
def test_identifier_select
@endpoint.is_op_identifier = true
msg = assert_log_matches('Generated checkid') {
@checkid_req.get_message(@realm, @return_to, immediate)
}
assert_has_required_fields(msg)
assert_equal(IDENTIFIER_SELECT,
msg.get_arg(OPENID1_NS, 'identity'))
end
end
class TestCheckIDRequestOpenID1Immediate < TestCheckIDRequestOpenID1
def immediate
true
end
def expected_mode
'checkid_immediate'
end
end
class TestCheckid_RequestOpenID2Immediate < TestCheckIDRequestOpenID2
def immediate
true
end
def expected_mode
'checkid_immediate'
end
end
end
end
end
ruby-openid-2.7.0debian.orig/test/test_association.rb 0000644 0001750 0001750 00000022006 12512544714 022173 0 ustar sbadia sbadia require "minitest/autorun"
require "openid/association"
require "openid/protocolerror"
module OpenID
class AssociationTestCase < Minitest::Test
def setup
# Use this funny way of getting a time so that it does not have
# fractional seconds, and so can be serialized exactly using our
# standard code.
issued = Time.at(Time.now.to_i)
lifetime = 600
@assoc = Association.new('handle', 'secret', issued,
lifetime, 'HMAC-SHA1')
end
def test_round_trip
assoc2 = Association.deserialize(@assoc.serialize())
[:handle, :secret, :lifetime, :assoc_type].each do |attr|
assert_equal(@assoc.send(attr), assoc2.send(attr))
end
end
def test_deserialize_failure
field_list = Util.kv_to_seq(@assoc.serialize)
kv = Util.seq_to_kv(field_list + [['monkeys', 'funny']])
assert_raises(ProtocolError) {
Association.deserialize(kv)
}
bad_version_list = field_list.dup
bad_version_list[0] = ['version', 'moon']
bad_version_kv = Util.seq_to_kv(bad_version_list)
assert_raises(ProtocolError) {
Association.deserialize(bad_version_kv)
}
end
def test_serialization_identity
assoc2 = Association.deserialize(@assoc.serialize)
assert_equal(@assoc, assoc2)
end
def test_expires_in
# Allow one second of slop
assert(@assoc.expires_in.between?(599,600))
assert(@assoc.expires_in(Time.now.to_i).between?(599,600))
assert_equal(0,@assoc.expires_in(Time.now.to_i + 10000),"negative expires_in")
end
def test_from_expires_in
start_time = Time.now
expires_in = @assoc.expires_in
assoc = Association.from_expires_in(expires_in,
@assoc.handle,
@assoc.secret,
@assoc.assoc_type)
# Allow one second of slop here for code execution time
assert_in_delta(1, assoc.expires_in, @assoc.expires_in)
[:handle, :secret, :assoc_type].each do |attr|
assert_equal(@assoc.send(attr), assoc.send(attr))
end
# Make sure the issued time is near the start
assert(assoc.issued >= start_time)
assert_in_delta(1, assoc.issued.to_f, start_time.to_f)
end
def test_sign_sha1
pairs = [['key1', 'value1'],
['key2', 'value2']]
[['HMAC-SHA256', "\xfd\xaa\xfe;\xac\xfc*\x988\xad\x05d6-\xeaVy\xd5\xa5Z.<\xa9\xed\x18\x82\\$\x95x\x1c&"],
['HMAC-SHA1', "\xe0\x1bv\x04\xf1G\xc0\xbb\x7f\x9a\x8b\xe9\xbc\xee}\\\xe5\xbb7*"],
].each do |assoc_type, expected|
assoc = Association.from_expires_in(3600, "handle", 'very_secret', assoc_type)
sig = assoc.sign(pairs)
assert_equal(expected.force_encoding("UTF-8"), sig.force_encoding("UTF-8"))
m = Message.new(OPENID2_NS)
pairs.each { |k, v|
m.set_arg(OPENID_NS, k, v)
}
m.set_arg(BARE_NS, "not_an_openid_arg", "bogus")
signed_m = assoc.sign_message(m)
assert(signed_m.has_key?(OPENID_NS, 'sig'))
assert_equal(signed_m.get_arg(OPENID_NS, 'signed'),
'assoc_handle,key1,key2,ns,signed')
end
end
def test_sign_message_with_sig
assoc = Association.from_expires_in(3600, "handle", "very_secret",
"HMAC-SHA1")
m = Message.new(OPENID2_NS)
m.set_arg(OPENID_NS, 'sig', 'noise')
assert_raises(ArgumentError) {
assoc.sign_message(m)
}
end
def test_sign_message_with_signed
assoc = Association.from_expires_in(3600, "handle", "very_secret",
"HMAC-SHA1")
m = Message.new(OPENID2_NS)
m.set_arg(OPENID_NS, 'signed', 'fields')
assert_raises(ArgumentError) {
assoc.sign_message(m)
}
end
def test_sign_different_assoc_handle
assoc = Association.from_expires_in(3600, "handle", "very_secret",
"HMAC-SHA1")
m = Message.new(OPENID2_NS)
m.set_arg(OPENID_NS, 'assoc_handle', 'different')
assert_raises(ArgumentError) {
assoc.sign_message(m)
}
end
def test_sign_bad_assoc_type
@assoc.instance_eval { @assoc_type = 'Cookies' }
assert_raises(ProtocolError) {
@assoc.sign([])
}
end
def test_make_pairs
msg = Message.new(OPENID2_NS)
msg.update_args(OPENID2_NS, {
'mode' => 'id_res',
'identifier' => '=example',
'signed' => 'identifier,mode',
'sig' => 'cephalopod',
})
msg.update_args(BARE_NS, {'xey' => 'value'})
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
"HMAC-SHA1")
pairs = assoc.make_pairs(msg)
assert_equal([['identifier', '=example'],
['mode', 'id_res']], pairs)
end
def test_check_message_signature_no_signed
m = Message.new(OPENID2_NS)
m.update_args(OPENID2_NS, {'mode' => 'id_res',
'identifier' => '=example',
'sig' => 'coyote',
})
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
"HMAC-SHA1")
assert_raises(ProtocolError) {
assoc.check_message_signature(m)
}
end
def test_check_message_signature_no_sig
m = Message.new(OPENID2_NS)
m.update_args(OPENID2_NS, {'mode' => 'id_res',
'identifier' => '=example',
'signed' => 'mode',
})
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
"HMAC-SHA1")
assert_raises(ProtocolError) {
assoc.check_message_signature(m)
}
end
def test_check_message_signature_bad_sig
m = Message.new(OPENID2_NS)
m.update_args(OPENID2_NS, {'mode' => 'id_res',
'identifier' => '=example',
'signed' => 'mode',
'sig' => Util.to_base64('coyote'),
})
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
"HMAC-SHA1")
assert(!assoc.check_message_signature(m))
end
def test_check_message_signature_good_sig
m = Message.new(OPENID2_NS)
m.update_args(OPENID2_NS, {'mode' => 'id_res',
'identifier' => '=example',
'signed' => 'mode',
'sig' => Util.to_base64('coyote'),
})
assoc = Association.from_expires_in(3600, '{sha1}', 'very_secret',
"HMAC-SHA1")
class << assoc
# Override sign, because it's already tested elsewhere
def sign(pairs)
"coyote"
end
end
assert(assoc.check_message_signature(m))
end
end
class AssociationNegotiatorTestCase < Minitest::Test
def assert_equal_under(item1, item2)
val1 = yield(item1)
val2 = yield(item2)
assert_equal(val1, val2)
end
def test_copy
neg = AssociationNegotiator.new([['HMAC-SHA1', 'DH-SHA1']])
neg2 = neg.copy
assert_equal_under(neg, neg2) {|n| n.instance_eval{@allowed_types} }
assert(neg.object_id != neg2.object_id)
end
def test_add_allowed
neg = AssociationNegotiator.new([])
assert(!neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
assert(!neg.allowed?('HMAC-SHA1', 'no-encryption'))
assert(!neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
neg.add_allowed_type('HMAC-SHA1')
assert(neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
assert(neg.allowed?('HMAC-SHA1', 'no-encryption'))
assert(!neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
neg.add_allowed_type('HMAC-SHA256', 'DH-SHA256')
assert(neg.allowed?('HMAC-SHA1', 'DH-SHA1'))
assert(neg.allowed?('HMAC-SHA1', 'no-encryption'))
assert(neg.allowed?('HMAC-SHA256', 'DH-SHA256'))
assert(!neg.allowed?('HMAC-SHA256', 'no-encryption'))
assert_equal(neg.get_allowed_type, ['HMAC-SHA1', 'DH-SHA1'])
end
def test_bad_assoc_type
assert_raises(ProtocolError) {
AssociationNegotiator.new([['OMG', 'Ponies']])
}
end
def test_bad_session_type
assert_raises(ProtocolError) {
AssociationNegotiator.new([['HMAC-SHA1', 'OMG-Ponies']])
}
end
def test_default_negotiator
assert_equal(DefaultNegotiator.get_allowed_type,
['HMAC-SHA1', 'DH-SHA1'])
assert(DefaultNegotiator.allowed?('HMAC-SHA256', 'no-encryption'))
end
def test_encrypted_negotiator
assert_equal(EncryptedNegotiator.get_allowed_type,
['HMAC-SHA1', 'DH-SHA1'])
assert(!EncryptedNegotiator.allowed?('HMAC-SHA256', 'no-encryption'))
end
end
end
ruby-openid-2.7.0debian.orig/test/test_idres.rb 0000644 0001750 0001750 00000100564 12512544714 020773 0 ustar sbadia sbadia require "minitest/autorun"
require "testutil"
require "util"
require "openid/consumer/idres"
require "openid/protocolerror"
require "openid/store/memory"
require "openid/store/nonce"
module OpenID
class Consumer
class IdResHandler
# Subclass of IdResHandler that doesn't do verification upon
# construction. All of the tests call this, except for the ones
# explicitly for id_res.
class IdResHandler < OpenID::Consumer::IdResHandler
def id_res
end
end
class CheckForFieldsTest < Minitest::Test
include ProtocolErrorMixin
BASE_FIELDS = ['return_to', 'assoc_handle', 'sig', 'signed']
OPENID2_FIELDS = BASE_FIELDS + ['op_endpoint']
OPENID1_FIELDS = BASE_FIELDS + ['identity']
OPENID1_SIGNED = ['return_to', 'identity']
OPENID2_SIGNED =
OPENID1_SIGNED + ['response_nonce', 'claimed_id', 'assoc_handle',
'op_endpoint']
def mkMsg(ns, fields, signed_fields)
msg = Message.new(ns)
fields.each do |field|
msg.set_arg(OPENID_NS, field, "don't care")
end
if fields.member?('signed')
msg.set_arg(OPENID_NS, 'signed', signed_fields.join(','))
end
msg
end
1.times do # so as not to bleed into the outer namespace
n = 0
[[],
['foo'],
['bar', 'baz'],
].each do |signed_fields|
test = lambda do
msg = mkMsg(OPENID2_NS, OPENID2_FIELDS, signed_fields)
idres = IdResHandler.new(msg, nil)
assert_equal(signed_fields, idres.send(:signed_list))
# Do it again to make sure logic for caching is correct
assert_equal(signed_fields, idres.send(:signed_list))
end
define_method("test_signed_list_#{n += 1}", test)
end
end
# test all missing fields for OpenID 1 and 2
1.times do
[["openid1", OPENID1_NS, OPENID1_FIELDS],
["openid1", OPENID11_NS, OPENID1_FIELDS],
["openid2", OPENID2_NS, OPENID2_FIELDS],
].each_with_index do |(ver, ns, all_fields), i|
all_fields.each do |field|
test = lambda do
fields = all_fields.dup
fields.delete(field)
msg = mkMsg(ns, fields, [])
idres = IdResHandler.new(msg, nil)
assert_protocol_error("Missing required field #{field}") {
idres.send(:check_for_fields)
}
end
define_method("test_#{i}_#{ver}_check_missing_#{field}", test)
end
end
end
# Test all missing signed for OpenID 1 and 2
1.times do
[["openid1", OPENID1_NS, OPENID1_FIELDS, OPENID1_SIGNED],
["openid1", OPENID11_NS, OPENID1_FIELDS, OPENID1_SIGNED],
["openid2", OPENID2_NS, OPENID2_FIELDS, OPENID2_SIGNED],
].each_with_index do |(ver, ns, all_fields, signed_fields), i|
signed_fields.each do |signed_field|
test = lambda do
fields = signed_fields.dup
fields.delete(signed_field)
msg = mkMsg(ns, all_fields, fields)
# Make sure the signed field is actually in the request
msg.set_arg(OPENID_NS, signed_field, "don't care")
idres = IdResHandler.new(msg, nil)
assert_protocol_error("#{signed_field.inspect} not signed") {
idres.send(:check_for_fields)
}
end
define_method("test_#{i}_#{ver}_check_missing_signed_#{signed_field}", test)
end
end
end
def test_112
args = {'openid.assoc_handle' => 'fa1f5ff0-cde4-11dc-a183-3714bfd55ca8',
'openid.claimed_id' => 'http://binkley.lan/user/test01',
'openid.identity' => 'http://test01.binkley.lan/',
'openid.mode' => 'id_res',
'openid.ns' => 'http://specs.openid.net/auth/2.0',
'openid.ns.pape' => 'http://specs.openid.net/extensions/pape/1.0',
'openid.op_endpoint' => 'http://binkley.lan/server',
'openid.pape.auth_policies' => 'none',
'openid.pape.auth_time' => '2008-01-28T20:42:36Z',
'openid.pape.nist_auth_level' => '0',
'openid.response_nonce' => '2008-01-28T21:07:04Z99Q=',
'openid.return_to' => 'http://binkley.lan:8001/process?janrain_nonce=2008-01-28T21%3A07%3A02Z0tMIKx',
'openid.sig' => 'YJlWH4U6SroB1HoPkmEKx9AyGGg=',
'openid.signed' => 'assoc_handle,identity,response_nonce,return_to,claimed_id,op_endpoint,pape.auth_time,ns.pape,pape.nist_auth_level,pape.auth_policies'
}
assert_equal(args['openid.ns'], OPENID2_NS)
incoming = Message.from_post_args(args)
assert(incoming.is_openid2)
idres = IdResHandler.new(incoming, nil)
car = idres.send(:create_check_auth_request)
expected_args = args.dup
expected_args['openid.mode'] = 'check_authentication'
expected = Message.from_post_args(expected_args)
assert(expected.is_openid2)
assert_equal(expected, car)
assert_equal(expected_args, car.to_post_args)
end
def test_no_signed_list
msg = Message.new(OPENID2_NS)
idres = IdResHandler.new(msg, nil)
assert_protocol_error("Response missing signed") {
idres.send(:signed_list)
}
end
def test_success_openid1
msg = mkMsg(OPENID1_NS, OPENID1_FIELDS, OPENID1_SIGNED)
idres = IdResHandler.new(msg, nil)
idres.send(:check_for_fields)
end
def test_success_openid1_1
msg = mkMsg(OPENID11_NS, OPENID1_FIELDS, OPENID1_SIGNED)
idres = IdResHandler.new(msg, nil)
idres.send(:check_for_fields)
end
end
class ReturnToArgsTest < Minitest::Test
include OpenID::ProtocolErrorMixin
def check_return_to_args(query)
idres = IdResHandler.new(Message.from_post_args(query), nil)
class << idres
def verify_return_to_base(unused)
end
end
idres.send(:verify_return_to)
end
def assert_bad_args(msg, query)
assert_protocol_error(msg) {
check_return_to_args(query)
}
end
def test_return_to_args_okay
check_return_to_args({
'openid.mode' => 'id_res',
'openid.return_to' => 'http://example.com/?foo=bar',
'foo' => 'bar',
})
end
def test_unexpected_arg_okay
assert_bad_args("Unexpected parameter", {
'openid.mode' => 'id_res',
'openid.return_to' => 'http://example.com/',
'foo' => 'bar',
})
end
def test_return_to_mismatch
assert_bad_args('Message missing ret', {
'openid.mode' => 'id_res',
'openid.return_to' => 'http://example.com/?foo=bar',
})
assert_bad_args("Parameter 'foo' val", {
'openid.mode' => 'id_res',
'openid.return_to' => 'http://example.com/?foo=bar',
'foo' => 'foos',
})
end
end
class ReturnToVerifyTest < Minitest::Test
def test_bad_return_to
return_to = "http://some.url/path?foo=bar"
m = Message.new(OPENID1_NS)
m.set_arg(OPENID_NS, 'mode', 'cancel')
m.set_arg(BARE_NS, 'foo', 'bar')
# Scheme, authority, and path differences are checked by
# IdResHandler.verify_return_to_base. Query args checked by
# IdResHandler.verify_return_to_args.
[
# Scheme only
"https://some.url/path?foo=bar",
# Authority only
"http://some.url.invalid/path?foo=bar",
# Path only
"http://some.url/path_extra?foo=bar",
# Query args differ
"http://some.url/path?foo=bar2",
"http://some.url/path?foo2=bar",
].each do |bad|
m.set_arg(OPENID_NS, 'return_to', bad)
idres = IdResHandler.new(m, return_to)
assert_raises(ProtocolError) {
idres.send(:verify_return_to)
}
end
end
def test_good_return_to
base = 'http://example.janrain.com/path'
[ [base, {}],
[base + "?another=arg", {'another' => 'arg'}],
[base + "?another=arg#frag", {'another' => 'arg'}],
['HTTP'+base[4..-1], {}],
[base.sub('com', 'COM'), {}],
['http://example.janrain.com:80/path', {}],
['http://example.janrain.com/p%61th', {}],
['http://example.janrain.com/./path',{}],
].each do |return_to, args|
args['openid.return_to'] = return_to
msg = Message.from_post_args(args)
idres = IdResHandler.new(msg, base)
idres.send(:verify_return_to)
end
end
end
class DummyEndpoint
attr_accessor :server_url
def initialize(server_url)
@server_url = server_url
end
end
class CheckSigTest < Minitest::Test
include ProtocolErrorMixin
include TestUtil
def setup
@assoc = GoodAssoc.new('{not_dumb}')
@store = Store::Memory.new
@server_url = 'http://server.url/'
@endpoint = DummyEndpoint.new(@server_url)
@store.store_association(@server_url, @assoc)
@message = Message.from_post_args({
'openid.mode' => 'id_res',
'openid.identity' => '=example',
'openid.sig' => GOODSIG,
'openid.assoc_handle' => @assoc.handle,
'openid.signed' => 'mode,identity,assoc_handle,signed',
'frobboz' => 'banzit',
})
end
def call_idres_method(method_name)
idres = IdResHandler.new(@message, nil, @store, @endpoint)
idres.extend(InstanceDefExtension)
yield idres
idres.send(method_name)
end
def call_check_sig(&proc)
call_idres_method(:check_signature, &proc)
end
def no_check_auth(idres)
idres.instance_def(:check_auth) { fail "Called check_auth" }
end
def test_sign_good
call_check_sig(&method(:no_check_auth))
end
def test_bad_sig
@message.set_arg(OPENID_NS, 'sig', 'bad sig!')
assert_protocol_error('Bad signature') {
call_check_sig(&method(:no_check_auth))
}
end
def test_check_auth_ok
@message.set_arg(OPENID_NS, 'assoc_handle', 'dumb-handle')
check_auth_called = false
call_check_sig do |idres|
idres.instance_def(:check_auth) do
check_auth_called = true
end
end
assert(check_auth_called)
end
def test_check_auth_ok_no_store
@store = nil
check_auth_called = false
call_check_sig do |idres|
idres.instance_def(:check_auth) do
check_auth_called = true
end
end
assert(check_auth_called)
end
def test_expired_assoc
@assoc.expires_in = -1
@store.store_association(@server_url, @assoc)
assert_protocol_error('Association with') {
call_check_sig(&method(:no_check_auth))
}
end
def call_check_auth(&proc)
assert_log_matches("Using 'check_authentication'") {
call_idres_method(:check_auth, &proc)
}
end
def test_check_auth_create_fail
assert_protocol_error("Could not generate") {
call_check_auth do |idres|
idres.instance_def(:create_check_auth_request) do
raise Message::KeyNotFound, "Testing"
end
end
}
end
def test_check_auth_okay
OpenID.extend(OverrideMethodMixin)
me = self
send_resp = Proc.new do |req, server_url|
me.assert_equal(:req, req)
:expected_response
end
OpenID.with_method_overridden(:make_kv_post, send_resp) do
call_check_auth do |idres|
idres.instance_def(:create_check_auth_request) {
:req
}
idres.instance_def(:process_check_auth_response) do |resp|
me.assert_equal(:expected_response, resp)
end
end
end
end
def test_check_auth_process_fail
OpenID.extend(OverrideMethodMixin)
me = self
send_resp = Proc.new do |req, server_url|
me.assert_equal(:req, req)
:expected_response
end
OpenID.with_method_overridden(:make_kv_post, send_resp) do
assert_protocol_error("Testing") do
call_check_auth do |idres|
idres.instance_def(:create_check_auth_request) { :req }
idres.instance_def(:process_check_auth_response) do |resp|
me.assert_equal(:expected_response, resp)
raise ProtocolError, "Testing"
end
end
end
end
end
1.times do
# Fields from the signed list
['mode', 'identity', 'assoc_handle'
].each do |field|
test = lambda do
@message.del_arg(OPENID_NS, field)
assert_raises(Message::KeyNotFound) {
call_idres_method(:create_check_auth_request) {}
}
end
define_method("test_create_check_auth_missing_#{field}", test)
end
end
def test_create_check_auth_request_success
ca_msg = call_idres_method(:create_check_auth_request) {}
expected = @message.copy
expected.set_arg(OPENID_NS, 'mode', 'check_authentication')
assert_equal(expected, ca_msg)
end
end
class CheckAuthResponseTest < Minitest::Test
include TestUtil
include ProtocolErrorMixin
def setup
@message = Message.from_openid_args({
'is_valid' => 'true',
})
@assoc = GoodAssoc.new
@store = Store::Memory.new
@server_url = 'http://invalid/'
@endpoint = DummyEndpoint.new(@server_url)
@idres = IdResHandler.new(nil, nil, @store, @endpoint)
end
def call_process
@idres.send(:process_check_auth_response, @message)
end
def test_valid
assert_log_matches() { call_process }
end
def test_invalid
['false', 'monkeys'].each do
@message.set_arg(OPENID_NS, 'is_valid', 'false')
assert_protocol_error("Server #{@server_url} responds") {
assert_log_matches() { call_process }
}
end
end
def test_valid_invalidate
@message.set_arg(OPENID_NS, 'invalidate_handle', 'cheese')
assert_log_matches("Received 'invalidate_handle'") { call_process }
end
def test_invalid_invalidate
@message.set_arg(OPENID_NS, 'invalidate_handle', 'cheese')
['false', 'monkeys'].each do
@message.set_arg(OPENID_NS, 'is_valid', 'false')
assert_protocol_error("Server #{@server_url} responds") {
assert_log_matches("Received 'invalidate_handle'") {
call_process
}
}
end
end
def test_invalidate_no_store
@idres.instance_variable_set(:@store, nil)
@message.set_arg(OPENID_NS, 'invalidate_handle', 'cheese')
assert_log_matches("Received 'invalidate_handle'",
'Unexpectedly got "invalidate_handle"') {
call_process
}
end
end
class NonceTest < Minitest::Test
include TestUtil
include ProtocolErrorMixin
def setup
@store = Object.new
class << @store
attr_accessor :nonces, :succeed
def use_nonce(server_url, time, extra)
@nonces << [server_url, time, extra]
@succeed
end
end
@store.nonces = []
@nonce = Nonce.mk_nonce
end
def call_check_nonce(post_args, succeed=false)
response = Message.from_post_args(post_args)
if !@store.nil?
@store.succeed = succeed
end
idres = IdResHandler.new(response, nil, @store, nil)
idres.send(:check_nonce)
end
def test_openid1_success
[{},
{'openid.ns' => OPENID1_NS},
{'openid.ns' => OPENID11_NS}
].each do |args|
call_check_nonce({'rp_nonce' => @nonce}.merge(args), true)
end
end
def test_openid1_missing
[{},
{'openid.ns' => OPENID1_NS},
{'openid.ns' => OPENID11_NS}
].each do |args|
assert_protocol_error('Nonce missing') { call_check_nonce(args) }
end
end
def test_openid2_ignore_rp_nonce
assert_protocol_error('Nonce missing') {
call_check_nonce({'rp_nonce' => @nonce,
'openid.ns' => OPENID2_NS})
}
end
def test_openid2_success
call_check_nonce({'openid.response_nonce' => @nonce,
'openid.ns' => OPENID2_NS}, true)
end
def test_openid1_ignore_response_nonce
[{},
{'openid.ns' => OPENID1_NS},
{'openid.ns' => OPENID11_NS}
].each do |args|
assert_protocol_error('Nonce missing') {
call_check_nonce({'openid.response_nonce' => @nonce}.merge(args))
}
end
end
def test_no_store
@store = nil
call_check_nonce({'rp_nonce' => @nonce})
end
def test_already_used
assert_protocol_error('Nonce already used') {
call_check_nonce({'rp_nonce' => @nonce}, false)
}
end
def test_malformed_nonce
assert_protocol_error('Malformed nonce') {
call_check_nonce({'rp_nonce' => 'whee!'})
}
end
end
class DiscoveryVerificationTest < Minitest::Test
include ProtocolErrorMixin
include TestUtil
def setup
@endpoint = OpenIDServiceEndpoint.new
end
def call_verify(msg_args)
call_verify_modify(msg_args){}
end
def call_verify_modify(msg_args)
msg = Message.from_openid_args(msg_args)
idres = IdResHandler.new(msg, nil, nil, @endpoint)
idres.extend(InstanceDefExtension)
yield idres
idres.send(:verify_discovery_results)
idres.instance_variable_get(:@endpoint)
end
def assert_verify_protocol_error(error_prefix, openid_args)
assert_protocol_error(error_prefix) {call_verify(openid_args)}
end
def test_openid1_no_local_id
@endpoint.claimed_id = 'http://invalid/'
assert_verify_protocol_error("Missing required field: "\
"<#{OPENID1_NS}>identity", {})
end
def test_openid1_no_endpoint
@endpoint = nil
assert_raises(ProtocolError) {
call_verify({'identity' => 'snakes on a plane'})
}
end
def test_openid1_fallback_1_0
[OPENID1_NS, OPENID11_NS].each do |openid1_ns|
claimed_id = 'http://claimed.id/'
@endpoint = nil
resp_mesg = Message.from_openid_args({
'ns' => openid1_ns,
'identity' => claimed_id,
})
# Pass the OpenID 1 claimed_id this way since we're
# passing None for the endpoint.
resp_mesg.set_arg(BARE_NS, 'openid1_claimed_id', claimed_id)
# We expect the OpenID 1 discovery verification to try
# matching the discovered endpoint against the 1.1 type
# and fall back to 1.0.
expected_endpoint = OpenIDServiceEndpoint.new
expected_endpoint.type_uris = [OPENID_1_0_TYPE]
expected_endpoint.local_id = nil
expected_endpoint.claimed_id = claimed_id
hacked_discover = Proc.new {
|_claimed_id| ['unused', [expected_endpoint]]
}
idres = IdResHandler.new(resp_mesg, nil, nil, @endpoint)
assert_log_matches('Performing discovery') {
OpenID.with_method_overridden(:discover, hacked_discover) {
idres.send(:verify_discovery_results)
}
}
actual_endpoint = idres.instance_variable_get(:@endpoint)
assert_equal(actual_endpoint, expected_endpoint)
end
end
def test_openid2_no_op_endpoint
assert_protocol_error("Missing required field: "\
"<#{OPENID2_NS}>op_endpoint") {
call_verify({'ns'=>OPENID2_NS})
}
end
def test_openid2_local_id_no_claimed
assert_verify_protocol_error('openid.identity is present without',
{'ns' => OPENID2_NS,
'op_endpoint' => 'Phone Home',
'identity' => 'Jorge Lius Borges'})
end
def test_openid2_no_local_id_claimed
assert_log_matches() {
assert_protocol_error('openid.claimed_id is present without') {
call_verify({'ns' => OPENID2_NS,
'op_endpoint' => 'Phone Home',
'claimed_id' => 'Manuel Noriega'})
}
}
end
def test_openid2_no_identifiers
op_endpoint = 'Phone Home'
result_endpoint = assert_log_matches() {
call_verify({'ns' => OPENID2_NS,
'op_endpoint' => op_endpoint})
}
assert(result_endpoint.is_op_identifier)
assert_equal(op_endpoint, result_endpoint.server_url)
assert(result_endpoint.claimed_id.nil?)
end
def test_openid2_no_endpoint_does_disco
endpoint = OpenIDServiceEndpoint.new
endpoint.claimed_id = 'monkeysoft'
@endpoint = nil
result = assert_log_matches('No pre-discovered') {
call_verify_modify({'ns' => OPENID2_NS,
'identity' => 'sour grapes',
'claimed_id' => 'monkeysoft',
'op_endpoint' => 'Phone Home'}) do |idres|
idres.instance_def(:discover_and_verify) do |claimed_id, endpoints|
@endpoint = endpoint
end
end
}
assert_equal(endpoint, result)
end
def test_openid2_mismatched_does_disco
@endpoint.claimed_id = 'nothing special, but different'
@endpoint.local_id = 'green cheese'
endpoint = OpenIDServiceEndpoint.new
endpoint.claimed_id = 'monkeysoft'
result = assert_log_matches('Error attempting to use stored',
'Attempting discovery') {
call_verify_modify({'ns' => OPENID2_NS,
'identity' => 'sour grapes',
'claimed_id' => 'monkeysoft',
'op_endpoint' => 'Green Cheese'}) do |idres|
idres.instance_def(:discover_and_verify) do |claimed_id, endpoints|
@endpoint = endpoint
end
end
}
assert(endpoint.equal?(result))
end
def test_verify_discovery_single_claimed_id_mismatch
idres = IdResHandler.new(nil, nil)
@endpoint.local_id = 'my identity'
@endpoint.claimed_id = 'http://i-am-sam/'
@endpoint.server_url = 'Phone Home'
@endpoint.type_uris = [OPENID_2_0_TYPE]
to_match = @endpoint.dup
to_match.claimed_id = 'http://something.else/'
e = assert_raises(ProtocolError) {
idres.send(:verify_discovery_single, @endpoint, to_match)
}
assert(e.to_s =~ /different subjects/)
end
def test_openid1_1_verify_discovery_single_no_server_url
idres = IdResHandler.new(nil, nil)
@endpoint.local_id = 'my identity'
@endpoint.claimed_id = 'http://i-am-sam/'
@endpoint.server_url = 'Phone Home'
@endpoint.type_uris = [OPENID_1_1_TYPE]
to_match = @endpoint.dup
to_match.claimed_id = 'http://i-am-sam/'
to_match.type_uris = [OPENID_1_1_TYPE]
to_match.server_url = nil
idres.send(:verify_discovery_single, @endpoint, to_match)
end
def test_openid2_use_pre_discovered
@endpoint.local_id = 'my identity'
@endpoint.claimed_id = 'http://i-am-sam/'
@endpoint.server_url = 'Phone Home'
@endpoint.type_uris = [OPENID_2_0_TYPE]
result = assert_log_matches() {
call_verify({'ns' => OPENID2_NS,
'identity' => @endpoint.local_id,
'claimed_id' => @endpoint.claimed_id,
'op_endpoint' => @endpoint.server_url
})
}
assert(result.equal?(@endpoint))
end
def test_openid2_use_pre_discovered_wrong_type
text = "verify failed"
me = self
@endpoint.local_id = 'my identity'
@endpoint.claimed_id = 'i am sam'
@endpoint.server_url = 'Phone Home'
@endpoint.type_uris = [OPENID_1_1_TYPE]
endpoint = @endpoint
msg = Message.from_openid_args({'ns' => OPENID2_NS,
'identity' => @endpoint.local_id,
'claimed_id' =>
@endpoint.claimed_id,
'op_endpoint' =>
@endpoint.server_url})
idres = IdResHandler.new(msg, nil, nil, @endpoint)
idres.extend(InstanceDefExtension)
idres.instance_def(:discover_and_verify) { |claimed_id, to_match|
me.assert_equal(endpoint.claimed_id, to_match[0].claimed_id)
me.assert_equal(claimed_id, endpoint.claimed_id)
raise ProtocolError, text
}
assert_log_matches('Error attempting to use stored',
'Attempting discovery') {
assert_protocol_error(text) {
idres.send(:verify_discovery_results)
}
}
end
def test_openid1_use_pre_discovered
@endpoint.local_id = 'my identity'
@endpoint.claimed_id = 'http://i-am-sam/'
@endpoint.server_url = 'Phone Home'
@endpoint.type_uris = [OPENID_1_1_TYPE]
result = assert_log_matches() {
call_verify({'ns' => OPENID1_NS,
'identity' => @endpoint.local_id})
}
assert(result.equal?(@endpoint))
end
def test_openid1_use_pre_discovered_wrong_type
verified_error = Class.new(Exception)
@endpoint.local_id = 'my identity'
@endpoint.claimed_id = 'i am sam'
@endpoint.server_url = 'Phone Home'
@endpoint.type_uris = [OPENID_2_0_TYPE]
assert_log_matches('Error attempting to use stored',
'Attempting discovery') {
assert_raises(verified_error) {
call_verify_modify({'ns' => OPENID1_NS,
'identity' => @endpoint.local_id}) { |idres|
idres.instance_def(:discover_and_verify) do |claimed_id, endpoints|
raise verified_error
end
}
}
}
end
def test_openid2_fragment
claimed_id = "http://unittest.invalid/"
claimed_id_frag = claimed_id + "#fragment"
@endpoint.local_id = 'my identity'
@endpoint.claimed_id = claimed_id
@endpoint.server_url = 'Phone Home'
@endpoint.type_uris = [OPENID_2_0_TYPE]
result = assert_log_matches() {
call_verify({'ns' => OPENID2_NS,
'identity' => @endpoint.local_id,
'claimed_id' => claimed_id_frag,
'op_endpoint' => @endpoint.server_url})
}
[:local_id, :server_url, :type_uris].each do |sym|
assert_equal(@endpoint.send(sym), result.send(sym))
end
assert_equal(claimed_id_frag, result.claimed_id)
end
def test_endpoint_without_local_id
# An endpoint like this with no local_id is generated as a result of
# e.g. Yadis discovery with no LocalID tag.
@endpoint.server_url = "http://localhost:8000/openidserver"
@endpoint.claimed_id = "http://localhost:8000/id/id-jo"
to_match = OpenIDServiceEndpoint.new
to_match.server_url = "http://localhost:8000/openidserver"
to_match.claimed_id = "http://localhost:8000/id/id-jo"
to_match.local_id = "http://localhost:8000/id/id-jo"
idres = IdResHandler.new(nil, nil)
assert_log_matches() {
idres.send(:verify_discovery_single, @endpoint, to_match)
}
end
end
class IdResTopLevelTest < Minitest::Test
def test_id_res
endpoint = OpenIDServiceEndpoint.new
endpoint.server_url = 'http://invalid/server'
endpoint.claimed_id = 'http://my.url/'
endpoint.local_id = 'http://invalid/username'
endpoint.type_uris = [OPENID_2_0_TYPE]
assoc = GoodAssoc.new
store = Store::Memory.new
store.store_association(endpoint.server_url, assoc)
signed_fields =
[
'response_nonce',
'op_endpoint',
'assoc_handle',
'identity',
'claimed_id',
'ns',
'return_to',
]
return_to = 'http://return.to/'
args = {
'ns' => OPENID2_NS,
'return_to' => return_to,
'claimed_id' => endpoint.claimed_id,
'identity' => endpoint.local_id,
'assoc_handle' => assoc.handle,
'op_endpoint' => endpoint.server_url,
'response_nonce' => Nonce.mk_nonce,
'signed' => signed_fields.join(','),
'sig' => GOODSIG,
}
msg = Message.from_openid_args(args)
idres = OpenID::Consumer::IdResHandler.new(msg, return_to,
store, endpoint)
assert_equal(idres.signed_fields,
signed_fields.map {|f|'openid.' + f})
end
end
class DiscoverAndVerifyTest < Minitest::Test
include ProtocolErrorMixin
include TestUtil
OpenID.extend(OverrideMethodMixin)
def test_no_services
me = self
disco = Proc.new do |e|
me.assert_equal(e, :sentinel)
[:undefined, []]
end
endpoint = OpenIDServiceEndpoint.new
endpoint.claimed_id = :sentinel
idres = IdResHandler.new(nil, nil)
assert_log_matches('Performing discovery on') do
assert_protocol_error('No OpenID information found') do
OpenID.with_method_overridden(:discover, disco) do
idres.send(:discover_and_verify, :sentinel, [endpoint])
end
end
end
end
end
class VerifyDiscoveredServicesTest < Minitest::Test
include ProtocolErrorMixin
include TestUtil
def test_no_services
endpoint = OpenIDServiceEndpoint.new
endpoint.claimed_id = :sentinel
idres = IdResHandler.new(nil, nil)
assert_log_matches('Discovery verification failure') do
assert_protocol_error('No matching endpoint') do
idres.send(:verify_discovered_services,
'http://bogus.id/', [], [endpoint])
end
end
end
end
end
end
end
ruby-openid-2.7.0debian.orig/test/test_xrires.rb 0000644 0001750 0001750 00000005020 12512544714 021170 0 ustar sbadia sbadia require 'minitest/autorun'
require 'openid/yadis/xrires'
module OpenID
module Yadis
class XRDSFetcher
def initialize(results)
@results = results
end
def fetch(url, body=nil, headers=nil, redirect_limit=nil)
if !@results.empty?
return @results.shift
end
nil
end
end
class ProxyQueryTestCase < Minitest::Test
def setup
@proxy_url = 'http://xri.example.com/'
@proxy = XRI::ProxyResolver.new(@proxy_url)
@servicetype = 'xri://+i-service*(+forwarding)*($v*1.0)'
@servicetype_enc = 'xri%3A%2F%2F%2Bi-service%2A%28%2Bforwarding%29%2A%28%24v%2A1.0%29'
end
def test_proxy_url
st = @servicetype
ste = @servicetype_enc
args_esc = ["_xrd_r=application%2Fxrds%2Bxml", "_xrd_t=#{ste}"]
pqu = @proxy.method('query_url')
h = @proxy_url
assert_match h + '=foo?', pqu.call('=foo', st)
assert_match args_esc[0], pqu.call('=foo', st)
assert_match args_esc[1], pqu.call('=foo', st)
assert_match h + '=foo/bar?baz&', pqu.call('=foo/bar?baz', st)
assert_match args_esc[0], pqu.call('=foo/bar?baz', st)
assert_match args_esc[1], pqu.call('=foo/bar?baz', st)
assert_match h + '=foo/bar?baz=quux&', pqu.call('=foo/bar?baz=quux', st)
assert_match args_esc[0], pqu.call('=foo/bar?baz=quux', st)
assert_match args_esc[1], pqu.call('=foo/bar?baz=quux', st)
assert_match h + '=foo/bar?mi=fa&so=la&', pqu.call('=foo/bar?mi=fa&so=la', st)
assert_match args_esc[0], pqu.call('=foo/bar?mi=fa&so=la', st)
assert_match args_esc[1], pqu.call('=foo/bar?mi=fa&so=la', st)
# With no service endpoint selection.
args_esc = "_xrd_r=application%2Fxrds%2Bxml%3Bsep%3Dfalse"
assert_match h + '=foo?', pqu.call('=foo', nil)
assert_match args_esc, pqu.call('=foo', nil)
end
def test_proxy_url_qmarks
st = @servicetype
ste = @servicetype_enc
args_esc = ["_xrd_r=application%2Fxrds%2Bxml", "_xrd_t=#{ste}"]
pqu = @proxy.method('query_url')
h = @proxy_url
assert_match h + '=foo/bar??', pqu.call('=foo/bar?', st)
assert_match args_esc[0], pqu.call('=foo/bar?', st)
assert_match args_esc[1], pqu.call('=foo/bar?', st)
assert_match h + '=foo/bar????', pqu.call('=foo/bar???', st)
assert_match args_esc[0], pqu.call('=foo/bar???', st)
assert_match args_esc[1], pqu.call('=foo/bar???', st)
end
end
end
end
ruby-openid-2.7.0debian.orig/test/util.rb 0000644 0001750 0001750 00000002350 12512544714 017575 0 ustar sbadia sbadia # Utilities that are only used in the testing code
require 'stringio'
module OpenID
module TestUtil
def assert_log_matches(*regexes)
begin
old_logger = Util.logger
log_output = StringIO.new
Util.logger = Logger.new(log_output)
result = yield
ensure
Util.logger = old_logger
end
log_output.rewind
log_lines = log_output.readlines
assert_equal(regexes.length, log_lines.length,
[regexes, log_lines].inspect)
log_lines.zip(regexes) do |line, regex|
assert_match(regex, line)
end
result
end
def assert_log_line_count(num_lines)
begin
old_logger = Util.logger
log_output = StringIO.new
Util.logger = Logger.new(log_output)
result = yield
ensure
Util.logger = old_logger
end
log_output.rewind
log_lines = log_output.readlines
assert_equal(num_lines, log_lines.length)
result
end
def silence_logging
begin
old_logger = Util.logger
log_output = StringIO.new
Util.logger = Logger.new(log_output)
result = yield
ensure
Util.logger = old_logger
end
result
end
end
end
ruby-openid-2.7.0debian.orig/test/test_server.rb 0000644 0001750 0001750 00000252166 12512544714 021201 0 ustar sbadia sbadia require 'minitest/autorun'
require 'testutil'
require 'util'
require 'uri'
require 'openid/server'
require 'openid/cryptutil'
require 'openid/association'
require 'openid/util'
require 'openid/message'
require 'openid/store/memory'
require 'openid/dh'
require 'openid/consumer/associationmanager'
# In general, if you edit or add tests here, try to move in the
# direction of testing smaller units. For testing the external
# interfaces, we'll be developing an implementation-agnostic testing
# suite.
# for more, see /etc/ssh/moduli
module OpenID
ALT_MODULUS = 0xCAADDDEC1667FC68B5FA15D53C4E1532DD24561A1A2D47A12C01ABEA1E00731F6921AAC40742311FDF9E634BB7131BEE1AF240261554389A910425E044E88C8359B010F5AD2B80E29CB1A5B027B19D9E01A6F63A6F45E5D7ED2FF6A2A0085050A7D0CF307C3DB51D2490355907B4427C23A98DF1EB8ABEF2BA209BB7AFFE86A7
ALT_GEN = 5
class CatchLogs
def catchlogs_setup
@old_logger = Util.logger
Util.logger = self.method('got_log_message')
@messages = []
end
def got_log_message(message)
@messages << message
end
def teardown
Util.logger = @old_logger
end
end
class TestProtocolError < Minitest::Test
def test_browserWithReturnTo
return_to = "http://rp.unittest/consumer"
# will be a ProtocolError raised by Decode or
# CheckIDRequest.answer
args = Message.from_post_args({
'openid.mode' => 'monkeydance',
'openid.identity' => 'http://wagu.unittest/',
'openid.return_to' => return_to,
})
e = Server::ProtocolError.new(args, "plucky")
assert(e.has_return_to)
expected_args = {
'openid.mode' => 'error',
'openid.error' => 'plucky',
}
_, result_args = e.encode_to_url.split('?', 2)
result_args = Util.parse_query(result_args)
assert_equal(result_args, expected_args)
end
def test_browserWithReturnTo_OpenID2_GET
return_to = "http://rp.unittest/consumer"
# will be a ProtocolError raised by Decode or
# CheckIDRequest.answer
args = Message.from_post_args({
'openid.ns' => OPENID2_NS,
'openid.mode' => 'monkeydance',
'openid.identity' => 'http://wagu.unittest/',
'openid.claimed_id' => 'http://wagu.unittest/',
'openid.return_to' => return_to,
})
e = Server::ProtocolError.new(args, "plucky")
assert(e.has_return_to)
expected_args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'error',
'openid.error' => 'plucky',
}
_, result_args = e.encode_to_url.split('?', 2)
result_args = Util.parse_query(result_args)
assert_equal(result_args, expected_args)
end
def test_browserWithReturnTo_OpenID2_POST
return_to = "http://rp.unittest/consumer" + ('x' * OPENID1_URL_LIMIT)
# will be a ProtocolError raised by Decode or
# CheckIDRequest.answer
args = Message.from_post_args({
'openid.ns' => OPENID2_NS,
'openid.mode' => 'monkeydance',
'openid.identity' => 'http://wagu.unittest/',
'openid.claimed_id' => 'http://wagu.unittest/',
'openid.return_to' => return_to,
})
e = Server::ProtocolError.new(args, "plucky")
assert(e.has_return_to)
assert(e.which_encoding == Server::ENCODE_HTML_FORM)
assert(e.to_form_markup == e.to_message.to_form_markup(
args.get_arg(OPENID_NS, 'return_to')))
end
def test_browserWithReturnTo_OpenID1_exceeds_limit
return_to = "http://rp.unittest/consumer" + ('x' * OPENID1_URL_LIMIT)
# will be a ProtocolError raised by Decode or
# CheckIDRequest.answer
args = Message.from_post_args({
'openid.mode' => 'monkeydance',
'openid.identity' => 'http://wagu.unittest/',
'openid.return_to' => return_to,
})
e = Server::ProtocolError.new(args, "plucky")
assert(e.has_return_to)
expected_args = {
'openid.mode' => 'error',
'openid.error' => 'plucky',
}
assert(e.which_encoding == Server::ENCODE_URL)
_, result_args = e.encode_to_url.split('?', 2)
result_args = Util.parse_query(result_args)
assert_equal(result_args, expected_args)
end
def test_noReturnTo
# will be a ProtocolError raised by Decode or
# CheckIDRequest.answer
args = Message.from_post_args({
'openid.mode' => 'zebradance',
'openid.identity' => 'http://wagu.unittest/',
})
e = Server::ProtocolError.new(args, "waffles")
assert(!e.has_return_to)
expected = "error:waffles\nmode:error\n"
assert_equal(e.encode_to_kvform, expected)
end
def test_no_message
e = Server::ProtocolError.new(nil, "no message")
assert(e.get_return_to.nil?)
assert_equal(e.which_encoding, nil)
end
def test_which_encoding_no_message
e = Server::ProtocolError.new(nil, "no message")
assert(e.which_encoding.nil?)
end
end
class TestDecode < Minitest::Test
def setup
@claimed_id = 'http://de.legating.de.coder.unittest/'
@id_url = "http://decoder.am.unittest/"
@rt_url = "http://rp.unittest/foobot/?qux=zam"
@tr_url = "http://rp.unittest/"
@assoc_handle = "{assoc}{handle}"
@op_endpoint = 'http://endpoint.unittest/encode'
@store = Store::Memory.new()
@server = Server::Server.new(@store, @op_endpoint)
@decode = Server::Decoder.new(@server).method('decode')
end
def test_none
args = {}
r = @decode.call(args)
assert_equal(r, nil)
end
def test_irrelevant
args = {
'pony' => 'spotted',
'sreg.mutant_power' => 'decaffinator',
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_bad
args = {
'openid.mode' => 'twos-compliment',
'openid.pants' => 'zippered',
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_dictOfLists
args = {
'openid.mode' => ['checkid_setup'],
'openid.identity' => @id_url,
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.trust_root' => @tr_url,
}
begin
result = @decode.call(args)
rescue ArgumentError => err
assert !err.to_s.index('values').nil?
else
flunk("Expected ArgumentError, but got result #{result}")
end
end
def test_checkidImmediate
args = {
'openid.mode' => 'checkid_immediate',
'openid.identity' => @id_url,
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.trust_root' => @tr_url,
# should be ignored
'openid.some.extension' => 'junk',
}
r = @decode.call(args)
assert(r.is_a?(Server::CheckIDRequest))
assert_equal(r.mode, "checkid_immediate")
assert_equal(r.immediate, true)
assert_equal(r.identity, @id_url)
assert_equal(r.trust_root, @tr_url)
assert_equal(r.return_to, @rt_url)
assert_equal(r.assoc_handle, @assoc_handle)
end
def test_checkidImmediate_constructor
r = Server::CheckIDRequest.new(@id_url, @rt_url, nil,
@rt_url, true, @assoc_handle)
assert(r.mode == 'checkid_immediate')
assert(r.immediate)
end
def test_checkid_missing_return_to_and_trust_root
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.claimed_id' => @id_url,
'openid.assoc_handle' => @assoc_handle,
}
assert_raises(Server::ProtocolError) {
m = Message.from_post_args(args)
Server::CheckIDRequest.from_message(m, @op_endpoint)
}
end
def test_checkid_id_select
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'checkid_setup',
'openid.identity' => IDENTIFIER_SELECT,
'openid.claimed_id' => IDENTIFIER_SELECT,
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.realm' => @tr_url,
}
m = Message.from_post_args(args)
req = Server::CheckIDRequest.from_message(m, @op_endpoint)
assert(req.id_select)
end
def test_checkid_not_id_select
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'checkid_setup',
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.realm' => @tr_url,
}
id_args = [
{'openid.claimed_id' => IDENTIFIER_SELECT,
'openid.identity' => 'http://bogus.com/'},
{'openid.claimed_id' => 'http://bogus.com/',
'openid.identity' => 'http://bogus.com/'},
]
id_args.each { |id|
m = Message.from_post_args(args.merge(id))
req = Server::CheckIDRequest.from_message(m, @op_endpoint)
assert(!req.id_select)
}
end
def test_checkidSetup
args = {
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.trust_root' => @tr_url,
}
r = @decode.call(args)
assert(r.is_a?(Server::CheckIDRequest))
assert_equal(r.mode, "checkid_setup")
assert_equal(r.immediate, false)
assert_equal(r.identity, @id_url)
assert_equal(r.trust_root, @tr_url)
assert_equal(r.return_to, @rt_url)
end
def test_checkidSetupOpenID2
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.claimed_id' => @claimed_id,
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.realm' => @tr_url,
}
r = @decode.call(args)
assert(r.is_a?(Server::CheckIDRequest))
assert_equal(r.mode, "checkid_setup")
assert_equal(r.immediate, false)
assert_equal(r.identity, @id_url)
assert_equal(r.claimed_id, @claimed_id)
assert_equal(r.trust_root, @tr_url)
assert_equal(r.return_to, @rt_url)
end
def test_checkidSetupNoClaimedIDOpenID2
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.realm' => @tr_url,
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_checkidSetupNoIdentityOpenID2
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'checkid_setup',
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.realm' => @tr_url,
}
r = @decode.call(args)
assert(r.is_a?(Server::CheckIDRequest))
assert_equal(r.mode, "checkid_setup")
assert_equal(r.immediate, false)
assert_equal(r.identity, nil)
assert_equal(r.trust_root, @tr_url)
assert_equal(r.return_to, @rt_url)
end
def test_checkidSetupNoReturnOpenID1
# Make sure an OpenID 1 request cannot be decoded if it lacks a
# return_to.
args = {
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.assoc_handle' => @assoc_handle,
'openid.trust_root' => @tr_url,
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_checkidSetupNoReturnOpenID2
# Make sure an OpenID 2 request with no return_to can be decoded,
# and make sure a response to such a request raises
# NoReturnToError.
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.claimed_id' => @id_url,
'openid.assoc_handle' => @assoc_handle,
'openid.realm' => @tr_url,
}
req = @decode.call(args)
assert(req.is_a?(Server::CheckIDRequest))
assert_raises(Server::NoReturnToError) {
req.answer(false)
}
assert_raises(Server::NoReturnToError) {
req.encode_to_url('bogus')
}
assert_raises(Server::NoReturnToError) {
req.cancel_url
}
end
def test_checkidSetupRealmRequiredOpenID2
# Make sure that an OpenID 2 request which lacks return_to cannot
# be decoded if it lacks a realm. Spec => This value
# (openid.realm) MUST be sent if openid.return_to is omitted.
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.assoc_handle' => @assoc_handle,
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_checkidSetupBadReturn
args = {
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => 'not a url',
}
begin
result = @decode.call(args)
rescue Server::ProtocolError => err
assert(err.openid_message)
else
flunk("Expected ProtocolError, instead returned with #{result}")
end
end
def test_checkidSetupUntrustedReturn
args = {
'openid.mode' => 'checkid_setup',
'openid.identity' => @id_url,
'openid.assoc_handle' => @assoc_handle,
'openid.return_to' => @rt_url,
'openid.trust_root' => 'http://not-the-return-place.unittest/',
}
begin
result = @decode.call(args)
rescue Server::UntrustedReturnURL => err
assert(err.openid_message, err.to_s)
else
flunk("Expected UntrustedReturnURL, instead returned with #{result}")
end
end
def test_checkidSetupUntrustedReturn_Constructor
assert_raises(Server::UntrustedReturnURL) {
Server::CheckIDRequest.new(@id_url, @rt_url, nil,
'http://not-the-return-place.unittest/',
false, @assoc_handle)
}
end
def test_checkidSetupMalformedReturnURL_Constructor
assert_raises(Server::MalformedReturnURL) {
Server::CheckIDRequest.new(@id_url, 'bogus://return.url', nil,
'http://trustroot.com/',
false, @assoc_handle)
}
end
def test_checkAuth
args = {
'openid.mode' => 'check_authentication',
'openid.assoc_handle' => '{dumb}{handle}',
'openid.sig' => 'sigblob',
'openid.signed' => 'identity,return_to,response_nonce,mode',
'openid.identity' => 'signedval1',
'openid.return_to' => 'signedval2',
'openid.response_nonce' => 'signedval3',
'openid.baz' => 'unsigned',
}
r = @decode.call(args)
assert(r.is_a?(Server::CheckAuthRequest))
assert_equal(r.mode, 'check_authentication')
assert_equal(r.sig, 'sigblob')
end
def test_checkAuthMissingSignature
args = {
'openid.mode' => 'check_authentication',
'openid.assoc_handle' => '{dumb}{handle}',
'openid.signed' => 'foo,bar,mode',
'openid.foo' => 'signedval1',
'openid.bar' => 'signedval2',
'openid.baz' => 'unsigned',
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_checkAuthAndInvalidate
args = {
'openid.mode' => 'check_authentication',
'openid.assoc_handle' => '{dumb}{handle}',
'openid.invalidate_handle' => '[[SMART_handle]]',
'openid.sig' => 'sigblob',
'openid.signed' => 'identity,return_to,response_nonce,mode',
'openid.identity' => 'signedval1',
'openid.return_to' => 'signedval2',
'openid.response_nonce' => 'signedval3',
'openid.baz' => 'unsigned',
}
r = @decode.call(args)
assert(r.is_a?(Server::CheckAuthRequest))
assert_equal(r.invalidate_handle, '[[SMART_handle]]')
end
def test_associateDH
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'DH-SHA1',
'openid.dh_consumer_public' => "Rzup9265tw==",
}
r = @decode.call(args)
assert(r.is_a?(Server::AssociateRequest))
assert_equal(r.mode, "associate")
assert_equal(r.session.session_type, "DH-SHA1")
assert_equal(r.assoc_type, "HMAC-SHA1")
assert(r.session.consumer_pubkey)
end
def test_associateDHMissingKey
# Trying DH assoc w/o public key
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'DH-SHA1',
}
# Using DH-SHA1 without supplying dh_consumer_public is an error.
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_associateDHpubKeyNotB64
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'DH-SHA1',
'openid.dh_consumer_public' => "donkeydonkeydonkey",
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_associateDHModGen
# test dh with non-default but valid values for dh_modulus and
# dh_gen
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'DH-SHA1',
'openid.dh_consumer_public' => "Rzup9265tw==",
'openid.dh_modulus' => CryptUtil.num_to_base64(ALT_MODULUS),
'openid.dh_gen' => CryptUtil.num_to_base64(ALT_GEN) ,
}
r = @decode.call(args)
assert(r.is_a?(Server::AssociateRequest))
assert_equal(r.mode, "associate")
assert_equal(r.session.session_type, "DH-SHA1")
assert_equal(r.assoc_type, "HMAC-SHA1")
assert_equal(r.session.dh.modulus, ALT_MODULUS)
assert_equal(r.session.dh.generator, ALT_GEN)
assert(r.session.consumer_pubkey)
end
def test_associateDHCorruptModGen
# test dh with non-default but valid values for dh_modulus and
# dh_gen
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'DH-SHA1',
'openid.dh_consumer_public' => "Rzup9265tw==",
'openid.dh_modulus' => 'pizza',
'openid.dh_gen' => 'gnocchi',
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_associateDHMissingGen
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'DH-SHA1',
'openid.dh_consumer_public' => "Rzup9265tw==",
'openid.dh_modulus' => 'pizza',
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_associateDHMissingMod
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'DH-SHA1',
'openid.dh_consumer_public' => "Rzup9265tw==",
'openid.dh_gen' => 'pizza',
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
# def test_associateDHInvalidModGen(self):
# # test dh with properly encoded values that are not a valid
# # modulus/generator combination.
# args = {
# 'openid.mode': 'associate',
# 'openid.session_type': 'DH-SHA1',
# 'openid.dh_consumer_public': "Rzup9265tw==",
# 'openid.dh_modulus': cryptutil.longToBase64(9),
# 'openid.dh_gen': cryptutil.longToBase64(27) ,
# }
# self.failUnlessRaises(server.ProtocolError, self.decode, args)
# test_associateDHInvalidModGen.todo = "low-priority feature"
def test_associateWeirdSession
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'FLCL6',
'openid.dh_consumer_public' => "YQ==\n",
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_associatePlain
args = {
'openid.mode' => 'associate',
}
r = @decode.call(args)
assert(r.is_a?(Server::AssociateRequest))
assert_equal(r.mode, "associate")
assert_equal(r.session.session_type, "no-encryption")
assert_equal(r.assoc_type, "HMAC-SHA1")
end
def test_nomode
args = {
'openid.session_type' => 'DH-SHA1',
'openid.dh_consumer_public' => "my public keeey",
}
assert_raises(Server::ProtocolError) {
@decode.call(args)
}
end
def test_invalidns
args = {'openid.ns' => 'Vegetables',
'openid.mode' => 'associate'}
begin
@decode.call(args)
rescue Server::ProtocolError => err
assert(err.openid_message)
assert(err.to_s.index('Vegetables'))
end
end
end
class BogusEncoder < Server::Encoder
def encode(response)
return "BOGUS"
end
end
class BogusDecoder < Server::Decoder
def decode(query)
return "BOGUS"
end
end
class TestEncode < Minitest::Test
def setup
@encoder = Server::Encoder.new
@encode = @encoder.method('encode')
@op_endpoint = 'http://endpoint.unittest/encode'
@store = Store::Memory.new
@server = Server::Server.new(@store, @op_endpoint)
end
def test_id_res_OpenID2_GET
# Check that when an OpenID 2 response does not exceed the OpenID
# 1 message size, a GET response (i.e., redirect) is issued.
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false,
nil)
request.message = Message.new(OPENID2_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'ns' => OPENID2_NS,
'mode' => 'id_res',
'identity' => request.identity,
'claimed_id' => request.identity,
'return_to' => request.return_to,
})
assert(!response.render_as_form)
assert(response.which_encoding == Server::ENCODE_URL)
webresponse = @encode.call(response)
assert(webresponse.headers.member?('location'))
end
def test_id_res_OpenID2_POST
# Check that when an OpenID 2 response exceeds the OpenID 1
# message size, a POST response (i.e., an HTML form) is returned.
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false,
nil)
request.message = Message.new(OPENID2_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'ns' => OPENID2_NS,
'mode' => 'id_res',
'identity' => request.identity,
'claimed_id' => request.identity,
'return_to' => 'x' * OPENID1_URL_LIMIT,
})
assert(response.render_as_form)
assert(response.encode_to_url.length > OPENID1_URL_LIMIT)
assert(response.which_encoding == Server::ENCODE_HTML_FORM)
webresponse = @encode.call(response)
assert_equal(webresponse.body, response.to_form_markup)
end
def test_to_form_markup
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false,
nil)
request.message = Message.new(OPENID2_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'ns' => OPENID2_NS,
'mode' => 'id_res',
'identity' => request.identity,
'claimed_id' => request.identity,
'return_to' => 'x' * OPENID1_URL_LIMIT,
})
form_markup = response.to_form_markup({'foo'=>'bar'})
assert(/ foo="bar"/ =~ form_markup, form_markup)
end
def test_to_html
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false,
nil)
request.message = Message.new(OPENID2_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'ns' => OPENID2_NS,
'mode' => 'id_res',
'identity' => request.identity,
'claimed_id' => request.identity,
'return_to' => 'x' * OPENID1_URL_LIMIT,
})
html = response.to_html
assert(html)
end
def test_id_res_OpenID1_exceeds_limit
# Check that when an OpenID 1 response exceeds the OpenID 1
# message size, a GET response is issued. Technically, this
# shouldn't be permitted by the library, but this test is in place
# to preserve the status quo for OpenID 1.
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false,
nil)
request.message = Message.new(OPENID1_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'mode' => 'id_res',
'identity' => request.identity,
'return_to' => 'x' * OPENID1_URL_LIMIT,
})
assert(!response.render_as_form)
assert(response.encode_to_url.length > OPENID1_URL_LIMIT)
assert(response.which_encoding == Server::ENCODE_URL)
webresponse = @encode.call(response)
assert_equal(webresponse.headers['location'], response.encode_to_url)
end
def test_id_res
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false, nil)
request.message = Message.new(OPENID1_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'mode' => 'id_res',
'identity' => request.identity,
'return_to' => request.return_to,
})
webresponse = @encode.call(response)
assert_equal(webresponse.code, Server::HTTP_REDIRECT)
assert(webresponse.headers.member?('location'))
location = webresponse.headers['location']
assert(location.start_with?(request.return_to),
sprintf("%s does not start with %s",
location, request.return_to))
# argh.
q2 = Util.parse_query(URI::parse(location).query)
expected = response.fields.to_post_args
assert_equal(q2, expected)
end
def test_cancel
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false, nil)
request.message = Message.new(OPENID2_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'mode' => 'cancel',
})
webresponse = @encode.call(response)
assert_equal(webresponse.code, Server::HTTP_REDIRECT)
assert(webresponse.headers.member?('location'))
end
def test_cancel_to_form
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false, nil)
request.message = Message.new(OPENID2_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'mode' => 'cancel',
})
form = response.to_form_markup
assert(form.index(request.return_to))
end
def test_assocReply
msg = Message.new(OPENID2_NS)
msg.set_arg(OPENID2_NS, 'session_type', 'no-encryption')
request = Server::AssociateRequest.from_message(msg)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_post_args(
{'openid.assoc_handle' => "every-zig"})
webresponse = @encode.call(response)
body = "assoc_handle:every-zig\n"
assert_equal(webresponse.code, Server::HTTP_OK)
assert_equal(webresponse.headers, {})
assert_equal(webresponse.body, body)
end
def test_checkauthReply
request = Server::CheckAuthRequest.new('a_sock_monkey',
'siggggg',
[])
request.message = Message.new(OPENID2_NS)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'is_valid' => 'true',
'invalidate_handle' => 'xXxX:xXXx'
})
body = "invalidate_handle:xXxX:xXXx\nis_valid:true\n"
webresponse = @encode.call(response)
assert_equal(webresponse.code, Server::HTTP_OK)
assert_equal(webresponse.headers, {})
assert_equal(webresponse.body, body)
end
def test_unencodableError
args = Message.from_post_args({
'openid.identity' => 'http://limu.unittest/',
})
e = Server::ProtocolError.new(args, "wet paint")
assert_raises(Server::EncodingError) {
@encode.call(e)
}
end
def test_encodableError
args = Message.from_post_args({
'openid.mode' => 'associate',
'openid.identity' => 'http://limu.unittest/',
})
body="error:snoot\nmode:error\n"
webresponse = @encode.call(Server::ProtocolError.new(args, "snoot"))
assert_equal(webresponse.code, Server::HTTP_ERROR)
assert_equal(webresponse.headers, {})
assert_equal(webresponse.body, body)
end
end
class TestSigningEncode < Minitest::Test
def setup
@_dumb_key = Server::Signatory._dumb_key
@_normal_key = Server::Signatory._normal_key
@store = Store::Memory.new()
@server = Server::Server.new(@store, "http://signing.unittest/enc")
@request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false, nil)
@request.message = Message.new(OPENID2_NS)
@response = Server::OpenIDResponse.new(@request)
@response.fields = Message.from_openid_args({
'mode' => 'id_res',
'identity' => @request.identity,
'return_to' => @request.return_to,
})
@signatory = Server::Signatory.new(@store)
@encoder = Server::SigningEncoder.new(@signatory)
@encode = @encoder.method('encode')
end
def test_idres
assoc_handle = '{bicycle}{shed}'
@store.store_association(
@_normal_key,
Association.from_expires_in(60, assoc_handle,
'sekrit', 'HMAC-SHA1'))
@request.assoc_handle = assoc_handle
webresponse = @encode.call(@response)
assert_equal(webresponse.code, Server::HTTP_REDIRECT)
assert(webresponse.headers.member?('location'))
location = webresponse.headers['location']
query = Util.parse_query(URI::parse(location).query)
assert(query.member?('openid.sig'))
assert(query.member?('openid.assoc_handle'))
assert(query.member?('openid.signed'))
end
def test_idresDumb
webresponse = @encode.call(@response)
assert_equal(webresponse.code, Server::HTTP_REDIRECT)
assert(webresponse.headers.has_key?('location'))
location = webresponse.headers['location']
query = Util.parse_query(URI::parse(location).query)
assert(query.member?('openid.sig'))
assert(query.member?('openid.assoc_handle'))
assert(query.member?('openid.signed'))
end
def test_forgotStore
@encoder.signatory = nil
assert_raises(ArgumentError) {
@encode.call(@response)
}
end
def test_cancel
request = Server::CheckIDRequest.new(
'http://bombom.unittest/',
'http://burr.unittest/999',
@server.op_endpoint,
'http://burr.unittest/',
false, nil)
request.message = Message.new(OPENID2_NS)
response = Server::OpenIDResponse.new(request)
response.fields.set_arg(OPENID_NS, 'mode', 'cancel')
webresponse = @encode.call(response)
assert_equal(webresponse.code, Server::HTTP_REDIRECT)
assert(webresponse.headers.has_key?('location'))
location = webresponse.headers['location']
query = Util.parse_query(URI::parse(location).query)
assert !query.has_key?('openid.sig')
end
def test_assocReply
msg = Message.new(OPENID2_NS)
msg.set_arg(OPENID2_NS, 'session_type', 'no-encryption')
request = Server::AssociateRequest.from_message(msg)
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({'assoc_handle' => "every-zig"})
webresponse = @encode.call(response)
body = "assoc_handle:every-zig\n"
assert_equal(webresponse.code, Server::HTTP_OK)
assert_equal(webresponse.headers, {})
assert_equal(webresponse.body, body)
end
def test_alreadySigned
@response.fields.set_arg(OPENID_NS, 'sig', 'priorSig==')
assert_raises(Server::AlreadySigned) {
@encode.call(@response)
}
end
end
class TestCheckID < Minitest::Test
def setup
@op_endpoint = 'http://endpoint.unittest/'
@store = Store::Memory.new()
@server = Server::Server.new(@store, @op_endpoint)
@request = Server::CheckIDRequest.new(
'http://bambam.unittest/',
'http://bar.unittest/999',
@server.op_endpoint,
'http://bar.unittest/',
false)
@request.message = Message.new(OPENID2_NS)
end
def test_trustRootInvalid
@request.trust_root = "http://foo.unittest/17"
@request.return_to = "http://foo.unittest/39"
assert(!@request.trust_root_valid())
end
def test_trustRootInvalid_modified
@request.trust_root = "does://not.parse/"
@request.message = :sentinel
begin
result = @request.trust_root_valid
rescue Server::MalformedTrustRoot => why
assert_equal(:sentinel, why.openid_message)
else
flunk("Expected MalformedTrustRoot, got #{result.inspect}")
end
end
def test_trustRootvalid_absent_trust_root
@request.trust_root = nil
assert(@request.trust_root_valid())
end
def test_trustRootValid
@request.trust_root = "http://foo.unittest/"
@request.return_to = "http://foo.unittest/39"
assert(@request.trust_root_valid())
end
def test_trustRootValidNoReturnTo
request = Server::CheckIDRequest.new(
'http://bambam.unittest/',
nil,
@server.op_endpoint,
'http://bar.unittest/',
false)
assert(request.trust_root_valid())
end
def test_returnToVerified_callsVerify
# Make sure that verifyReturnTo is calling the trustroot
# function verifyReturnTo
# Ensure that exceptions are passed through
sentinel = Exception.new()
__req = @request
tc = self
vrfyExc = Proc.new { |trust_root, return_to|
tc.assert_equal(__req.trust_root, trust_root)
tc.assert_equal(__req.return_to, return_to)
raise sentinel
}
TrustRoot.extend(OverrideMethodMixin)
TrustRoot.with_method_overridden(:verify_return_to, vrfyExc) do
begin
@request.return_to_verified()
flunk("Expected sentinel to be raised, got success")
rescue Exception => e
assert(e.equal?(sentinel), [e, sentinel].inspect)
end
end
# Ensure that True and False are passed through unchanged
constVerify = Proc.new { |val|
verify = Proc.new { |trust_root, return_to|
tc.assert_equal(__req.trust_root, trust_root)
tc.assert_equal(__req.request.return_to, return_to)
return val
}
return verify
}
[true, false].each { |val|
verifier = constVerify.call(val)
TrustRoot.with_method_overridden(:verify_return_to, verifier) do
assert_equal(val, @request.return_to_verified())
end
}
end
def _expectAnswer(answer, identity=nil, claimed_id=nil)
expected_list = [
['mode', 'id_res'],
['return_to', @request.return_to],
['op_endpoint', @op_endpoint],
]
if identity
expected_list << ['identity', identity]
if claimed_id
expected_list << ['claimed_id', claimed_id]
else
expected_list << ['claimed_id', identity]
end
end
expected_list.each { |k, expected|
actual = answer.fields.get_arg(OPENID_NS, k)
assert_equal(expected, actual,
sprintf("%s: expected %s, got %s",
k, expected, actual))
}
assert(answer.fields.has_key?(OPENID_NS, 'response_nonce'))
assert(answer.fields.get_openid_namespace() == OPENID2_NS)
# One for nonce, one for ns
assert_equal(answer.fields.to_post_args.length,
expected_list.length + 2,
answer.fields.to_post_args.inspect)
end
def test_answerAllow
# Check the fields specified by "Positive Assertions"
#
# including mode=id_res, identity, claimed_id, op_endpoint,
# return_to
answer = @request.answer(true)
assert_equal(answer.request, @request)
_expectAnswer(answer, @request.identity)
end
def test_answerAllowDelegatedIdentity
@request.claimed_id = 'http://delegating.unittest/'
answer = @request.answer(true)
_expectAnswer(answer, @request.identity,
@request.claimed_id)
end
def test_answerAllowWithoutIdentityReally
@request.identity = nil
answer = @request.answer(true)
assert_equal(answer.request, @request)
_expectAnswer(answer)
end
def test_answerAllowAnonymousFail
@request.identity = nil
# XXX - Check on this, I think this behavior is legal in OpenID
# 2.0?
assert_raises(ArgumentError) {
@request.answer(true, nil, "=V")
}
end
def test_answerAllowWithIdentity
@request.identity = IDENTIFIER_SELECT
selected_id = 'http://anon.unittest/9861'
answer = @request.answer(true, nil, selected_id)
_expectAnswer(answer, selected_id)
end
def test_answerAllowWithNoIdentity
@request.identity = IDENTIFIER_SELECT
assert_raises(ArgumentError) {
@request.answer(true, nil, nil)
}
end
def test_immediate_openid1_no_identity
@request.message = Message.new(OPENID1_NS)
@request.immediate = true
@request.mode = 'checkid_immediate'
resp = @request.answer(false)
assert(resp.fields.get_arg(OPENID_NS, 'mode') == 'id_res')
end
def test_checkid_setup_openid1_no_identity
@request.message = Message.new(OPENID1_NS)
@request.immediate = false
@request.mode = 'checkid_setup'
resp = @request.answer(false)
assert(resp.fields.get_arg(OPENID_NS, 'mode') == 'cancel')
end
def test_immediate_openid1_no_server_url
@request.message = Message.new(OPENID1_NS)
@request.immediate = true
@request.mode = 'checkid_immediate'
@request.op_endpoint = nil
assert_raises(ArgumentError) {
@request.answer(false)
}
end
def test_immediate_encode_to_url
@request.message = Message.new(OPENID1_NS)
@request.immediate = true
@request.mode = 'checkid_immediate'
@request.trust_root = "BOGUS"
@request.assoc_handle = "ASSOC"
server_url = "http://server.com/server"
url = @request.encode_to_url(server_url)
assert(url.start_with?(server_url))
_, query = url.split("?", 2)
args = Util.parse_query(query)
m = Message.from_post_args(args)
assert(m.get_arg(OPENID_NS, 'trust_root') == "BOGUS")
assert(m.get_arg(OPENID_NS, 'assoc_handle') == "ASSOC")
assert(m.get_arg(OPENID_NS, 'mode'), "checkid_immediate")
assert(m.get_arg(OPENID_NS, 'identity') == @request.identity)
assert(m.get_arg(OPENID_NS, 'claimed_id') == @request.claimed_id)
assert(m.get_arg(OPENID_NS, 'return_to') == @request.return_to)
end
def test_answerAllowWithDelegatedIdentityOpenID2
# Answer an IDENTIFIER_SELECT case with a delegated identifier.
# claimed_id delegates to selected_id here.
@request.identity = IDENTIFIER_SELECT
selected_id = 'http://anon.unittest/9861'
claimed_id = 'http://monkeyhat.unittest/'
answer = @request.answer(true, nil, selected_id, claimed_id)
_expectAnswer(answer, selected_id, claimed_id)
end
def test_answerAllowWithDelegatedIdentityOpenID1
# claimed_id parameter doesn't exist in OpenID 1.
@request.message = Message.new(OPENID1_NS)
# claimed_id delegates to selected_id here.
@request.identity = IDENTIFIER_SELECT
selected_id = 'http://anon.unittest/9861'
claimed_id = 'http://monkeyhat.unittest/'
assert_raises(Server::VersionError) {
@request.answer(true, nil, selected_id, claimed_id)
}
end
def test_answerAllowWithAnotherIdentity
# XXX - Check on this, I think this behavior is legal in OpenID
# 2.0?
assert_raises(ArgumentError){
@request.answer(true, nil, "http://pebbles.unittest/")
}
end
def test_answerAllowNoIdentityOpenID1
@request.message = Message.new(OPENID1_NS)
@request.identity = nil
assert_raises(ArgumentError) {
@request.answer(true, nil, nil)
}
end
def test_answerAllowForgotEndpoint
@request.op_endpoint = nil
assert_raises(RuntimeError) {
@request.answer(true)
}
end
def test_checkIDWithNoIdentityOpenID1
msg = Message.new(OPENID1_NS)
msg.set_arg(OPENID_NS, 'return_to', 'bogus')
msg.set_arg(OPENID_NS, 'trust_root', 'bogus')
msg.set_arg(OPENID_NS, 'mode', 'checkid_setup')
msg.set_arg(OPENID_NS, 'assoc_handle', 'bogus')
assert_raises(Server::ProtocolError) {
Server::CheckIDRequest.from_message(msg, @server)
}
end
def test_fromMessageClaimedIDWithoutIdentityOpenID2
msg = Message.new(OPENID2_NS)
msg.set_arg(OPENID_NS, 'mode', 'checkid_setup')
msg.set_arg(OPENID_NS, 'return_to', 'http://invalid:8000/rt')
msg.set_arg(OPENID_NS, 'claimed_id', 'https://example.myopenid.com')
assert_raises(Server::ProtocolError) {
Server::CheckIDRequest.from_message(msg, @server)
}
end
def test_fromMessageIdentityWithoutClaimedIDOpenID2
msg = Message.new(OPENID2_NS)
msg.set_arg(OPENID_NS, 'mode', 'checkid_setup')
msg.set_arg(OPENID_NS, 'return_to', 'http://invalid:8000/rt')
msg.set_arg(OPENID_NS, 'identity', 'https://example.myopenid.com')
assert_raises(Server::ProtocolError) {
Server::CheckIDRequest.from_message(msg, @server)
}
end
def test_fromMessageWithEmptyTrustRoot
return_to = 'http://some.url/foo?bar=baz'
msg = Message.from_post_args({
'openid.assoc_handle' => '{blah}{blah}{OZivdQ==}',
'openid.claimed_id' => 'http://delegated.invalid/',
'openid.identity' => 'http://op-local.example.com/',
'openid.mode' => 'checkid_setup',
'openid.ns' => 'http://openid.net/signon/1.0',
'openid.return_to' => return_to,
'openid.trust_root' => ''
});
result = Server::CheckIDRequest.from_message(msg, @server)
assert_equal(return_to, result.trust_root)
end
def test_trustRootOpenID1
# Ignore openid.realm in OpenID 1
msg = Message.new(OPENID1_NS)
msg.set_arg(OPENID_NS, 'mode', 'checkid_setup')
msg.set_arg(OPENID_NS, 'trust_root', 'http://trustroot.com/')
msg.set_arg(OPENID_NS, 'realm', 'http://fake_trust_root/')
msg.set_arg(OPENID_NS, 'return_to', 'http://trustroot.com/foo')
msg.set_arg(OPENID_NS, 'assoc_handle', 'bogus')
msg.set_arg(OPENID_NS, 'identity', 'george')
result = Server::CheckIDRequest.from_message(msg, @server.op_endpoint)
assert(result.trust_root == 'http://trustroot.com/')
end
def test_trustRootOpenID2
# Ignore openid.trust_root in OpenID 2
msg = Message.new(OPENID2_NS)
msg.set_arg(OPENID_NS, 'mode', 'checkid_setup')
msg.set_arg(OPENID_NS, 'realm', 'http://trustroot.com/')
msg.set_arg(OPENID_NS, 'trust_root', 'http://fake_trust_root/')
msg.set_arg(OPENID_NS, 'return_to', 'http://trustroot.com/foo')
msg.set_arg(OPENID_NS, 'assoc_handle', 'bogus')
msg.set_arg(OPENID_NS, 'identity', 'george')
msg.set_arg(OPENID_NS, 'claimed_id', 'george')
result = Server::CheckIDRequest.from_message(msg, @server.op_endpoint)
assert(result.trust_root == 'http://trustroot.com/')
end
def test_answerAllowNoTrustRoot
@request.trust_root = nil
answer = @request.answer(true)
assert_equal(answer.request, @request)
_expectAnswer(answer, @request.identity)
end
def test_answerImmediateDenyOpenID2
# Look for mode=setup_needed in checkid_immediate negative
# response in OpenID 2 case.
#
# See specification Responding to Authentication Requests /
# Negative Assertions / In Response to Immediate Requests.
@request.mode = 'checkid_immediate'
@request.immediate = true
server_url = "http://setup-url.unittest/"
# crappiting setup_url, you dirty my interface with your presence!
answer = @request.answer(false, server_url)
assert_equal(answer.request, @request)
assert_equal(answer.fields.to_post_args.length, 3, answer.fields)
assert_equal(answer.fields.get_openid_namespace, OPENID2_NS)
assert_equal(answer.fields.get_arg(OPENID_NS, 'mode'),
'setup_needed')
# user_setup_url no longer required.
end
def test_answerImmediateDenyOpenID1
# Look for user_setup_url in checkid_immediate negative response
# in OpenID 1 case.
@request.message = Message.new(OPENID1_NS)
@request.mode = 'checkid_immediate'
@request.immediate = true
@request.claimed_id = 'http://claimed-id.test/'
server_url = "http://setup-url.unittest/"
# crappiting setup_url, you dirty my interface with your presence!
answer = @request.answer(false, server_url)
assert_equal(answer.request, @request)
assert_equal(2, answer.fields.to_post_args.length, answer.fields)
assert_equal(OPENID1_NS, answer.fields.get_openid_namespace)
assert_equal('id_res', answer.fields.get_arg(OPENID_NS, 'mode'))
usu = answer.fields.get_arg(OPENID_NS, 'user_setup_url', '')
assert(usu.start_with?(server_url))
expected_substr = 'openid.claimed_id=http%3A%2F%2Fclaimed-id.test%2F'
assert(!usu.index(expected_substr).nil?, usu)
end
def test_answerSetupDeny
answer = @request.answer(false)
assert_equal(answer.fields.get_args(OPENID_NS), {
'mode' => 'cancel',
})
end
def test_encodeToURL
server_url = 'http://openid-server.unittest/'
result = @request.encode_to_url(server_url)
# How to check? How about a round-trip test.
_, result_args = result.split('?', 2)
result_args = Util.parse_query(result_args)
message = Message.from_post_args(result_args)
rebuilt_request = Server::CheckIDRequest.from_message(message,
@server.op_endpoint)
@request.message = message
@request.instance_variables.each { |var|
assert_equal(@request.instance_variable_get(var),
rebuilt_request.instance_variable_get(var), var)
}
end
def test_getCancelURL
url = @request.cancel_url
rt, query_string = url.split('?', -1)
assert_equal(@request.return_to, rt)
query = Util.parse_query(query_string)
assert_equal(query, {'openid.mode' => 'cancel',
'openid.ns' => OPENID2_NS})
end
def test_getCancelURLimmed
@request.mode = 'checkid_immediate'
@request.immediate = true
assert_raises(ArgumentError) {
@request.cancel_url
}
end
def test_fromMessageWithoutTrustRoot
msg = Message.new(OPENID2_NS)
msg.set_arg(OPENID_NS, 'mode', 'checkid_setup')
msg.set_arg(OPENID_NS, 'return_to', 'http://real.trust.root/foo')
msg.set_arg(OPENID_NS, 'assoc_handle', 'bogus')
msg.set_arg(OPENID_NS, 'identity', 'george')
msg.set_arg(OPENID_NS, 'claimed_id', 'george')
result = Server::CheckIDRequest.from_message(msg, @server.op_endpoint)
assert_equal(result.trust_root, 'http://real.trust.root/foo')
end
def test_fromMessageWithoutTrustRootOrReturnTo
msg = Message.new(OPENID2_NS)
msg.set_arg(OPENID_NS, 'mode', 'checkid_setup')
msg.set_arg(OPENID_NS, 'assoc_handle', 'bogus')
msg.set_arg(OPENID_NS, 'identity', 'george')
msg.set_arg(OPENID_NS, 'claimed_id', 'george')
assert_raises(Server::ProtocolError) {
Server::CheckIDRequest.from_message(msg, @server.op_endpoint)
}
end
end
class TestCheckIDExtension < Minitest::Test
def setup
@op_endpoint = 'http://endpoint.unittest/ext'
@store = Store::Memory.new()
@server = Server::Server.new(@store, @op_endpoint)
@request = Server::CheckIDRequest.new(
'http://bambam.unittest/',
'http://bar.unittest/999',
@server.op_endpoint,
'http://bar.unittest/',
false)
@request.message = Message.new(OPENID2_NS)
@response = Server::OpenIDResponse.new(@request)
@response.fields.set_arg(OPENID_NS, 'mode', 'id_res')
@response.fields.set_arg(OPENID_NS, 'blue', 'star')
end
def test_addField
namespace = 'something:'
@response.fields.set_arg(namespace, 'bright', 'potato')
assert_equal(@response.fields.get_args(OPENID_NS),
{'blue' => 'star',
'mode' => 'id_res',
})
assert_equal(@response.fields.get_args(namespace),
{'bright' => 'potato'})
end
def test_addFields
namespace = 'mi5:'
args = {'tangy' => 'suspenders',
'bravo' => 'inclusion'}
@response.fields.update_args(namespace, args)
assert_equal(@response.fields.get_args(OPENID_NS),
{'blue' => 'star',
'mode' => 'id_res',
})
assert_equal(@response.fields.get_args(namespace), args)
end
end
class MockSignatory
attr_accessor :isValid, :assocs
def initialize(assoc)
@isValid = true
@assocs = [assoc]
end
def verify(assoc_handle, message)
Util.assert(message.has_key?(OPENID_NS, "sig"))
if self.assocs.member?([true, assoc_handle])
return @isValid
else
return false
end
end
def get_association(assoc_handle, dumb)
if self.assocs.member?([dumb, assoc_handle])
# This isn't a valid implementation for many uses of this
# function, mind you.
return true
else
return nil
end
end
def invalidate(assoc_handle, dumb)
if self.assocs.member?([dumb, assoc_handle])
@assocs.delete([dumb, assoc_handle])
end
end
end
class TestCheckAuth < Minitest::Test
def setup
@assoc_handle = 'mooooooooo'
@message = Message.from_post_args({
'openid.sig' => 'signarture',
'one' => 'alpha',
'two' => 'beta',
})
@request = Server::CheckAuthRequest.new(
@assoc_handle, @message)
@request.message = Message.new(OPENID2_NS)
@signatory = MockSignatory.new([true, @assoc_handle])
end
def test_to_s
@request.to_s
end
def test_valid
r = @request.answer(@signatory)
assert_equal({'is_valid' => 'true'},
r.fields.get_args(OPENID_NS))
assert_equal(r.request, @request)
end
def test_invalid
@signatory.isValid = false
r = @request.answer(@signatory)
assert_equal({'is_valid' => 'false'},
r.fields.get_args(OPENID_NS))
end
def test_replay
# Don't validate the same response twice.
#
# From "Checking the Nonce"::
#
# When using "check_authentication", the OP MUST ensure that an
# assertion has not yet been accepted with the same value for
# "openid.response_nonce".
#
# In this implementation, the assoc_handle is only valid once.
# And nonces are a signed component of the message, so they can't
# be used with another handle without breaking the sig.
r = @request.answer(@signatory)
r = @request.answer(@signatory)
assert_equal({'is_valid' => 'false'},
r.fields.get_args(OPENID_NS))
end
def test_invalidatehandle
@request.invalidate_handle = "bogusHandle"
r = @request.answer(@signatory)
assert_equal(r.fields.get_args(OPENID_NS),
{'is_valid' => 'true',
'invalidate_handle' => "bogusHandle"})
assert_equal(r.request, @request)
end
def test_invalidatehandleNo
assoc_handle = 'goodhandle'
@signatory.assocs << [false, 'goodhandle']
@request.invalidate_handle = assoc_handle
r = @request.answer(@signatory)
assert_equal(r.fields.get_args(OPENID_NS), {'is_valid' => 'true'})
end
end
class TestAssociate < Minitest::Test
# TODO: test DH with non-default values for modulus and gen.
# (important to do because we actually had it broken for a while.)
def setup
@request = Server::AssociateRequest.from_message(Message.from_post_args({}))
@store = Store::Memory.new()
@signatory = Server::Signatory.new(@store)
end
def test_dhSHA1
@assoc = @signatory.create_association(false, 'HMAC-SHA1')
consumer_dh = DiffieHellman.from_defaults()
cpub = consumer_dh.public
server_dh = DiffieHellman.from_defaults()
session = Server::DiffieHellmanSHA1ServerSession.new(server_dh, cpub)
@request = Server::AssociateRequest.new(session, 'HMAC-SHA1')
@request.message = Message.new(OPENID2_NS)
response = @request.answer(@assoc)
rfg = lambda { |f| response.fields.get_arg(OPENID_NS, f) }
assert_equal(rfg.call("assoc_type"), "HMAC-SHA1")
assert_equal(rfg.call("assoc_handle"), @assoc.handle)
assert(!rfg.call("mac_key"))
assert_equal(rfg.call("session_type"), "DH-SHA1")
assert(rfg.call("enc_mac_key"))
assert(rfg.call("dh_server_public"))
enc_key = Util.from_base64(rfg.call("enc_mac_key"))
spub = CryptUtil.base64_to_num(rfg.call("dh_server_public"))
secret = consumer_dh.xor_secret(CryptUtil.method('sha1'),
spub, enc_key)
assert_equal(secret, @assoc.secret)
end
def test_dhSHA256
@assoc = @signatory.create_association(false, 'HMAC-SHA256')
consumer_dh = DiffieHellman.from_defaults()
cpub = consumer_dh.public
server_dh = DiffieHellman.from_defaults()
session = Server::DiffieHellmanSHA256ServerSession.new(server_dh, cpub)
@request = Server::AssociateRequest.new(session, 'HMAC-SHA256')
@request.message = Message.new(OPENID2_NS)
response = @request.answer(@assoc)
rfg = lambda { |f| response.fields.get_arg(OPENID_NS, f) }
assert_equal(rfg.call("assoc_type"), "HMAC-SHA256")
assert_equal(rfg.call("assoc_handle"), @assoc.handle)
assert(!rfg.call("mac_key"))
assert_equal(rfg.call("session_type"), "DH-SHA256")
assert(rfg.call("enc_mac_key"))
assert(rfg.call("dh_server_public"))
enc_key = Util.from_base64(rfg.call("enc_mac_key"))
spub = CryptUtil.base64_to_num(rfg.call("dh_server_public"))
secret = consumer_dh.xor_secret(CryptUtil.method('sha256'),
spub, enc_key)
assert_equal(secret, @assoc.secret)
end
def test_protoError256
s256_session = Consumer::DiffieHellmanSHA256Session.new()
invalid_s256 = {'openid.assoc_type' => 'HMAC-SHA1',
'openid.session_type' => 'DH-SHA256',}
invalid_s256.merge!(s256_session.get_request())
invalid_s256_2 = {'openid.assoc_type' => 'MONKEY-PIRATE',
'openid.session_type' => 'DH-SHA256',}
invalid_s256_2.merge!(s256_session.get_request())
bad_request_argss = [
invalid_s256,
invalid_s256_2,
]
bad_request_argss.each { |request_args|
message = Message.from_post_args(request_args)
assert_raises(Server::ProtocolError) {
Server::AssociateRequest.from_message(message)
}
}
end
def test_protoError
s1_session = Consumer::DiffieHellmanSHA1Session.new()
invalid_s1 = {'openid.assoc_type' => 'HMAC-SHA256',
'openid.session_type' => 'DH-SHA1',}
invalid_s1.merge!(s1_session.get_request())
invalid_s1_2 = {'openid.assoc_type' => 'ROBOT-NINJA',
'openid.session_type' => 'DH-SHA1',}
invalid_s1_2.merge!(s1_session.get_request())
bad_request_argss = [
{'openid.assoc_type' => 'Wha?'},
invalid_s1,
invalid_s1_2,
]
bad_request_argss.each { |request_args|
message = Message.from_post_args(request_args)
assert_raises(Server::ProtocolError) {
Server::AssociateRequest.from_message(message)
}
}
end
def test_protoErrorFields
contact = 'user@example.invalid'
reference = 'Trac ticket number MAX_INT'
error = 'poltergeist'
openid1_args = {
'openid.identitiy' => 'invalid',
'openid.mode' => 'checkid_setup',
}
openid2_args = openid1_args.dup
openid2_args.merge!({'openid.ns' => OPENID2_NS})
# Check presence of optional fields in both protocol versions
openid1_msg = Message.from_post_args(openid1_args)
p = Server::ProtocolError.new(openid1_msg, error,
reference, contact)
reply = p.to_message()
assert_equal(reply.get_arg(OPENID_NS, 'reference'), reference)
assert_equal(reply.get_arg(OPENID_NS, 'contact'), contact)
openid2_msg = Message.from_post_args(openid2_args)
p = Server::ProtocolError.new(openid2_msg, error,
reference, contact)
reply = p.to_message()
assert_equal(reply.get_arg(OPENID_NS, 'reference'), reference)
assert_equal(reply.get_arg(OPENID_NS, 'contact'), contact)
end
def failUnlessExpiresInMatches(msg, expected_expires_in)
expires_in_str = msg.get_arg(OPENID_NS, 'expires_in', NO_DEFAULT)
expires_in = expires_in_str.to_i
# Slop is necessary because the tests can sometimes get run
# right on a second boundary
slop = 1 # second
difference = expected_expires_in - expires_in
error_message = sprintf('"expires_in" value not within %s of expected: ' +
'expected=%s, actual=%s', slop, expected_expires_in,
expires_in)
assert((0 <= difference and difference <= slop), error_message)
end
def test_plaintext
@assoc = @signatory.create_association(false, 'HMAC-SHA1')
response = @request.answer(@assoc)
rfg = lambda { |f| response.fields.get_arg(OPENID_NS, f) }
assert_equal(rfg.call("assoc_type"), "HMAC-SHA1")
assert_equal(rfg.call("assoc_handle"), @assoc.handle)
failUnlessExpiresInMatches(response.fields,
@signatory.secret_lifetime)
assert_equal(
rfg.call("mac_key"), Util.to_base64(@assoc.secret))
assert(!rfg.call("session_type"))
assert(!rfg.call("enc_mac_key"))
assert(!rfg.call("dh_server_public"))
end
def test_plaintext_v2
# The main difference between this and the v1 test is that
# session_type is always returned in v2.
args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'associate',
'openid.assoc_type' => 'HMAC-SHA1',
'openid.session_type' => 'no-encryption',
}
@request = Server::AssociateRequest.from_message(
Message.from_post_args(args))
assert(!@request.message.is_openid1())
@assoc = @signatory.create_association(false, 'HMAC-SHA1')
response = @request.answer(@assoc)
rfg = lambda { |f| response.fields.get_arg(OPENID_NS, f) }
assert_equal(rfg.call("assoc_type"), "HMAC-SHA1")
assert_equal(rfg.call("assoc_handle"), @assoc.handle)
failUnlessExpiresInMatches(
response.fields, @signatory.secret_lifetime)
assert_equal(
rfg.call("mac_key"), Util.to_base64(@assoc.secret))
assert_equal(rfg.call("session_type"), "no-encryption")
assert(!rfg.call("enc_mac_key"))
assert(!rfg.call("dh_server_public"))
end
def test_plaintext256
@assoc = @signatory.create_association(false, 'HMAC-SHA256')
response = @request.answer(@assoc)
rfg = lambda { |f| response.fields.get_arg(OPENID_NS, f) }
assert_equal(rfg.call("assoc_type"), "HMAC-SHA1")
assert_equal(rfg.call("assoc_handle"), @assoc.handle)
failUnlessExpiresInMatches(
response.fields, @signatory.secret_lifetime)
assert_equal(
rfg.call("mac_key"), Util.to_base64(@assoc.secret))
assert(!rfg.call("session_type"))
assert(!rfg.call("enc_mac_key"))
assert(!rfg.call("dh_server_public"))
end
def test_unsupportedPrefer
allowed_assoc = 'COLD-PET-RAT'
allowed_sess = 'FROG-BONES'
message = 'This is a unit test'
# Set an OpenID 2 message so answerUnsupported doesn't raise
# ProtocolError.
@request.message = Message.new(OPENID2_NS)
response = @request.answer_unsupported(message,
allowed_assoc,
allowed_sess)
rfg = lambda { |f| response.fields.get_arg(OPENID_NS, f) }
assert_equal(rfg.call('error_code'), 'unsupported-type')
assert_equal(rfg.call('assoc_type'), allowed_assoc)
assert_equal(rfg.call('error'), message)
assert_equal(rfg.call('session_type'), allowed_sess)
end
def test_unsupported
message = 'This is a unit test'
# Set an OpenID 2 message so answerUnsupported doesn't raise
# ProtocolError.
@request.message = Message.new(OPENID2_NS)
response = @request.answer_unsupported(message)
rfg = lambda { |f| response.fields.get_arg(OPENID_NS, f) }
assert_equal(rfg.call('error_code'), 'unsupported-type')
assert_equal(rfg.call('assoc_type'), nil)
assert_equal(rfg.call('error'), message)
assert_equal(rfg.call('session_type'), nil)
end
def test_openid1_unsupported_explode
# answer_unsupported on an associate request should explode if
# the request was an OpenID 1 request.
m = Message.new(OPENID1_NS)
assert_raises(Server::ProtocolError) {
@request.answer_unsupported(m)
}
end
end
class UnhandledError < Exception
end
class TestServer < Minitest::Test
include TestUtil
def setup
@store = Store::Memory.new()
@server = Server::Server.new(@store, "http://server.unittest/endpt")
# catchlogs_setup()
end
def test_failed_dispatch
request = Server::OpenIDRequest.new()
request.mode = "monkeymode"
request.message = Message.new(OPENID1_NS)
assert_raises(RuntimeError) {
@server.handle_request(request)
}
end
def test_decode_request
@server.decoder = BogusDecoder.new(@server)
assert(@server.decode_request({}) == "BOGUS")
end
def test_encode_response
@server.encoder = BogusEncoder.new
assert(@server.encode_response(nil) == "BOGUS")
end
def test_dispatch
@server.extend(InstanceDefExtension)
@server.instance_def(:openid_monkeymode) do |request|
raise UnhandledError
end
request = Server::OpenIDRequest.new()
request.mode = "monkeymode"
request.message = Message.new(OPENID1_NS)
assert_raises(UnhandledError) {
@server.handle_request(request)
}
end
def test_associate
request = Server::AssociateRequest.from_message(Message.from_post_args({}))
response = @server.openid_associate(request)
assert(response.fields.has_key?(OPENID_NS, "assoc_handle"),
sprintf("No assoc_handle here: %s", response.fields.inspect))
end
def test_associate2
# Associate when the server has no allowed association types
#
# Gives back an error with error_code and no fallback session or
# assoc types.
@server.negotiator.allowed_types = []
# Set an OpenID 2 message so answerUnsupported doesn't raise
# ProtocolError.
msg = Message.from_post_args({
'openid.ns' => OPENID2_NS,
'openid.session_type' => 'no-encryption',
})
request = Server::AssociateRequest.from_message(msg)
response = @server.openid_associate(request)
assert(response.fields.has_key?(OPENID_NS, "error"))
assert(response.fields.has_key?(OPENID_NS, "error_code"))
assert(!response.fields.has_key?(OPENID_NS, "assoc_handle"))
assert(!response.fields.has_key?(OPENID_NS, "assoc_type"))
assert(!response.fields.has_key?(OPENID_NS, "session_type"))
end
def test_associate3
# Request an assoc type that is not supported when there are
# supported types.
#
# Should give back an error message with a fallback type.
@server.negotiator.allowed_types = [['HMAC-SHA256', 'DH-SHA256']]
msg = Message.from_post_args({
'openid.ns' => OPENID2_NS,
'openid.session_type' => 'no-encryption',
})
request = Server::AssociateRequest.from_message(msg)
response = @server.openid_associate(request)
assert(response.fields.has_key?(OPENID_NS, "error"))
assert(response.fields.has_key?(OPENID_NS, "error_code"))
assert(!response.fields.has_key?(OPENID_NS, "assoc_handle"))
assert_equal(response.fields.get_arg(OPENID_NS, "assoc_type"),
'HMAC-SHA256')
assert_equal(response.fields.get_arg(OPENID_NS, "session_type"),
'DH-SHA256')
end
def test_associate4
# DH-SHA256 association session
@server.negotiator.allowed_types = [['HMAC-SHA256', 'DH-SHA256']]
query = {
'openid.dh_consumer_public' =>
'ALZgnx8N5Lgd7pCj8K86T/DDMFjJXSss1SKoLmxE72kJTzOtG6I2PaYrHX' +
'xku4jMQWSsGfLJxwCZ6280uYjUST/9NWmuAfcrBfmDHIBc3H8xh6RBnlXJ' +
'1WxJY3jHd5k1/ZReyRZOxZTKdF/dnIqwF8ZXUwI6peV0TyS/K1fOfF/s',
'openid.assoc_type' => 'HMAC-SHA256',
'openid.session_type' => 'DH-SHA256',
}
message = Message.from_post_args(query)
request = Server::AssociateRequest.from_message(message)
response = @server.openid_associate(request)
assert(response.fields.has_key?(OPENID_NS, "assoc_handle"))
end
def test_no_encryption_openid1
# Make sure no-encryption associate requests for OpenID 1 are
# logged.
assert_log_matches(/Continuing anyway./) {
m = Message.from_openid_args({
'session_type' => 'no-encryption',
})
Server::AssociateRequest.from_message(m)
}
end
def test_missingSessionTypeOpenID2
# Make sure session_type is required in OpenID 2
msg = Message.from_post_args({
'openid.ns' => OPENID2_NS,
})
assert_raises(Server::ProtocolError) {
Server::AssociateRequest.from_message(msg)
}
end
def test_checkAuth
request = Server::CheckAuthRequest.new('arrrrrf', '0x3999', [])
request.message = Message.new(OPENID2_NS)
response = nil
silence_logging {
response = @server.openid_check_authentication(request)
}
assert(response.fields.has_key?(OPENID_NS, "is_valid"))
end
end
class TestingRequest < Server::OpenIDRequest
attr_accessor :assoc_handle, :namespace
end
class TestSignatory < Minitest::Test
include TestUtil
def setup
@store = Store::Memory.new()
@signatory = Server::Signatory.new(@store)
@_dumb_key = @signatory.class._dumb_key
@_normal_key = @signatory.class._normal_key
# CatchLogs.setUp(self)
end
def test_get_association_nil
assert_raises(ArgumentError) {
@signatory.get_association(nil, false)
}
end
def test_sign
request = TestingRequest.new()
assoc_handle = '{assoc}{lookatme}'
@store.store_association(
@_normal_key,
Association.from_expires_in(60, assoc_handle,
'sekrit', 'HMAC-SHA1'))
request.assoc_handle = assoc_handle
request.namespace = OPENID1_NS
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'foo' => 'amsigned',
'bar' => 'notsigned',
'azu' => 'alsosigned',
})
sresponse = @signatory.sign(response)
assert_equal(
sresponse.fields.get_arg(OPENID_NS, 'assoc_handle'),
assoc_handle)
assert_equal(sresponse.fields.get_arg(OPENID_NS, 'signed'),
'assoc_handle,azu,bar,foo,signed')
assert(sresponse.fields.get_arg(OPENID_NS, 'sig'))
# assert(!@messages, @messages)
end
def test_signDumb
request = TestingRequest.new()
request.assoc_handle = nil
request.namespace = OPENID2_NS
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'foo' => 'amsigned',
'bar' => 'notsigned',
'azu' => 'alsosigned',
'ns' => OPENID2_NS,
})
sresponse = @signatory.sign(response)
assoc_handle = sresponse.fields.get_arg(OPENID_NS, 'assoc_handle')
assert(assoc_handle)
assoc = @signatory.get_association(assoc_handle, true)
assert(assoc)
assert_equal(sresponse.fields.get_arg(OPENID_NS, 'signed'),
'assoc_handle,azu,bar,foo,ns,signed')
assert(sresponse.fields.get_arg(OPENID_NS, 'sig'))
# assert(!@messages, @messages)
end
def test_signExpired
# Sign a response to a message with an expired handle (using
# invalidate_handle).
#
# From "Verifying with an Association":
#
# If an authentication request included an association handle
# for an association between the OP and the Relying party, and
# the OP no longer wishes to use that handle (because it has
# expired or the secret has been compromised, for instance),
# the OP will send a response that must be verified directly
# with the OP, as specified in Section 11.3.2. In that
# instance, the OP will include the field
# "openid.invalidate_handle" set to the association handle
# that the Relying Party included with the original request.
request = TestingRequest.new()
request.namespace = OPENID2_NS
assoc_handle = '{assoc}{lookatme}'
@store.store_association(
@_normal_key,
Association.from_expires_in(-10, assoc_handle,
'sekrit', 'HMAC-SHA1'))
assert(@store.get_association(@_normal_key, assoc_handle))
request.assoc_handle = assoc_handle
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'foo' => 'amsigned',
'bar' => 'notsigned',
'azu' => 'alsosigned',
})
sresponse = nil
silence_logging {
sresponse = @signatory.sign(response)
}
new_assoc_handle = sresponse.fields.get_arg(OPENID_NS, 'assoc_handle')
assert(new_assoc_handle)
assert(new_assoc_handle != assoc_handle)
assert_equal(
sresponse.fields.get_arg(OPENID_NS, 'invalidate_handle'),
assoc_handle)
assert_equal(sresponse.fields.get_arg(OPENID_NS, 'signed'),
'assoc_handle,azu,bar,foo,invalidate_handle,signed')
assert(sresponse.fields.get_arg(OPENID_NS, 'sig'))
# make sure the expired association is gone
assert(!@store.get_association(@_normal_key, assoc_handle),
"expired association is still retrievable.")
# make sure the new key is a dumb mode association
assert(@store.get_association(@_dumb_key, new_assoc_handle))
assert(!@store.get_association(@_normal_key, new_assoc_handle))
# assert(@messages)
end
def test_signInvalidHandle
request = TestingRequest.new()
request.namespace = OPENID2_NS
assoc_handle = '{bogus-assoc}{notvalid}'
request.assoc_handle = assoc_handle
response = Server::OpenIDResponse.new(request)
response.fields = Message.from_openid_args({
'foo' => 'amsigned',
'bar' => 'notsigned',
'azu' => 'alsosigned',
})
sresponse = @signatory.sign(response)
new_assoc_handle = sresponse.fields.get_arg(OPENID_NS, 'assoc_handle')
assert(new_assoc_handle)
assert(new_assoc_handle != assoc_handle)
assert_equal(
sresponse.fields.get_arg(OPENID_NS, 'invalidate_handle'),
assoc_handle)
assert_equal(
sresponse.fields.get_arg(OPENID_NS, 'signed'),
'assoc_handle,azu,bar,foo,invalidate_handle,signed')
assert(sresponse.fields.get_arg(OPENID_NS, 'sig'))
# make sure the new key is a dumb mode association
assert(@store.get_association(@_dumb_key, new_assoc_handle))
assert(!@store.get_association(@_normal_key, new_assoc_handle))
# @failIf(@messages, @messages)
end
def test_verify
assoc_handle = '{vroom}{zoom}'
assoc = Association.from_expires_in(
60, assoc_handle, 'sekrit', 'HMAC-SHA1')
@store.store_association(@_dumb_key, assoc)
signed = Message.from_post_args({
'openid.foo' => 'bar',
'openid.apple' => 'orange',
'openid.assoc_handle' => assoc_handle,
'openid.signed' => 'apple,assoc_handle,foo,signed',
'openid.sig' => 'uXoT1qm62/BB09Xbj98TQ8mlBco=',
})
verified = @signatory.verify(assoc_handle, signed)
assert(verified)
# assert(!@messages, @messages)
end
def test_verifyBadSig
assoc_handle = '{vroom}{zoom}'
assoc = Association.from_expires_in(
60, assoc_handle, 'sekrit', 'HMAC-SHA1')
@store.store_association(@_dumb_key, assoc)
signed = Message.from_post_args({
'openid.foo' => 'bar',
'openid.apple' => 'orange',
'openid.assoc_handle' => assoc_handle,
'openid.signed' => 'apple,assoc_handle,foo,signed',
'openid.sig' => 'uXoT1qm62/BB09Xbj98TQ8mlBco=BOGUS'
})
verified = @signatory.verify(assoc_handle, signed)
# @failIf(@messages, @messages)
assert(!verified)
end
def test_verifyBadHandle
assoc_handle = '{vroom}{zoom}'
signed = Message.from_post_args({
'foo' => 'bar',
'apple' => 'orange',
'openid.sig' => "Ylu0KcIR7PvNegB/K41KpnRgJl0=",
})
verified = nil
silence_logging {
verified = @signatory.verify(assoc_handle, signed)
}
assert !verified
end
def test_verifyAssocMismatch
# Attempt to validate sign-all message with a signed-list assoc.
assoc_handle = '{vroom}{zoom}'
assoc = Association.from_expires_in(
60, assoc_handle, 'sekrit', 'HMAC-SHA1')
@store.store_association(@_dumb_key, assoc)
signed = Message.from_post_args({
'foo' => 'bar',
'apple' => 'orange',
'openid.sig' => "d71xlHtqnq98DonoSgoK/nD+QRM=",
})
verified = nil
silence_logging {
verified = @signatory.verify(assoc_handle, signed)
}
assert !verified
end
def test_getAssoc
assoc_handle = makeAssoc(true)
assoc = @signatory.get_association(assoc_handle, true)
assert assoc
assert_equal assoc.handle, assoc_handle
end
def test_getAssocExpired
assoc_handle = makeAssoc(true, -10)
assoc = nil
silence_logging {
assoc = @signatory.get_association(assoc_handle, true)
}
assert !assoc
end
def test_getAssocInvalid
ah = 'no-such-handle'
silence_logging {
assert_equal(
@signatory.get_association(ah, false), nil)
}
# assert(!@messages, @messages)
end
def test_getAssocDumbVsNormal
# getAssociation(dumb=False) cannot get a dumb assoc
assoc_handle = makeAssoc(true)
silence_logging {
assert_equal(
@signatory.get_association(assoc_handle, false), nil)
}
# @failIf(@messages, @messages)
end
def test_getAssocNormalVsDumb
# getAssociation(dumb=True) cannot get a shared assoc
#
# From "Verifying Directly with the OpenID Provider"::
#
# An OP MUST NOT verify signatures for associations that have shared
# MAC keys.
assoc_handle = makeAssoc(false)
silence_logging {
assert_equal(
@signatory.get_association(assoc_handle, true), nil)
}
# @failIf(@messages, @messages)
end
def test_createAssociation
assoc = @signatory.create_association(false)
silence_logging {
assert(@signatory.get_association(assoc.handle, false))
}
# @failIf(@messages, @messages)
end
def makeAssoc(dumb, lifetime=60)
assoc_handle = '{bling}'
assoc = Association.from_expires_in(lifetime, assoc_handle,
'sekrit', 'HMAC-SHA1')
silence_logging {
@store.store_association(((dumb and @_dumb_key) or @_normal_key), assoc)
}
return assoc_handle
end
def test_invalidate
assoc_handle = '-squash-'
assoc = Association.from_expires_in(60, assoc_handle,
'sekrit', 'HMAC-SHA1')
silence_logging {
@store.store_association(@_dumb_key, assoc)
assoc = @signatory.get_association(assoc_handle, true)
assert(assoc)
assoc = @signatory.get_association(assoc_handle, true)
assert(assoc)
@signatory.invalidate(assoc_handle, true)
assoc = @signatory.get_association(assoc_handle, true)
assert(!assoc)
}
# @failIf(@messages, @messages)
end
end
class RunthroughTestCase < Minitest::Test
def setup
@store = Store::Memory.new
@server = Server::Server.new(@store, "http://example.com/openid/server")
end
def test_openid1_assoc_checkid
assoc_args = {'openid.mode' => 'associate',
'openid.assoc_type' => 'HMAC-SHA1'}
areq = @server.decode_request(assoc_args)
aresp = @server.handle_request(areq)
amess = aresp.fields
assert(amess.is_openid1)
ahandle = amess.get_arg(OPENID_NS, 'assoc_handle')
assert(ahandle)
assoc = @store.get_association('http://localhost/|normal', ahandle)
assert(assoc.is_a?(Association))
checkid_args = {'openid.mode' => 'checkid_setup',
'openid.return_to' => 'http://example.com/openid/consumer',
'openid.assoc_handle' => ahandle,
'openid.identity' => 'http://foo.com/'}
cireq = @server.decode_request(checkid_args)
ciresp = cireq.answer(true)
signed_resp = @server.signatory.sign(ciresp)
assert_equal(assoc.get_message_signature(signed_resp.fields),
signed_resp.fields.get_arg(OPENID_NS, 'sig'))
assert(assoc.check_message_signature(signed_resp.fields))
end
end
end
ruby-openid-2.7.0debian.orig/test/test_associationmanager.rb 0000644 0001750 0001750 00000072525 12512544714 023541 0 ustar sbadia sbadia require "minitest/autorun"
require "testutil"
require "openid/consumer/associationmanager"
require "openid/association"
require "openid/dh"
require "openid/util"
require "openid/cryptutil"
require "openid/message"
require "openid/protocolerror"
require "openid/store/memory"
require "util"
require "time"
module OpenID
class DHAssocSessionTest < Minitest::Test
def test_sha1_get_request
# Initialized without an explicit DH gets defaults
sess = Consumer::DiffieHellmanSHA1Session.new
assert_equal(['dh_consumer_public'], sess.get_request.keys)
Util::from_base64(sess.get_request['dh_consumer_public'])
end
def test_sha1_get_request_custom_dh
dh = DiffieHellman.new(1299721, 2)
sess = Consumer::DiffieHellmanSHA1Session.new(dh)
req = sess.get_request
assert_equal(['dh_consumer_public', 'dh_modulus', 'dh_gen'].sort,
req.keys.sort)
assert_equal(dh.modulus, CryptUtil.base64_to_num(req['dh_modulus']))
assert_equal(dh.generator, CryptUtil.base64_to_num(req['dh_gen']))
Util::from_base64(req['dh_consumer_public'])
end
end
module TestDiffieHellmanResponseParametersMixin
def setup
session_cls = self.class.session_cls
# Pre-compute DH with small prime so tests run quickly.
@server_dh = DiffieHellman.new(100389557, 2)
@consumer_dh = DiffieHellman.new(100389557, 2)
# base64(btwoc(g ^ xb mod p))
@dh_server_public = CryptUtil.num_to_base64(@server_dh.public)
@secret = CryptUtil.random_string(session_cls.secret_size)
enc_mac_key_unencoded =
@server_dh.xor_secret(session_cls.hashfunc,
@consumer_dh.public,
@secret)
@enc_mac_key = Util.to_base64(enc_mac_key_unencoded)
@consumer_session = session_cls.new(@consumer_dh)
@msg = Message.new(self.class.message_namespace)
end
def test_extract_secret
@msg.set_arg(OPENID_NS, 'dh_server_public', @dh_server_public)
@msg.set_arg(OPENID_NS, 'enc_mac_key', @enc_mac_key)
extracted = @consumer_session.extract_secret(@msg)
assert_equal(extracted, @secret)
end
def test_absent_serve_public
@msg.set_arg(OPENID_NS, 'enc_mac_key', @enc_mac_key)
assert_raises(Message::KeyNotFound) {
@consumer_session.extract_secret(@msg)
}
end
def test_absent_mac_key
@msg.set_arg(OPENID_NS, 'dh_server_public', @dh_server_public)
assert_raises(Message::KeyNotFound) {
@consumer_session.extract_secret(@msg)
}
end
def test_invalid_base64_public
@msg.set_arg(OPENID_NS, 'dh_server_public', 'n o t b a s e 6 4.')
@msg.set_arg(OPENID_NS, 'enc_mac_key', @enc_mac_key)
assert_raises(ArgumentError) {
@consumer_session.extract_secret(@msg)
}
end
def test_invalid_base64_mac_key
@msg.set_arg(OPENID_NS, 'dh_server_public', @dh_server_public)
@msg.set_arg(OPENID_NS, 'enc_mac_key', 'n o t base 64')
assert_raises(ArgumentError) {
@consumer_session.extract_secret(@msg)
}
end
end
class TestConsumerOpenID1DHSHA1 < Minitest::Test
include TestDiffieHellmanResponseParametersMixin
class << self
attr_reader :session_cls, :message_namespace
end
@session_cls = Consumer::DiffieHellmanSHA1Session
@message_namespace = OPENID1_NS
end
class TestConsumerOpenID2DHSHA1 < Minitest::Test
include TestDiffieHellmanResponseParametersMixin
class << self
attr_reader :session_cls, :message_namespace
end
@session_cls = Consumer::DiffieHellmanSHA1Session
@message_namespace = OPENID2_NS
end
class TestConsumerOpenID2DHSHA256 < Minitest::Test
include TestDiffieHellmanResponseParametersMixin
class << self
attr_reader :session_cls, :message_namespace
end
@session_cls = Consumer::DiffieHellmanSHA256Session
@message_namespace = OPENID2_NS
end
class TestConsumerNoEncryptionSession < Minitest::Test
def setup
@sess = Consumer::NoEncryptionSession.new
end
def test_empty_request
assert_equal(@sess.get_request, {})
end
def test_get_secret
secret = 'shhh!' * 4
mac_key = Util.to_base64(secret)
msg = Message.from_openid_args({'mac_key' => mac_key})
assert_equal(secret, @sess.extract_secret(msg))
end
end
class TestCreateAssociationRequest < Minitest::Test
def setup
@server_url = 'http://invalid/'
@assoc_manager = Consumer::AssociationManager.new(nil, @server_url)
class << @assoc_manager
def compatibility_mode=(val)
@compatibility_mode = val
end
end
@assoc_type = 'HMAC-SHA1'
end
def test_no_encryption_sends_type
session_type = 'no-encryption'
session, args = @assoc_manager.send(:create_associate_request,
@assoc_type,
session_type)
assert(session.is_a?(Consumer::NoEncryptionSession))
expected = Message.from_openid_args(
{'ns' => OPENID2_NS,
'session_type' => session_type,
'mode' => 'associate',
'assoc_type' => @assoc_type,
})
assert_equal(expected, args)
end
def test_no_encryption_compatibility
@assoc_manager.compatibility_mode = true
session_type = 'no-encryption'
session, args = @assoc_manager.send(:create_associate_request,
@assoc_type,
session_type)
assert(session.is_a?(Consumer::NoEncryptionSession))
assert_equal(Message.from_openid_args({'mode' => 'associate',
'assoc_type' => @assoc_type,
}), args)
end
def test_dh_sha1_compatibility
@assoc_manager.compatibility_mode = true
session_type = 'DH-SHA1'
session, args = @assoc_manager.send(:create_associate_request,
@assoc_type,
session_type)
assert(session.is_a?(Consumer::DiffieHellmanSHA1Session))
# This is a random base-64 value, so just check that it's
# present.
refute_nil(args.get_arg(OPENID1_NS, 'dh_consumer_public'))
args.del_arg(OPENID1_NS, 'dh_consumer_public')
# OK, session_type is set here and not for no-encryption
# compatibility
expected = Message.from_openid_args({'mode' => 'associate',
'session_type' => 'DH-SHA1',
'assoc_type' => @assoc_type,
})
assert_equal(expected, args)
end
end
class TestAssociationManagerExpiresIn < Minitest::Test
def expires_in_msg(val)
msg = Message.from_openid_args({'expires_in' => val})
Consumer::AssociationManager.extract_expires_in(msg)
end
def test_parse_fail
['',
'-2',
' 1',
' ',
'0x00',
'foosball',
'1\n',
'100,000,000,000',
].each do |x|
assert_raises(ProtocolError) {expires_in_msg(x)}
end
end
def test_parse
['0',
'1',
'1000',
'9999999',
'01',
].each do |n|
assert_equal(n.to_i, expires_in_msg(n))
end
end
end
class TestAssociationManagerCreateSession < Minitest::Test
def test_invalid
assert_raises(ArgumentError) {
Consumer::AssociationManager.create_session('monkeys')
}
end
def test_sha256
sess = Consumer::AssociationManager.create_session('DH-SHA256')
assert(sess.is_a?(Consumer::DiffieHellmanSHA256Session))
end
end
module NegotiationTestMixin
include TestUtil
def mk_message(args)
args['ns'] = @openid_ns
Message.from_openid_args(args)
end
def call_negotiate(responses, negotiator=nil)
store = nil
compat = self.class::Compat
assoc_manager = Consumer::AssociationManager.new(store, @server_url,
compat, negotiator)
class << assoc_manager
attr_accessor :responses
def request_association(assoc_type, session_type)
m = @responses.shift
if m.is_a?(Message)
raise ServerError.from_message(m)
else
return m
end
end
end
assoc_manager.responses = responses
assoc_manager.negotiate_association
end
end
# Test the session type negotiation behavior of an OpenID 2
# consumer.
class TestOpenID2SessionNegotiation < Minitest::Test
include NegotiationTestMixin
Compat = false
def setup
@server_url = 'http://invalid/'
@openid_ns = OPENID2_NS
end
# Test the case where the response to an associate request is a
# server error or is otherwise undecipherable.
def test_bad_response
assert_log_matches('Server error when requesting an association') {
assert_equal(call_negotiate([mk_message({})]), nil)
}
end
# Test the case where the association type (assoc_type) returned
# in an unsupported-type response is absent.
def test_empty_assoc_type
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'session_type' => 'new-session-type',
})
assert_log_matches('Unsupported association type',
"Server #{@server_url} responded with unsupported "\
"association session but did not supply a fallback."
) {
assert_equal(call_negotiate([msg]), nil)
}
end
# Test the case where the session type (session_type) returned
# in an unsupported-type response is absent.
def test_empty_session_type
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'new-assoc-type',
})
assert_log_matches('Unsupported association type',
"Server #{@server_url} responded with unsupported "\
"association session but did not supply a fallback."
) {
assert_equal(call_negotiate([msg]), nil)
}
end
# Test the case where an unsupported-type response specifies a
# preferred (assoc_type, session_type) combination that is not
# allowed by the consumer's SessionNegotiator.
def test_not_allowed
negotiator = AssociationNegotiator.new([])
negotiator.instance_eval{
@allowed_types = [['assoc_bogus', 'session_bogus']]
}
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'not-allowed',
'session_type' => 'not-allowed',
})
assert_log_matches('Unsupported association type',
'Server sent unsupported session/association type:') {
assert_equal(call_negotiate([msg], negotiator), nil)
}
end
# Test the case where an unsupported-type response triggers a
# retry to get an association with the new preferred type.
def test_unsupported_with_retry
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'HMAC-SHA1',
'session_type' => 'DH-SHA1',
})
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
assert_log_matches('Unsupported association type') {
assert_equal(assoc, call_negotiate([msg, assoc]))
}
end
# Test the case where an unsupported-typ response triggers a
# retry, but the retry fails and nil is returned instead.
def test_unsupported_with_retry_and_fail
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'HMAC-SHA1',
'session_type' => 'DH-SHA1',
})
assert_log_matches('Unsupported association type',
"Server #{@server_url} refused") {
assert_equal(call_negotiate([msg, msg]), nil)
}
end
# Test the valid case, wherein an association is returned on the
# first attempt to get one.
def test_valid
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
assert_log_matches() {
assert_equal(call_negotiate([assoc]), assoc)
}
end
end
# Tests for the OpenID 1 consumer association session behavior. See
# the docs for TestOpenID2SessionNegotiation. Notice that this
# class is not a subclass of the OpenID 2 tests. Instead, it uses
# many of the same inputs but inspects the log messages logged with
# oidutil.log. See the calls to self.failUnlessLogMatches. Some of
# these tests pass openid2-style messages to the openid 1
# association processing logic to be sure it ignores the extra data.
class TestOpenID1SessionNegotiation < Minitest::Test
include NegotiationTestMixin
Compat = true
def setup
@server_url = 'http://invalid/'
@openid_ns = OPENID1_NS
end
def test_bad_response
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([mk_message({})])
assert_equal(nil, response)
}
end
def test_empty_assoc_type
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'session_type' => 'new-session-type',
})
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([msg])
assert_equal(nil, response)
}
end
def test_empty_session_type
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'new-assoc-type',
})
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([msg])
assert_equal(nil, response)
}
end
def test_not_allowed
negotiator = AssociationNegotiator.new([])
negotiator.instance_eval{
@allowed_types = [['assoc_bogus', 'session_bogus']]
}
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'not-allowed',
'session_type' => 'not-allowed',
})
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([msg])
assert_equal(nil, response)
}
end
def test_unsupported_with_retry
msg = mk_message({'error' => 'Unsupported type',
'error_code' => 'unsupported-type',
'assoc_type' => 'HMAC-SHA1',
'session_type' => 'DH-SHA1',
})
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
assert_log_matches('Server error when requesting an association') {
response = call_negotiate([msg, assoc])
assert_equal(nil, response)
}
end
def test_valid
assoc = Association.new('handle', 'secret', Time.now, 10000, 'HMAC-SHA1')
assert_log_matches() {
response = call_negotiate([assoc])
assert_equal(assoc, response)
}
end
end
class TestExtractAssociation < Minitest::Test
include ProtocolErrorMixin
# An OpenID associate response (without the namespace)
DEFAULTS = {
'expires_in' => '1000',
'assoc_handle' => 'a handle',
'assoc_type' => 'a type',
'session_type' => 'a session type',
}
def setup
@assoc_manager = Consumer::AssociationManager.new(nil, nil)
end
# Make tests that ensure that an association response that is
# missing required fields will raise an Message::KeyNotFound.
#
# According to 'Association Session Response' subsection 'Common
# Response Parameters', the following fields are required for
# OpenID 2.0:
#
# * ns
# * session_type
# * assoc_handle
# * assoc_type
# * expires_in
#
# In OpenID 1, everything except 'session_type' and 'ns' are
# required.
MISSING_FIELD_SETS = ([["no_fields", []]] +
(DEFAULTS.keys.map do |f|
fields = DEFAULTS.keys
fields.delete(f)
["missing_#{f}", fields]
end)
)
[OPENID1_NS, OPENID2_NS].each do |ns|
MISSING_FIELD_SETS.each do |name, fields|
# OpenID 1 is allowed to be missing session_type
if ns != OPENID1_NS and name != 'missing_session_type'
test = lambda do
msg = Message.new(ns)
fields.each do |field|
msg.set_arg(ns, field, DEFAULTS[field])
end
assert_raises(Message::KeyNotFound) do
@assoc_manager.send(:extract_association, msg, nil)
end
end
define_method("test_#{name}", test)
end
end
end
# assert that extracting a response that contains the given
# response session type when the request was made for the given
# request session type will raise a ProtocolError indicating
# session type mismatch
def assert_session_mismatch(req_type, resp_type, ns)
# Create an association session that has "req_type" as its
# session_type and no allowed_assoc_types
assoc_session_class = Class.new do
@session_type = req_type
def self.session_type
@session_type
end
def self.allowed_assoc_types
[]
end
end
assoc_session = assoc_session_class.new
# Build an OpenID 1 or 2 association response message that has
# the specified association session type
msg = Message.new(ns)
msg.update_args(ns, DEFAULTS)
msg.set_arg(ns, 'session_type', resp_type)
# The request type and response type have been chosen to produce
# a session type mismatch.
assert_protocol_error('Session type mismatch') {
@assoc_manager.send(:extract_association, msg, assoc_session)
}
end
[['no-encryption', '', OPENID2_NS],
['DH-SHA1', 'no-encryption', OPENID2_NS],
['DH-SHA256', 'no-encryption', OPENID2_NS],
['no-encryption', 'DH-SHA1', OPENID2_NS],
['DH-SHA1', 'DH-SHA256', OPENID1_NS],
['DH-SHA256', 'DH-SHA1', OPENID1_NS],
['no-encryption', 'DH-SHA1', OPENID1_NS],
].each do |req_type, resp_type, ns|
test = lambda { assert_session_mismatch(req_type, resp_type, ns) }
name = "test_mismatch_req_#{req_type}_resp_#{resp_type}_#{ns}"
define_method(name, test)
end
def test_openid1_no_encryption_fallback
# A DH-SHA1 session
assoc_session = Consumer::DiffieHellmanSHA1Session.new
# An OpenID 1 no-encryption association response
msg = Message.from_openid_args({
'expires_in' => '1000',
'assoc_handle' => 'a handle',
'assoc_type' => 'HMAC-SHA1',
'mac_key' => 'X' * 20,
})
# Should succeed
assoc = @assoc_manager.send(:extract_association, msg, assoc_session)
assert_equal('a handle', assoc.handle)
assert_equal('HMAC-SHA1', assoc.assoc_type)
assert(assoc.expires_in.between?(999, 1000))
assert('X' * 20, assoc.secret)
end
end
class GetOpenIDSessionTypeTest < Minitest::Test
include TestUtil
SERVER_URL = 'http://invalid/'
def do_test(expected_session_type, session_type_value)
# Create a Message with just 'session_type' in it, since
# that's all this function will use. 'session_type' may be
# absent if it's set to None.
args = {}
if !session_type_value.nil?
args['session_type'] = session_type_value
end
message = Message.from_openid_args(args)
assert(message.is_openid1)
assoc_manager = Consumer::AssociationManager.new(nil, SERVER_URL)
actual_session_type = assoc_manager.send(:get_openid1_session_type,
message)
error_message = ("Returned session type parameter #{session_type_value}"\
"was expected to yield session type "\
"#{expected_session_type}, but yielded "\
"#{actual_session_type}")
assert_equal(expected_session_type, actual_session_type, error_message)
end
[['nil', 'no-encryption', nil],
['empty', 'no-encryption', ''],
['dh_sha1', 'DH-SHA1', 'DH-SHA1'],
['dh_sha256', 'DH-SHA256', 'DH-SHA256'],
].each {|name, expected, input|
# Define a test method that will check what session type will be
# used if the OpenID 1 response to an associate call sets the
# 'session_type' field to `session_type_value`
test = lambda {assert_log_matches() { do_test(expected, input) } }
define_method("test_#{name}", &test)
}
# This one's different because it expects log messages
def test_explicit_no_encryption
assert_log_matches("WARNING: #{SERVER_URL} sent 'no-encryption'"){
do_test('no-encryption', 'no-encryption')
}
end
end
class ExtractAssociationTest < Minitest::Test
include ProtocolErrorMixin
SERVER_URL = 'http://invalid/'
def setup
@session_type = 'testing-session'
# This must something that works for Association::from_expires_in
@assoc_type = 'HMAC-SHA1'
@assoc_handle = 'testing-assoc-handle'
# These arguments should all be valid
@assoc_response =
Message.from_openid_args({
'expires_in' => '1000',
'assoc_handle' => @assoc_handle,
'assoc_type' => @assoc_type,
'session_type' => @session_type,
'ns' => OPENID2_NS,
})
assoc_session_cls = Class.new do
class << self
attr_accessor :allowed_assoc_types, :session_type
end
attr_reader :extract_secret_called, :secret
def initialize
@extract_secret_called = false
@secret = 'shhhhh!'
end
def extract_secret(_)
@extract_secret_called = true
@secret
end
end
@assoc_session = assoc_session_cls.new
@assoc_session.class.allowed_assoc_types = [@assoc_type]
@assoc_session.class.session_type = @session_type
@assoc_manager = Consumer::AssociationManager.new(nil, SERVER_URL)
end
def call_extract
@assoc_manager.send(:extract_association,
@assoc_response, @assoc_session)
end
# Handle a full successful association response
def test_works_with_good_fields
assoc = call_extract
assert(@assoc_session.extract_secret_called)
assert_equal(@assoc_session.secret, assoc.secret)
assert_equal(1000, assoc.lifetime)
assert_equal(@assoc_handle, assoc.handle)
assert_equal(@assoc_type, assoc.assoc_type)
end
def test_bad_assoc_type
# Make sure that the assoc type in the response is not valid
# for the given session.
@assoc_session.class.allowed_assoc_types = []
assert_protocol_error('Unsupported assoc_type for sess') {call_extract}
end
def test_bad_expires_in
# Invalid value for expires_in should cause failure
@assoc_response.set_arg(OPENID_NS, 'expires_in', 'forever')
assert_protocol_error('Invalid expires_in') {call_extract}
end
end
class TestExtractAssociationDiffieHellman < Minitest::Test
include ProtocolErrorMixin
SECRET = 'x' * 20
def setup
@assoc_manager = Consumer::AssociationManager.new(nil, nil)
end
def setup_dh
sess, _ = @assoc_manager.send(:create_associate_request,
'HMAC-SHA1', 'DH-SHA1')
server_dh = DiffieHellman.new
cons_dh = sess.instance_variable_get('@dh')
enc_mac_key = server_dh.xor_secret(CryptUtil.method(:sha1),
cons_dh.public, SECRET)
server_resp = {
'dh_server_public' => CryptUtil.num_to_base64(server_dh.public),
'enc_mac_key' => Util.to_base64(enc_mac_key),
'assoc_type' => 'HMAC-SHA1',
'assoc_handle' => 'handle',
'expires_in' => '1000',
'session_type' => 'DH-SHA1',
}
if @assoc_manager.instance_variable_get(:@compatibility_mode)
server_resp['ns'] = OPENID2_NS
end
return [sess, Message.from_openid_args(server_resp)]
end
def test_success
sess, server_resp = setup_dh
ret = @assoc_manager.send(:extract_association, server_resp, sess)
assert(!ret.nil?)
assert_equal(ret.assoc_type, 'HMAC-SHA1')
assert_equal(ret.secret, SECRET)
assert_equal(ret.handle, 'handle')
assert_equal(ret.lifetime, 1000)
end
def test_openid2success
# Use openid 1 type in endpoint so _setUpDH checks
# compatibility mode state properly
@assoc_manager.instance_variable_set('@compatibility_mode', true)
test_success()
end
def test_bad_dh_values
sess, server_resp = setup_dh
server_resp.set_arg(OPENID_NS, 'enc_mac_key', '\x00\x00\x00')
assert_protocol_error('Malformed response for') {
@assoc_manager.send(:extract_association, server_resp, sess)
}
end
end
class TestAssocManagerGetAssociation < Minitest::Test
include FetcherMixin
include TestUtil
attr_reader :negotiate_association
def setup
@server_url = 'http://invalid/'
@store = Store::Memory.new
@assoc_manager = Consumer::AssociationManager.new(@store, @server_url)
@assoc_manager.extend(Const)
@assoc = Association.new('handle', 'secret', Time.now, 10000,
'HMAC-SHA1')
end
def set_negotiate_response(assoc)
@assoc_manager.const(:negotiate_association, assoc)
end
def test_not_in_store_no_response
set_negotiate_response(nil)
assert_equal(nil, @assoc_manager.get_association)
end
def test_not_in_store_negotiate_assoc
# Not stored beforehand:
stored_assoc = @store.get_association(@server_url, @assoc.handle)
assert_equal(nil, stored_assoc)
# Returned from associate call:
set_negotiate_response(@assoc)
assert_equal(@assoc, @assoc_manager.get_association)
# It should have been stored:
stored_assoc = @store.get_association(@server_url, @assoc.handle)
assert_equal(@assoc, stored_assoc)
end
def test_in_store_no_response
set_negotiate_response(nil)
@store.store_association(@server_url, @assoc)
assert_equal(@assoc, @assoc_manager.get_association)
end
def test_request_assoc_with_status_error
fetcher_class = Class.new do
define_method(:fetch) do |*args|
MockResponse.new(500, '')
end
end
with_fetcher(fetcher_class.new) do
assert_log_matches('Got HTTP status error when requesting') {
result = @assoc_manager.send(:request_association, 'HMAC-SHA1',
'no-encryption')
assert(result.nil?)
}
end
end
end
class TestAssocManagerRequestAssociation < Minitest::Test
include FetcherMixin
include TestUtil
def setup
@assoc_manager = Consumer::AssociationManager.new(nil, 'http://invalid/')
@assoc_type = 'HMAC-SHA1'
@session_type = 'no-encryption'
@message = Message.new(OPENID2_NS)
@message.update_args(OPENID_NS, {
'assoc_type' => @assoc_type,
'session_type' => @session_type,
'assoc_handle' => 'kaboodle',
'expires_in' => '1000',
'mac_key' => 'X' * 20,
})
end
def make_request
kv = @message.to_kvform
fetcher_class = Class.new do
define_method(:fetch) do |*args|
MockResponse.new(200, kv)
end
end
with_fetcher(fetcher_class.new) do
@assoc_manager.send(:request_association, @assoc_type, @session_type)
end
end
# The association we get is from valid processing of our result,
# and that no errors are raised
def test_success
assert_equal('kaboodle', make_request.handle)
end
# A missing parameter gets translated into a log message and
# causes the method to return nil
def test_missing_fields
@message.del_arg(OPENID_NS, 'assoc_type')
assert_log_matches('Missing required par') {
assert_equal(nil, make_request)
}
end
# A bad value results in a log message and causes the method to
# return nil
def test_protocol_error
@message.set_arg(OPENID_NS, 'expires_in', 'goats')
assert_log_matches('Protocol error processing') {
assert_equal(nil, make_request)
}
end
end
end
ruby-openid-2.7.0debian.orig/test/test_xrds.rb 0000644 0001750 0001750 00000010644 12512544714 020644 0 ustar sbadia sbadia require 'minitest/autorun'
require 'testutil'
require 'openid/yadis/xrds'
module OpenID
module Yadis
module XRDSTestMixin
include TestDataMixin
XRD_FILE = 'valid-populated-xrds.xml'
NOXRDS_FILE = 'not-xrds.xml'
NOXRD_FILE = 'no-xrd.xml'
XRDS_DATA_DIR = TEST_DATA_DIR.join('test_xrds')
def read_xrds_data_file(filename)
read_data_file(filename, false, XRDS_DATA_DIR)
end
end
class ParseXRDSTestCase < Minitest::Test
include XRDSTestMixin
# Check that parsing succeeds at all.
def test_parse
result = Yadis.parseXRDS(read_xrds_data_file(XRD_FILE))
refute_nil result
end
def test_parse_no_xrds_xml
xmldoc = read_xrds_data_file(NOXRDS_FILE)
assert_raises(Yadis::XRDSError) {
Yadis.parseXRDS(xmldoc)
}
end
def test_parse_no_xrds_empty
assert_raises(Yadis::XRDSError) {
Yadis.parseXRDS('')
}
end
def test_is_xrds
isnt = REXML::Document.new(read_xrds_data_file(NOXRDS_FILE))
should_be = Yadis.parseXRDS(read_xrds_data_file(XRD_FILE))
assert_equal false, Yadis::is_xrds?(isnt)
assert Yadis::is_xrds?(should_be)
end
end
class GetYadisXRDTestCase < Minitest::Test
include XRDSTestMixin
# XXX: Test to make sure this really gets the _right_ XRD.
def test_get_xrd
doc = Yadis.parseXRDS(read_xrds_data_file(XRD_FILE))
result = Yadis::get_yadis_xrd(doc)
refute_nil result
assert_equal 'XRD', result.name
assert_equal Yadis::XRD_NS_2_0, result.namespace
end
def test_no_xrd
xmldoc = read_xrds_data_file(NOXRD_FILE)
doc = Yadis.parseXRDS(xmldoc)
assert_raises(Yadis::XRDSError) {
Yadis.get_yadis_xrd(doc)
}
end
end
class EachServiceTestCase < Minitest::Test
include XRDSTestMixin
def test_get_xrd
doc = Yadis.parseXRDS(read_xrds_data_file(XRD_FILE))
count = 0
result = Yadis::each_service(doc) { |e|
assert_equal 'Service', e.name
count += 1
}
refute_nil result
assert_equal 5, count
end
def test_no_xrd
xmldoc = read_xrds_data_file(NOXRD_FILE)
doc = Yadis.parseXRDS(xmldoc)
assert_raises(Yadis::XRDSError) {
Yadis.each_service(doc)
}
end
def test_equal_j3h
doc = Yadis.parseXRDS(read_xrds_data_file('=j3h.2007.11.14.xrds'))
count = 0
result = Yadis::each_service(doc) { |e|
assert_equal 'Service', e.name
count += 1
}
refute_nil result
assert_equal 2, count
end
end
# XXX: test prioSort!
class ExpandServiceTestCase < Minitest::Test
@@service_xml = < Blah blah blah blah blah blah blah Blah blah blah blah blah blah blah Blah blah blah blah blah blah blah Blah blah blah blah blah blah blah foo foo foo こんにちは foo foo Welcome to the Ruby OpenID example. This code is a starting point
for developers wishing to implement an OpenID provider or relying
party. We've used the Rails
platform to demonstrate, but the library code is not Rails specific.
The server will automatically create an identity page for
you at <%= @base_url %>user/name Because WEBrick can only handle one thing at a time, you'll need to
run another instance of the example on another port if you want to use
a relying party to use with this example provider: (The RP needs to be able to access the provider, so unless you're
running this example on a public IP, you can't use the live example
at openidenabled.com on
your local provider.)Joe Schmoe's Homepage
Joe Schmoe's Homepage
Joe Schmoe's Homepage
Joe Schmoe's Homepage
Rails OpenID Example Relying Party
<% if flash[:alert] %>
To use the example provider
script/server --port=3001
Visit /consumer and enter your OpenID.
ruby-openid-2.7.0debian.orig/examples/rails_openid/app/views/layouts/ 0000755 0001750 0001750 00000000000 12512544714 025217 5 ustar sbadia sbadia ruby-openid-2.7.0debian.orig/examples/rails_openid/app/views/layouts/server.html.erb 0000644 0001750 0001750 00000002720 12512544714 030163 0 ustar sbadia sbadia