obsolete.ChilliProject/vendor/gems/ruby-openid-2.1.4/test/test_server.rb

2458 lines
86 KiB
Ruby
Raw Normal View History

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'
require 'util'
require "testutil"
require 'test/unit'
require 'uri'
# 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 < Test::Unit::TestCase
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',
}
rt_base, 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',
}
rt_base, 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)
expected_args = {
'openid.ns' => OPENID2_NS,
'openid.mode' => 'error',
'openid.error' => 'plucky',
}
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)
rt_base, 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 < Test::Unit::TestCase
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_raise(Server::ProtocolError) {
@decode.call(args)
}
end
def test_bad
args = {
'openid.mode' => 'twos-compliment',
'openid.pants' => 'zippered',
}
assert_raise(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?, err)
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_raise(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_raise(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_raise(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_raise(Server::NoReturnToError) {
req.answer(false)
}
assert_raise(Server::NoReturnToError) {
req.encode_to_url('bogus')
}
assert_raise(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_raise(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_raise(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_raise(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_raise(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_raise(Server::ProtocolError) {
@decode.call(args)
}
end
def test_associateDHpubKeyNotB64
args = {
'openid.mode' => 'associate',
'openid.session_type' => 'DH-SHA1',
'openid.dh_consumer_public' => "donkeydonkeydonkey",
}
assert_raise(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_raise(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_raise(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_raise(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_raise(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_raise(Server::ProtocolError) {
@decode.call(args)
}
end
def test_invalidns
args = {'openid.ns' => 'Vegetables',
'openid.mode' => 'associate'}
begin
r = @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 < Test::Unit::TestCase
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.starts_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_raise(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 < Test::Unit::TestCase
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_raise(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'), response.fields.to_post_args())
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_raise(Server::AlreadySigned) {
@encode.call(@response)
}
end
end
class TestCheckID < Test::Unit::TestCase
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_raise(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
selected_id = 'http://anon.unittest/9861'
assert_raise(ArgumentError) {
answer = @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_raise(ArgumentError) {
resp = @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.starts_with?(server_url))
unused, 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_raise(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_raise(ArgumentError){
@request.answer(true, nil, "http://pebbles.unittest/")
}
end
def test_answerAllowNoIdentityOpenID1
@request.message = Message.new(OPENID1_NS)
@request.identity = nil
assert_raise(ArgumentError) {
@request.answer(true, nil, nil)
}
end
def test_answerAllowForgotEndpoint
@request.op_endpoint = nil
assert_raise(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_raise(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_raise(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_raise(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.starts_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.
base, 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_raise(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 < Test::Unit::TestCase
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 < Test::Unit::TestCase
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 < Test::Unit::TestCase
# 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_raise(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_raise(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_raise(Server::ProtocolError) {
@request.answer_unsupported(m)
}
end
end
class Counter
def initialize
@count = 0
end
def inc
@count += 1
end
end
class UnhandledError < Exception
end
class TestServer < Test::Unit::TestCase
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_raise(RuntimeError) {
webresult = @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
monkeycalled = Counter.new()
@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_raise(UnhandledError) {
webresult = @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',
})
req = 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 < Test::Unit::TestCase
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)
#assert(@messages)
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)
#assert(@messages)
end
def test_getAssoc
assoc_handle = makeAssoc(true)
assoc = @signatory.get_association(assoc_handle, true)
assert(assoc)
assert_equal(assoc.handle, assoc_handle)
# @failIf(@messages, @messages)
end
def test_getAssocExpired
assoc_handle = makeAssoc(true, -10)
assoc = nil
silence_logging {
assoc = @signatory.get_association(assoc_handle, true)
}
assert(!assoc, assoc)
# assert(@messages)
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 < Test::Unit::TestCase
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