"""Tests for the cas protocol-related code"""
from __future__ import absolute_import
import sys
import cas
import pytest
from pytest import fixture
#general tests, apply to all protocols
#
# get_login_url tests
#
def test_login_url_helper():
client = cas.CASClientBase(
renew=False,
extra_login_params=False,
server_url='http://www.example.com/cas/',
service_url='http://testserver/'
)
actual = client.get_login_url()
expected = 'http://www.example.com/cas/login?service=http%3A%2F%2Ftestserver%2F'
assert actual == expected
def test_login_url_helper_with_extra_params():
client = cas.CASClientBase(
renew=False,
extra_login_params={'test': '1234'},
server_url='http://www.example.com/cas/',
service_url='http://testserver/'
)
actual = client.get_login_url()
# since the dictionary of parameters is unordered, we dont know which
# parameter will be first, so just check that both are in the url.
assert 'service=http%3A%2F%2Ftestserver%2F' in actual
assert 'test=1234' in actual
def test_login_url_helper_with_renew():
client = cas.CASClientBase(
renew=True,
extra_login_params=None,
server_url='http://www.example.com/cas/',
service_url='http://testserver/'
)
actual = client.get_login_url()
# since the dictionary of parameters is unordered, we dont know which
# parameter will be first, so just check that both are in the url.
assert 'service=http%3A%2F%2Ftestserver%2F' in actual
assert 'renew=true' in actual
#
# get_logout_url tests
#
@fixture
def logout_client_v1():
return cas.CASClient(
version='1',
server_url='http://www.example.com/cas/'
)
@fixture
def logout_client_v2():
return cas.CASClient(
version='2',
server_url='http://www.example.com/cas/'
)
@fixture
def logout_client_v3():
return cas.CASClient(
version='3',
server_url='http://www.example.com/cas/'
)
def test_logout_url(logout_client_v3):
actual = logout_client_v3.get_logout_url()
expected = 'http://www.example.com/cas/logout'
assert actual == expected
def test_v1_logout_url_with_redirect(logout_client_v1):
actual = logout_client_v1.get_logout_url(
redirect_url='http://testserver/landing-page/'
)
expected = 'http://www.example.com/cas/logout?url=http%3A%2F%2Ftestserver%2Flanding-page%2F'
assert actual == expected
def test_v2_logout_url_with_redirect(logout_client_v2):
actual = logout_client_v2.get_logout_url(
redirect_url='http://testserver/landing-page/'
)
expected = 'http://www.example.com/cas/logout?url=http%3A%2F%2Ftestserver%2Flanding-page%2F'
assert actual == expected
def test_v3_logout_url_with_redirect(logout_client_v3):
actual = logout_client_v3.get_logout_url(
redirect_url='http://testserver/landing-page/'
)
expected = 'http://www.example.com/cas/logout?service=http%3A%2F%2Ftestserver%2Flanding-page%2F'
assert actual == expected
def test_v3_logout_url_without_redirect(logout_client_v3):
actual = logout_client_v3.get_logout_url()
expected = 'http://www.example.com/cas/logout'
assert actual == expected
#cas3 responses
@fixture
def client_v3():
return cas.CASClient(
version='3',
server_url='https://cas.example.com/cas/',
service_url='https://example.com/login')
SUCCESS_RESPONSE = """
user@example.com
"""
def test_cas3_basic_successful_response_verification(client_v3):
user, attributes, pgtiou = client_v3.verify_response(SUCCESS_RESPONSE)
assert user == 'user@example.com'
assert not attributes
assert not pgtiou
SUCCESS_RESPONSE_WITH_ATTRIBUTES = """
user@example.combar1234
"""
def test_cas3_successful_response_verification_with_attributes(client_v3):
user, attributes, pgtiou = client_v3.verify_response(SUCCESS_RESPONSE_WITH_ATTRIBUTES)
assert user == 'user@example.com'
assert not pgtiou
assert attributes['foo'] == 'bar'
assert attributes['baz'] == '1234'
SUCCESS_RESPONSE_WITH_PGTIOU = """
user@example.comPGTIOU-84678-8a9d
"""
def test_successful_response_verification_with_pgtiou(client_v3):
user, attributes, pgtiou = client_v3.verify_response(SUCCESS_RESPONSE_WITH_PGTIOU)
assert user == 'user@example.com'
assert pgtiou == 'PGTIOU-84678-8a9d'
FAILURE_RESPONSE = """
service ticket ST-1415306486-qs5TfUWlwge23u013h8fivR21RklkeWI has already been used
"""
def test_unsuccessful_response(client_v3):
user, attributes, pgtiou = client_v3.verify_response(FAILURE_RESPONSE)
assert user is None
assert not pgtiou
assert not attributes
def test_proxy_url(client_v3):
tgt = 'tgt-1234'
proxy_url_string = client_v3.get_proxy_url(tgt)
assert proxy_url_string == 'https://cas.example.com/cas/proxy?pgt=tgt-1234&targetService=https%3A%2F%2Fexample.com%2Flogin' or proxy_url_string == 'https://cas.example.com/cas/proxy?targetService=https%3A%2F%2Fexample.com%2Flogin&pgt=tgt-1234'
#test CAS+SAML protocol
def test_can_saml_assertion_is_encoded():
ticket = 'test-ticket'
client = cas.CASClient(version='CAS_2_SAML_1_0')
saml = client.get_saml_assertion(ticket)
if sys.version_info > (3, 0):
assert type(saml) is bytes
assert ticket.encode('utf-8') in saml
else:
assert ticket in saml
# Test session= constructor argument with a mock session
@pytest.mark.skipif(sys.version_info < (3, 3), reason="Mock class not available")
def test_v3_custom_session():
from unittest.mock import Mock
response = Mock()
response.content = SUCCESS_RESPONSE
session = Mock()
session.get = Mock(return_value=response)
client = cas.CASClient(
version='3',
server_url='https://cas.example.com/cas/',
service_url='https://example.com/login',
session=session)
user, attributes, pgtiou = client.verify_ticket('ABC123')
assert user == 'user@example.com'
assert not attributes
assert not pgtiou
@fixture
def client_v2():
return cas.CASClientV2()
SUCCESS_RESPONSE_WITH_JASIG_ATTRIBUTES = """
someuserJasigunudutrikvarsomeuser@example.com
"""
def test_cas2_jasig_attributes(client_v2):
user, attributes, pgtiou = client_v2.verify_response(SUCCESS_RESPONSE_WITH_JASIG_ATTRIBUTES)
assert user == 'someuser'
expected_attributes = {
'email': 'someuser@example.com',
'nombroj': ['unu', 'du', 'tri', 'kvar'],
}
assert attributes == expected_attributes
SUCCESS_RESPONSE_WITH_NON_STANDARD_USER_NODE = """
John Doesomeusersomeuser
"""
def test_cas2_non_standard_user_node(client_v2):
user, attributes, pgtiou = client_v2.verify_response(SUCCESS_RESPONSE_WITH_NON_STANDARD_USER_NODE)
assert user == 'someuser'
def test_unsupported_protocol_version():
with pytest.raises(ValueError):
cas.CASClient(version='unknown')
def test_verify_logout_request_invalid_parameters():
client = cas.CASClientWithSAMLV1()
assert not client.verify_logout_request('', '')
def test_verify_logout_request_success():
client = cas.CASClientWithSAMLV1()
logout_request = '''
@NOT_USED@
st-1234
'''
ticket = 'st-1234'
assert client.verify_logout_request(logout_request, ticket)
def test_verify_logout_request_invalid_st():
client = cas.CASClientWithSAMLV1()
logout_request = '''
@NOT_USED@
st-1234
'''
ticket = 'st-not-match'
assert not client.verify_logout_request(logout_request, ticket)