/boomhammer/vendor/gems/ruby-openid-2.1.4/test/test_server.rb
Ruby | 2457 lines | 1972 code | 322 blank | 163 comment | 26 complexity | 1c5d2f9de227427638e28300cb536adc MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, GPL-3.0
- 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