295 lines
9.4 KiB
Ruby
295 lines
9.4 KiB
Ruby
require "openid/consumer/checkid_request"
|
|
require "openid/message"
|
|
require "test/unit"
|
|
require "testutil"
|
|
require "util"
|
|
|
|
module OpenID
|
|
class Consumer
|
|
class CheckIDRequest
|
|
class DummyEndpoint
|
|
attr_accessor :preferred_namespace, :local_id, :server_url,
|
|
:is_op_identifier, :claimed_id
|
|
|
|
def initialize
|
|
@preferred_namespace = nil
|
|
@local_id = nil
|
|
@server_url = nil
|
|
@is_op_identifier = false
|
|
end
|
|
|
|
def get_local_id
|
|
@local_id
|
|
end
|
|
|
|
def compatibility_mode
|
|
@preferred_namespace == OPENID1_NS
|
|
end
|
|
end
|
|
|
|
module CheckIDTestMixin
|
|
include TestUtil
|
|
|
|
def setup
|
|
@endpoint = DummyEndpoint.new
|
|
@endpoint.local_id = 'http://server.unittest/joe'
|
|
@endpoint.claimed_id = 'http://joe.vanity.example/'
|
|
@endpoint.server_url = 'http://server.unittest/'
|
|
@endpoint.preferred_namespace = preferred_namespace
|
|
@realm = 'http://example/'
|
|
@return_to = 'http://example/return/'
|
|
@assoc = GoodAssoc.new
|
|
@checkid_req = CheckIDRequest.new(@assoc, @endpoint)
|
|
end
|
|
|
|
def assert_has_identifiers(msg, local_id, claimed_id)
|
|
assert_openid_value_equal(msg, 'identity', local_id)
|
|
assert_openid_value_equal(msg, 'claimed_id', claimed_id)
|
|
end
|
|
|
|
def assert_openid_key_exists(msg, key)
|
|
assert(msg.get_arg(OPENID_NS, key),
|
|
"#{key} not present in #{msg.get_args(OPENID_NS).inspect}")
|
|
end
|
|
|
|
def assert_openid_key_absent(msg, key)
|
|
assert(msg.get_arg(OPENID_NS, key).nil?)
|
|
end
|
|
|
|
def assert_openid_value_equal(msg, key, expected)
|
|
actual = msg.get_arg(OPENID_NS, key, NO_DEFAULT)
|
|
error_text = ("Expected #{expected.inspect} for openid.#{key} "\
|
|
"but got #{actual.inspect}: #{msg.inspect}")
|
|
assert_equal(expected, actual, error_text)
|
|
end
|
|
|
|
def assert_anonymous(msg)
|
|
['claimed_id', 'identity'].each do |key|
|
|
assert_openid_key_absent(msg, key)
|
|
end
|
|
end
|
|
|
|
def assert_has_required_fields(msg)
|
|
internal_message = @checkid_req.instance_variable_get(:@message)
|
|
assert_equal(preferred_namespace,
|
|
internal_message.get_openid_namespace)
|
|
|
|
assert_equal(preferred_namespace, msg.get_openid_namespace)
|
|
assert_openid_value_equal(msg, 'mode', expected_mode)
|
|
|
|
# Implement these in subclasses because they depend on
|
|
# protocol differences!
|
|
assert_has_realm(msg)
|
|
assert_identifiers_present(msg)
|
|
end
|
|
|
|
# TESTS
|
|
|
|
def test_check_no_assoc_handle
|
|
@checkid_req.instance_variable_set('@assoc', nil)
|
|
msg = assert_log_matches("Generated checkid") {
|
|
@checkid_req.get_message(@realm, @return_to, immediate)
|
|
}
|
|
assert_openid_key_absent(msg, 'assoc_handle')
|
|
end
|
|
|
|
def test_check_with_assoc_handle
|
|
msg = assert_log_matches("Generated checkid") {
|
|
@checkid_req.get_message(@realm, @return_to, immediate)
|
|
}
|
|
|
|
assert_openid_value_equal(msg, 'assoc_handle', @assoc.handle)
|
|
end
|
|
|
|
def test_add_extension_arg
|
|
@checkid_req.add_extension_arg('bag:', 'color', 'brown')
|
|
@checkid_req.add_extension_arg('bag:', 'material', 'paper')
|
|
assert(@checkid_req.message.namespaces.member?('bag:'))
|
|
assert_equal(@checkid_req.message.get_args('bag:'),
|
|
{'color' => 'brown', 'material' => 'paper'})
|
|
|
|
msg = assert_log_matches("Generated checkid") {
|
|
@checkid_req.get_message(@realm, @return_to, immediate)
|
|
}
|
|
|
|
# XXX: this depends on the way that Message assigns
|
|
# namespaces. Really it doesn't care that it has alias "0",
|
|
# but that is tested anyway
|
|
post_args = msg.to_post_args()
|
|
assert_equal('brown', post_args['openid.ext0.color'])
|
|
assert_equal('paper', post_args['openid.ext0.material'])
|
|
end
|
|
|
|
def test_standard
|
|
msg = assert_log_matches('Generated checkid') {
|
|
@checkid_req.get_message(@realm, @return_to, immediate)
|
|
}
|
|
assert_has_identifiers(msg, @endpoint.local_id, @endpoint.claimed_id)
|
|
end
|
|
|
|
def test_send_redirect?
|
|
silence_logging {
|
|
url = @checkid_req.redirect_url(@realm, @return_to, immediate)
|
|
assert(url.length < OPENID1_URL_LIMIT)
|
|
assert(@checkid_req.send_redirect?(@realm, @return_to, immediate))
|
|
|
|
@return_to << '/foo' * 1000
|
|
url = @checkid_req.redirect_url(@realm, @return_to, immediate)
|
|
assert(url.length > OPENID1_URL_LIMIT)
|
|
actual = @checkid_req.send_redirect?(@realm, @return_to, immediate)
|
|
expected = preferred_namespace != OPENID2_NS
|
|
assert_equal(expected, actual)
|
|
}
|
|
end
|
|
end
|
|
|
|
class TestCheckIDRequestOpenID2 < Test::Unit::TestCase
|
|
include CheckIDTestMixin
|
|
|
|
def immediate
|
|
false
|
|
end
|
|
|
|
def expected_mode
|
|
'checkid_setup'
|
|
end
|
|
|
|
def preferred_namespace
|
|
OPENID2_NS
|
|
end
|
|
|
|
# check presence of proper realm key and absence of the wrong
|
|
# one.
|
|
def assert_has_realm(msg)
|
|
assert_openid_value_equal(msg, 'realm', @realm)
|
|
assert_openid_key_absent(msg, 'trust_root')
|
|
end
|
|
|
|
def assert_identifiers_present(msg)
|
|
identity_present = msg.has_key?(OPENID_NS, 'identity')
|
|
claimed_present = msg.has_key?(OPENID_NS, 'claimed_id')
|
|
|
|
assert_equal(claimed_present, identity_present)
|
|
end
|
|
|
|
# OpenID Checkid_Requests should be able to set 'anonymous' to true.
|
|
def test_set_anonymous_works_for_openid2
|
|
assert(@checkid_req.message.is_openid2)
|
|
assert_nothing_raised {@checkid_req.anonymous = true}
|
|
assert_nothing_raised {@checkid_req.anonymous = false}
|
|
end
|
|
|
|
def test_user_anonymous_ignores_identfier
|
|
@checkid_req.anonymous = true
|
|
msg = assert_log_matches('Generated checkid') {
|
|
@checkid_req.get_message(@realm, @return_to, immediate)
|
|
}
|
|
assert_has_required_fields(msg)
|
|
assert_anonymous(msg)
|
|
end
|
|
|
|
def test_op_anonymous_ignores_identifier
|
|
@endpoint.is_op_identifier = true
|
|
@checkid_req.anonymous = true
|
|
msg = assert_log_matches('Generated checkid') {
|
|
@checkid_req.get_message(@realm, @return_to, immediate)
|
|
}
|
|
assert_has_required_fields(msg)
|
|
assert_anonymous(msg)
|
|
end
|
|
|
|
def test_op_identifier_sends_identifier_select
|
|
@endpoint.is_op_identifier = true
|
|
msg = assert_log_matches('Generated checkid') {
|
|
@checkid_req.get_message(@realm, @return_to, immediate)
|
|
}
|
|
assert_has_required_fields(msg)
|
|
assert_has_identifiers(msg, IDENTIFIER_SELECT, IDENTIFIER_SELECT)
|
|
end
|
|
end
|
|
|
|
class TestCheckIDRequestOpenID1 < Test::Unit::TestCase
|
|
include CheckIDTestMixin
|
|
|
|
def immediate
|
|
false
|
|
end
|
|
|
|
def preferred_namespace
|
|
OPENID1_NS
|
|
end
|
|
|
|
def expected_mode
|
|
'checkid_setup'
|
|
end
|
|
|
|
# Make sure claimed_is is *absent* in request.
|
|
def assert_has_identifiers(msg, op_specific_id, claimed_id)
|
|
assert_openid_value_equal(msg, 'identity', op_specific_id)
|
|
assert_openid_key_absent(msg, 'claimed_id')
|
|
end
|
|
|
|
def assert_identifiers_present(msg)
|
|
assert_openid_key_absent(msg, 'claimed_id')
|
|
assert(msg.has_key?(OPENID_NS, 'identity'))
|
|
end
|
|
|
|
# check presence of proper realm key and absence of the wrong
|
|
# one.
|
|
def assert_has_realm(msg)
|
|
assert_openid_value_equal(msg, 'trust_root', @realm)
|
|
assert_openid_key_absent(msg, 'realm')
|
|
end
|
|
|
|
# TESTS
|
|
|
|
# OpenID 1 requests MUST NOT be able to set anonymous to true
|
|
def test_set_anonymous_fails_for_openid1
|
|
assert(@checkid_req.message.is_openid1)
|
|
assert_raises(ArgumentError) {
|
|
@checkid_req.anonymous = true
|
|
}
|
|
assert_nothing_raised{
|
|
@checkid_req.anonymous = false
|
|
}
|
|
end
|
|
|
|
# Identfier select SHOULD NOT be sent, but this pathway is in
|
|
# here in case some special discovery stuff is done to trigger
|
|
# it with OpenID 1. If it is triggered, it will send
|
|
# identifier_select just like OpenID 2.
|
|
def test_identifier_select
|
|
@endpoint.is_op_identifier = true
|
|
msg = assert_log_matches('Generated checkid') {
|
|
@checkid_req.get_message(@realm, @return_to, immediate)
|
|
}
|
|
assert_has_required_fields(msg)
|
|
assert_equal(IDENTIFIER_SELECT,
|
|
msg.get_arg(OPENID1_NS, 'identity'))
|
|
end
|
|
|
|
end
|
|
|
|
class TestCheckIDRequestOpenID1Immediate < TestCheckIDRequestOpenID1
|
|
def immediate
|
|
true
|
|
end
|
|
|
|
def expected_mode
|
|
'checkid_immediate'
|
|
end
|
|
end
|
|
|
|
class TestCheckid_RequestOpenID2Immediate < TestCheckIDRequestOpenID2
|
|
def immediate
|
|
true
|
|
end
|
|
|
|
def expected_mode
|
|
'checkid_immediate'
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|