Make attributes conformant with CAS 3.0 spec, fix bug in model whitelist, add more tests, add roadmap to README.txt
This commit is contained in:
parent
0922e03caf
commit
05003074b0
13
README.txt
13
README.txt
|
@ -18,3 +18,16 @@ A2_IDP_CAS_SERVICES A sequence of URL prefixes, any URL starting with
|
||||||
A2_IDP_CAS_PROVIDER Class implementating CAS views, default to
|
A2_IDP_CAS_PROVIDER Class implementating CAS views, default to
|
||||||
`authentic2_idp_cas.views.CasProvider`
|
`authentic2_idp_cas.views.CasProvider`
|
||||||
A2_IDP_CAS_TICKET_EXPIRATION Ticket lifetime
|
A2_IDP_CAS_TICKET_EXPIRATION Ticket lifetime
|
||||||
|
|
||||||
|
Roadmap
|
||||||
|
=======
|
||||||
|
|
||||||
|
- implement proxy tickets
|
||||||
|
- add test for samlValidate
|
||||||
|
- implement CAS 3.0 new constraints
|
||||||
|
- implement CAS 3.0 logout
|
||||||
|
- add service field to CasService model, use domain only to filter them
|
||||||
|
easily
|
||||||
|
- add model to store attribute configuration for a service
|
||||||
|
- add way to set attribute configuration for a service from settings
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,9 @@ PROXY_TICKET_ELT = 'proxyTicket'
|
||||||
|
|
||||||
PROXY_FAILURE_ELT = 'proxyFailure'
|
PROXY_FAILURE_ELT = 'proxyFailure'
|
||||||
|
|
||||||
|
# XML Elements for CAS 3.0
|
||||||
|
ATTRIBUTES_ELT = 'attributes'
|
||||||
|
|
||||||
# Templates
|
# Templates
|
||||||
|
|
||||||
CAS10_VALIDATION_FAILURE = 'no\n\n'
|
CAS10_VALIDATION_FAILURE = 'no\n\n'
|
||||||
|
@ -56,3 +59,42 @@ CAS20_VALIDATION_SUCCESS = '''<cas:serviceResponse xmlns:cas='http://www.yale.ed
|
||||||
<cas:user>%s</cas:user>
|
<cas:user>%s</cas:user>
|
||||||
</cas:authenticationSuccess>
|
</cas:authenticationSuccess>
|
||||||
</cas:serviceResponse>'''
|
</cas:serviceResponse>'''
|
||||||
|
|
||||||
|
SAML_RESPONSE_TEMPLATE = '''<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
|
||||||
|
<SOAP-ENV:Header/>
|
||||||
|
<SOAP-ENV:Body>
|
||||||
|
<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" IssueInstant="2013-05-16T16:07:35Z" MajorVersion="1" MinorVersion="1" Recipient="https://amonecole.monreseau.lan/webcalendar/login.php" ResponseID="{reponse_id}">
|
||||||
|
<Status>
|
||||||
|
<StatusCode Value="samlp:Success">
|
||||||
|
</StatusCode>
|
||||||
|
</Status>
|
||||||
|
<Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="{assertion_id}" IssueInstant="{issue_instant}" Issuer="{issuer}" MajorVersion="1" MinorVersion="1">
|
||||||
|
<Conditions NotBefore="{not_before}" NotOnOrAfter="{not_on_or_after}">
|
||||||
|
<AudienceRestrictionCondition>
|
||||||
|
<Audience>{audience}</Audience>
|
||||||
|
</AudienceRestrictionCondition>
|
||||||
|
</Conditions>
|
||||||
|
<AttributeStatement>
|
||||||
|
<Subject>
|
||||||
|
<NameIdentifier>{name_id}</NameIdentifier>
|
||||||
|
<SubjectConfirmation>
|
||||||
|
<ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:artifact</ConfirmationMethod>
|
||||||
|
</SubjectConfirmation>
|
||||||
|
</Subject>
|
||||||
|
{attributes}
|
||||||
|
|
||||||
|
</AttributeStatement>
|
||||||
|
<AuthenticationStatement AuthenticationInstant="{authentication_instant}" AuthenticationMethod="{authentication_method}">
|
||||||
|
<Subject>
|
||||||
|
<NameIdentifier>{name_id}</NameIdentifier>
|
||||||
|
<SubjectConfirmation>
|
||||||
|
<ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:artifact</ConfirmationMethod>
|
||||||
|
</SubjectConfirmation>
|
||||||
|
</Subject>
|
||||||
|
</AuthenticationStatement>
|
||||||
|
</Assertion>
|
||||||
|
</Response>
|
||||||
|
</SOAP-ENV:Body>
|
||||||
|
</SOAP-ENV:Envelope>'''
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,12 @@ from xml.etree import ElementTree as ET
|
||||||
|
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory, Client
|
||||||
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
|
|
||||||
from authentic2.compat import get_user_model
|
from authentic2.compat import get_user_model
|
||||||
from .models import CasTicket
|
from .models import CasTicket, CasService
|
||||||
from . import views
|
from . import views
|
||||||
from . import constants
|
from . import constants
|
||||||
|
|
||||||
|
@ -14,12 +15,49 @@ from . import constants
|
||||||
class CasTests(TestCase):
|
class CasTests(TestCase):
|
||||||
LOGIN = 'test'
|
LOGIN = 'test'
|
||||||
PASSWORD = 'test'
|
PASSWORD = 'test'
|
||||||
|
DOMAIN = 'casclient.com'
|
||||||
|
SERVICE = 'https://%s/' % DOMAIN
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
self.user = User.objects.create_user(self.LOGIN, password=self.PASSWORD)
|
self.user = User.objects.create_user(self.LOGIN, password=self.PASSWORD)
|
||||||
self.factory = RequestFactory()
|
self.factory = RequestFactory()
|
||||||
|
|
||||||
|
def test_cas_login_blacklist_failure(self):
|
||||||
|
client = Client()
|
||||||
|
response = client.get('/idp/cas/login/', {'service': self.SERVICE})
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
self.assertIn('is not allowed', response.content)
|
||||||
|
|
||||||
|
@override_settings(A2_IDP_CAS_SERVICES=(SERVICE,))
|
||||||
|
def test_cas_login_settings_whitelist(self):
|
||||||
|
self.helper_test_cas_login()
|
||||||
|
|
||||||
|
def test_cas_login_model_whitelist(self):
|
||||||
|
CasService.objects.create(
|
||||||
|
name=self.DOMAIN,
|
||||||
|
slug=self.DOMAIN,
|
||||||
|
domain=self.DOMAIN)
|
||||||
|
self.helper_test_cas_login()
|
||||||
|
|
||||||
|
def helper_test_cas_login(self):
|
||||||
|
client = Client()
|
||||||
|
response = client.get('/idp/cas/login/', {'service': self.SERVICE})
|
||||||
|
self.assertIn('Location', response)
|
||||||
|
self.assertTrue(response['Location'].startswith('http://testserver/login'))
|
||||||
|
response = client.post(response['Location'], {
|
||||||
|
'username': self.LOGIN,
|
||||||
|
'password': self.PASSWORD,
|
||||||
|
'submit-password': ''})
|
||||||
|
self.assertTrue(response['Location'].startswith('http://testserver/idp/cas/continue/'))
|
||||||
|
response = client.get(response['Location'])
|
||||||
|
self.assertTrue(response['Location'].startswith('https://casclient.com/?ticket=ST-'))
|
||||||
|
# verify ticket
|
||||||
|
ticket = response['Location'].split('ticket=')[1]
|
||||||
|
response = client.get('/idp/cas/serviceValidate/', {'service': self.SERVICE, 'ticket': ticket})
|
||||||
|
self.assertEqual(response.content, '''<?xml version='1.0' encoding='utf8'?>
|
||||||
|
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas"><cas:authenticationSuccess><cas:user>test</cas:user></cas:authenticationSuccess></cas:serviceResponse>''')
|
||||||
|
|
||||||
def test_service_validate_with_default_attributes(self):
|
def test_service_validate_with_default_attributes(self):
|
||||||
CasTicket.objects.create(
|
CasTicket.objects.create(
|
||||||
ticket_id='ST-xxx',
|
ticket_id='ST-xxx',
|
||||||
|
@ -32,28 +70,15 @@ class CasTests(TestCase):
|
||||||
def get_attributes(self, request, st):
|
def get_attributes(self, request, st):
|
||||||
assert st.service == 'yyy'
|
assert st.service == 'yyy'
|
||||||
assert st.ticket_id == 'ST-xxx'
|
assert st.ticket_id == 'ST-xxx'
|
||||||
return { 'username': 'bob', 'email': 'bob@example.com' }, 'default'
|
return 'bob', { 'username': 'bob', 'email': 'bob@example.com' }
|
||||||
provider = TestCasProvider()
|
provider = TestCasProvider()
|
||||||
response = provider.service_validate(request)
|
response = provider.service_validate(request)
|
||||||
print response.content
|
|
||||||
root = ET.fromstring(response.content)
|
root = ET.fromstring(response.content)
|
||||||
ns_ctx = { 'cas': constants.CAS_NAMESPACE }
|
ns_ctx = { 'cas': constants.CAS_NAMESPACE }
|
||||||
user_elt = root.find('cas:authenticationSuccess/cas:utilisateur', namespaces=ns_ctx)
|
user_elt = root.find('cas:authenticationSuccess/cas:user', namespaces=ns_ctx)
|
||||||
assert user_elt is not None
|
self.assertIsNotNone(user_elt)
|
||||||
|
self.assertEqual(user_elt.text, 'bob')
|
||||||
def test_service_validate_with_custom_attributes(self):
|
username_elt = root.find('cas:authenticationSuccess/cas:attributes/cas:username', namespaces=ns_ctx)
|
||||||
CasTicket.objects.create(
|
self.assertEqual(username_elt.text, 'bob')
|
||||||
ticket_id='ST-xxx',
|
email_elt = root.find('cas:authenticationSuccess/cas:attributes/cas:email', namespaces=ns_ctx)
|
||||||
service='yyy',
|
self.assertEqual(email_elt.text, 'bob@example.com')
|
||||||
user=self.user,
|
|
||||||
validity=True)
|
|
||||||
request = self.factory.get('/idp/cas/serviceValidate',
|
|
||||||
{'service': 'yyy', 'ticket': 'ST-xxx'})
|
|
||||||
class TestCasProvider(views.CasProvider):
|
|
||||||
def get_attributes(self, request, st):
|
|
||||||
assert st.service == 'yyy'
|
|
||||||
assert st.ticket_id == 'ST-xxx'
|
|
||||||
return { 'username': 'bob', 'email': 'bob@example.com' }, 'utilisateur'
|
|
||||||
provider = TestCasProvider()
|
|
||||||
response = provider.service_validate(request)
|
|
||||||
print response.content
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ from django.http import HttpResponseRedirect, HttpResponseBadRequest, \
|
||||||
HttpResponse, HttpResponseNotAllowed
|
HttpResponse, HttpResponseNotAllowed
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.contrib.auth.views import redirect_to_login
|
from django.contrib.auth.views import redirect_to_login
|
||||||
from django.utils.http import urlquote, urlencode
|
|
||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import patterns, url
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
@ -20,50 +19,13 @@ from constants import SERVICE_PARAM, RENEW_PARAM, GATEWAY_PARAM, ID_PARAM, \
|
||||||
CAS10_VALIDATION_FAILURE, CAS10_VALIDATION_SUCCESS, PGT_URL_PARAM, \
|
CAS10_VALIDATION_FAILURE, CAS10_VALIDATION_SUCCESS, PGT_URL_PARAM, \
|
||||||
INVALID_REQUEST_ERROR, INVALID_TICKET_ERROR, INVALID_SERVICE_ERROR, \
|
INVALID_REQUEST_ERROR, INVALID_TICKET_ERROR, INVALID_SERVICE_ERROR, \
|
||||||
INTERNAL_ERROR, CAS20_VALIDATION_FAILURE, \
|
INTERNAL_ERROR, CAS20_VALIDATION_FAILURE, \
|
||||||
CAS_NAMESPACE, USER_ELT, SERVICE_RESPONSE_ELT, AUTHENTICATION_SUCCESS_ELT
|
CAS_NAMESPACE, USER_ELT, SERVICE_RESPONSE_ELT, AUTHENTICATION_SUCCESS_ELT, \
|
||||||
|
SAML_RESPONSE_TEMPLATE, ATTRIBUTES_ELT
|
||||||
|
|
||||||
from . import models, utils, app_settings
|
from . import models, utils, app_settings
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
SAML_RESPONSE_TEMPLATE = '''<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
|
|
||||||
<SOAP-ENV:Header/>
|
|
||||||
<SOAP-ENV:Body>
|
|
||||||
<Response xmlns="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:1.0:protocol" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" IssueInstant="2013-05-16T16:07:35Z" MajorVersion="1" MinorVersion="1" Recipient="https://amonecole.monreseau.lan/webcalendar/login.php" ResponseID="{reponse_id}">
|
|
||||||
<Status>
|
|
||||||
<StatusCode Value="samlp:Success">
|
|
||||||
</StatusCode>
|
|
||||||
</Status>
|
|
||||||
<Assertion xmlns="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="{assertion_id}" IssueInstant="{issue_instant}" Issuer="{issuer}" MajorVersion="1" MinorVersion="1">
|
|
||||||
<Conditions NotBefore="{not_before}" NotOnOrAfter="{not_on_or_after}">
|
|
||||||
<AudienceRestrictionCondition>
|
|
||||||
<Audience>{audience}</Audience>
|
|
||||||
</AudienceRestrictionCondition>
|
|
||||||
</Conditions>
|
|
||||||
<AttributeStatement>
|
|
||||||
<Subject>
|
|
||||||
<NameIdentifier>{name_id}</NameIdentifier>
|
|
||||||
<SubjectConfirmation>
|
|
||||||
<ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:artifact</ConfirmationMethod>
|
|
||||||
</SubjectConfirmation>
|
|
||||||
</Subject>
|
|
||||||
{attributes}
|
|
||||||
|
|
||||||
</AttributeStatement>
|
|
||||||
<AuthenticationStatement AuthenticationInstant="{authentication_instant}" AuthenticationMethod="{authentication_method}">
|
|
||||||
<Subject>
|
|
||||||
<NameIdentifier>{name_id}</NameIdentifier>
|
|
||||||
<SubjectConfirmation>
|
|
||||||
<ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:artifact</ConfirmationMethod>
|
|
||||||
</SubjectConfirmation>
|
|
||||||
</Subject>
|
|
||||||
</AuthenticationStatement>
|
|
||||||
</Assertion>
|
|
||||||
</Response>
|
|
||||||
</SOAP-ENV:Body>
|
|
||||||
</SOAP-ENV:Envelope>'''
|
|
||||||
|
|
||||||
class CasProvider(object):
|
class CasProvider(object):
|
||||||
def get_url(self):
|
def get_url(self):
|
||||||
return patterns('cas',
|
return patterns('cas',
|
||||||
|
@ -121,10 +83,10 @@ class CasProvider(object):
|
||||||
else:
|
else:
|
||||||
scheme, domain, x, x, x, x = urlparse.urlparse(service)
|
scheme, domain, x, x, x, x = urlparse.urlparse(service)
|
||||||
try:
|
try:
|
||||||
cas_service = models.CasService.get(domain=domain)
|
models.CasService.objects.get(domain=domain)
|
||||||
except models.CasService.DoesNotExist:
|
except models.CasService.DoesNotExist:
|
||||||
self.failure(request, 'service %r is not allowed' % service)
|
return self.failure(request, 'service %r is not allowed' % service)
|
||||||
return self.handle_login(request, cas_service, service, renew, gateway)
|
return self.handle_login(request, service, renew, gateway)
|
||||||
|
|
||||||
def must_authenticate(self, request, renew):
|
def must_authenticate(self, request, renew):
|
||||||
'''Does the user needs to authenticate ?
|
'''Does the user needs to authenticate ?
|
||||||
|
@ -143,7 +105,7 @@ class CasProvider(object):
|
||||||
'''
|
'''
|
||||||
return request.user.username
|
return request.user.username
|
||||||
|
|
||||||
def handle_login(self, request, cas_service, service, renew, gateway,
|
def handle_login(self, request, service, renew, gateway,
|
||||||
duration=None):
|
duration=None):
|
||||||
'''
|
'''
|
||||||
Handle a login request
|
Handle a login request
|
||||||
|
@ -279,11 +241,9 @@ renew:%s and gateway:%s' % (service, renew, gateway))
|
||||||
content_type='text/xml')
|
content_type='text/xml')
|
||||||
|
|
||||||
def get_attributes(self, request, st):
|
def get_attributes(self, request, st):
|
||||||
# XXX: st.service contains the requesting service URL, use it to match CAS attribute policy
|
return request.user.username, {}
|
||||||
return {}, False
|
|
||||||
|
|
||||||
def saml_build_attributes(self, request, st):
|
def saml_build_attributes(self, request, st, attributes):
|
||||||
attributes, section = self.get_attributes(request, st)
|
|
||||||
result = []
|
result = []
|
||||||
for key, value in attributes.iteritems():
|
for key, value in attributes.iteritems():
|
||||||
key = key.encode('utf-8')
|
key = key.encode('utf-8')
|
||||||
|
@ -311,6 +271,7 @@ renew:%s and gateway:%s' % (service, renew, gateway))
|
||||||
st = None
|
st = None
|
||||||
if st is None or not st.valid():
|
if st is None or not st.valid():
|
||||||
return self.saml_error(request, INVALID_TICKET_ERROR)
|
return self.saml_error(request, INVALID_TICKET_ERROR)
|
||||||
|
username, attributes = self.get_attributes(request, st)
|
||||||
new_id = self.generate_id()
|
new_id = self.generate_id()
|
||||||
|
|
||||||
ctx = {
|
ctx = {
|
||||||
|
@ -321,31 +282,27 @@ renew:%s and gateway:%s' % (service, renew, gateway))
|
||||||
'not_before': '', # XXX: issue time - lag
|
'not_before': '', # XXX: issue time - lag
|
||||||
'not_on_or_after': '', # XXX issue time + lag,
|
'not_on_or_after': '', # XXX issue time + lag,
|
||||||
'audience': st.service.encode('utf-8'),
|
'audience': st.service.encode('utf-8'),
|
||||||
'name_id': request.user.username,
|
'name_id': unicode(username).encode('utf-8'),
|
||||||
'attributes': self.saml_build_attributes(request, st),
|
'attributes': self.saml_build_attributes(request, st, attributes),
|
||||||
}
|
}
|
||||||
return HttpResponse(SAML_RESPONSE_TEMPLATE.format(**ctx),
|
return HttpResponse(SAML_RESPONSE_TEMPLATE.format(**ctx),
|
||||||
content_type='text/xml')
|
content_type='text/xml')
|
||||||
|
|
||||||
def service_validate_success_response(self, request, st):
|
def service_validate_success_response(self, request, st):
|
||||||
attributes, section = self.get_attributes(request, st)
|
username, attributes = self.get_attributes(request, st)
|
||||||
try:
|
try:
|
||||||
ET.register_namespace('cas', 'http://www.yale.edu/tp/cas')
|
ET.register_namespace('cas', 'http://www.yale.edu/tp/cas')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
ET._namespace_map['http://www.yale.edu/tp/cas'] = 'cas'
|
ET._namespace_map['http://www.yale.edu/tp/cas'] = 'cas'
|
||||||
root = ET.Element('{%s}%s' % (CAS_NAMESPACE, SERVICE_RESPONSE_ELT))
|
root = ET.Element('{%s}%s' % (CAS_NAMESPACE, SERVICE_RESPONSE_ELT))
|
||||||
success = ET.SubElement(root, '{%s}%s' % (CAS_NAMESPACE, AUTHENTICATION_SUCCESS_ELT))
|
success = ET.SubElement(root, '{%s}%s' % (CAS_NAMESPACE, AUTHENTICATION_SUCCESS_ELT))
|
||||||
|
user = ET.SubElement(success, '{%s}%s' % (CAS_NAMESPACE, USER_ELT))
|
||||||
|
user.text = unicode(username)
|
||||||
if attributes:
|
if attributes:
|
||||||
if section == 'default':
|
container = ET.SubElement(success, '{%s}%s' % (CAS_NAMESPACE, ATTRIBUTES_ELT))
|
||||||
user = success
|
|
||||||
else:
|
|
||||||
user = ET.SubElement(success, '{%s}%s' % (CAS_NAMESPACE, section))
|
|
||||||
for key, value in attributes.iteritems():
|
for key, value in attributes.iteritems():
|
||||||
elt = ET.SubElement(user, '{%s}%s' % (CAS_NAMESPACE, key))
|
elt = ET.SubElement(container, '{%s}%s' % (CAS_NAMESPACE, key))
|
||||||
elt.text = unicode(value)
|
elt.text = unicode(value)
|
||||||
else:
|
|
||||||
user = ET.SubElement(success, '{%s}%s' % (CAS_NAMESPACE, USER_ELT))
|
|
||||||
user.text = unicode(st.user)
|
|
||||||
return HttpResponse(ET.tostring(root, encoding='utf8'),
|
return HttpResponse(ET.tostring(root, encoding='utf8'),
|
||||||
content_type='text/xml')
|
content_type='text/xml')
|
||||||
|
|
||||||
|
@ -383,7 +340,7 @@ renew:%s and gateway:%s' % (service, renew, gateway))
|
||||||
return self.service_validate_success_response(request, st)
|
return self.service_validate_success_response(request, st)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception('error in cas:service_validate')
|
logger.exception('error in cas:service_validate')
|
||||||
return self.cas20_error(INTERNAL_ERROR)
|
return self.cas20_error(request, INTERNAL_ERROR)
|
||||||
|
|
||||||
def logout(self, request):
|
def logout(self, request):
|
||||||
url = request.REQUEST.get('url')
|
url = request.REQUEST.get('url')
|
||||||
|
@ -395,19 +352,10 @@ renew:%s and gateway:%s' % (service, renew, gateway))
|
||||||
|
|
||||||
class Authentic2CasProvider(CasProvider):
|
class Authentic2CasProvider(CasProvider):
|
||||||
def authenticate(self, request, st, passive=False):
|
def authenticate(self, request, st, passive=False):
|
||||||
next = '%s?id=%s' % (reverse(self.continue_cas),
|
next_url = utils.url_add_parameters(reverse(self.continue_cas),
|
||||||
urlquote(st.ticket_id))
|
id=st.sticket_id)
|
||||||
if passive:
|
return auth2_redirect_to_login(request, next=next_url,
|
||||||
if getattr(settings, 'AUTH_SSL', False):
|
nonce=st.ticket_id)
|
||||||
query = { 'next': next,
|
|
||||||
'nonce': st.ticket_id }
|
|
||||||
return HttpResponseRedirect('%s?%s' %
|
|
||||||
(reverse('user_signin_ssl'), urlencode(query)))
|
|
||||||
else:
|
|
||||||
return self.cas_failure(request, st,
|
|
||||||
'''user needs to login and no passive authentication \
|
|
||||||
is possible''')
|
|
||||||
return auth2_redirect_to_login(request, next=next, nonce=st.ticket_id)
|
|
||||||
|
|
||||||
def check_authentication(self, request, st):
|
def check_authentication(self, request, st):
|
||||||
try:
|
try:
|
||||||
|
|
Reference in New Issue