Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
django-cas
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
django-cas
Commits
9a7ce56f
Commit
9a7ce56f
authored
Nov 24, 2010
by
Ed Crewe
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add the original patch file
parent
34b53889
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
326 additions
and
0 deletions
+326
-0
django-cas-proxy.patch
+326
-0
No files found.
django-cas-proxy.patch
0 → 100644
View file @
9a7ce56f
Index: setup.py
===================================================================
--- setup.py (revision 1175)
+++ setup.py (arbetskopia)
@@ -37,5 +37,5 @@
name='django_cas',
packages=['django_cas'],
url='http://code.google.com/p/django-cas/',
- version='2.0.3',
+ version='2.0.3-KTH-2',
)
Index: django_cas/backends.py
===================================================================
--- django_cas/backends.py (revision 1175)
+++ django_cas/backends.py (arbetskopia)
@@ -4,9 +4,9 @@
from urlparse import urljoin
from django.conf import settings
+from django.core.exceptions import ObjectDoesNotExist
+from django_cas.models import User, Tgt, PgtIOU
-from django_cas.models import User
-
__all__ = ['CASBackend']
def _verify_cas1(ticket, service):
@@ -40,21 +40,71 @@
except ImportError:
from elementtree import ElementTree
+ if settings.CAS_PROXY_CALLBACK:
+ params = {'ticket': ticket, 'service': service, 'pgtUrl': settings.CAS_PROXY_CALLBACK}
+ else:
+ params = {'ticket': ticket, 'service': service}
+
+ url = (urljoin(settings.CAS_SERVER_URL, 'proxyValidate') + '?' +
+ urlencode(params))
+
+ page = urlopen(url)
+
+ try:
+ response = page.read()
+ tree = ElementTree.fromstring(response)
+ if tree[0].tag.endswith('authenticationSuccess'):
+ username = tree[0][0].text
+ if len(tree[0]) >= 2 and tree[0][1].tag.endswith('proxyGrantingTicket'):
+ pgtIou = PgtIOU.objects.get(pgtIou = tree[0][1].text)
+ try:
+ tgt = Tgt.objects.get(username = username)
+ tgt.tgt = pgtIou.tgt
+ tgt.save()
+ except ObjectDoesNotExist:
+ Tgt.objects.create(username = username, tgt = pgtIou.tgt)
+
+ pgtIou.delete()
+ return username
+ else:
+ return None
+ finally:
+ page.close()
+
+
+def verify_proxy_ticket(ticket, service):
+ """Verifies CAS 2.0+ XML-based proxy ticket.
+
+ Returns username on success and None on failure.
+ """
+
+ try:
+ from xml.etree import ElementTree
+ except ImportError:
+ from elementtree import ElementTree
+
params = {'ticket': ticket, 'service': service}
+
url = (urljoin(settings.CAS_SERVER_URL, 'proxyValidate') + '?' +
urlencode(params))
+
page = urlopen(url)
+
try:
response = page.read()
tree = ElementTree.fromstring(response)
if tree[0].tag.endswith('authenticationSuccess'):
- return tree[0][0].text
+ username = tree[0][0].text
+ proxies = []
+ for element in tree[0][1]:
+ proxies.append(element.text)
+ return {"username": username, "proxies": proxies}
else:
return None
finally:
page.close()
+
-
_PROTOCOLS = {'1': _verify_cas1, '2': _verify_cas2}
if settings.CAS_VERSION not in _PROTOCOLS:
Index: django_cas/middleware.py
===================================================================
--- django_cas/middleware.py (revision 1175)
+++ django_cas/middleware.py (arbetskopia)
@@ -1,13 +1,13 @@
"""CAS authentication middleware"""
from urllib import urlencode
-
-from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
+from django.contrib.auth import logout as do_logout
from django.contrib.auth.views import login, logout
from django.core.urlresolvers import reverse
-
+from django.http import HttpResponseRedirect, HttpResponseForbidden
+from django_cas.exceptions import CasTicketException
from django_cas.views import login as cas_login, logout as cas_logout
__all__ = ['CASMiddleware']
@@ -50,3 +50,13 @@
return HttpResponseForbidden(error)
params = urlencode({REDIRECT_FIELD_NAME: request.get_full_path()})
return HttpResponseRedirect(reverse(cas_login) + '?' + params)
+
+ def process_exception(self, request, exception):
+ """When we get a CasTicketException, that is probably caused by the ticket timing out.
+ So logout/login and get the same page again."""
+ if isinstance(exception, CasTicketException):
+ do_logout(request)
+ # This assumes that request.path requires authentication.
+ return HttpResponseRedirect(request.path)
+ else:
+ return None
Index: django_cas/views.py
===================================================================
--- django_cas/views.py (revision 1175)
+++ django_cas/views.py (arbetskopia)
@@ -3,9 +3,10 @@
from urllib import urlencode
from urlparse import urljoin
-from django.http import get_host, HttpResponseRedirect, HttpResponseForbidden
+from django.http import get_host, HttpResponseRedirect, HttpResponseForbidden, HttpResponse
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
+from django_cas.models import PgtIOU
__all__ = ['login', 'logout']
@@ -76,6 +77,7 @@
if ticket:
from django.contrib import auth
user = auth.authenticate(ticket=ticket, service=service)
+
if user is not None:
auth.login(request, user)
name = user.first_name or user.username
@@ -102,3 +104,18 @@
return HttpResponseRedirect(_logout_url(request, next_page))
else:
return HttpResponseRedirect(next_page)
+
+def proxy_callback(request):
+ """Handles CAS 2.0+ XML-based proxy callback call.
+
+ Stores the proxy granting ticket in the database for
+ future use.
+ """
+ pgtIou = request.GET.get('pgtIou')
+ tgt = request.GET.get('pgtId')
+
+ if not (pgtIou and tgt):
+ return HttpResponse()
+
+ PgtIOU.objects.create(tgt = tgt, pgtIou = pgtIou)
+ return HttpResponse()
Index: django_cas/__init__.py
===================================================================
--- django_cas/__init__.py (revision 1175)
+++ django_cas/__init__.py (arbetskopia)
@@ -11,6 +11,7 @@
'CAS_LOGOUT_COMPLETELY': True,
'CAS_REDIRECT_URL': '/',
'CAS_RETRY_LOGIN': False,
+ 'CAS_PROXY_CALLBACK': None,
'CAS_SERVER_URL': None,
'CAS_VERSION': '2',
}
Index: django_cas/exceptions.py
===================================================================
--- django_cas/exceptions.py (revision 0)
+++ django_cas/exceptions.py (revision 1216)
@@ -0,0 +1,13 @@
+class CasTicketException(Exception):
+ def __init__(self, error):
+ self.error = error
+
+ def __str__(self):
+ return repr(self.error)
+
+class CasConfigException(Exception):
+ def __init__(self, error):
+ self.error = error
+
+ def __str__(self):
+ return repr(self.error)
Index: django_cas/models.py
===================================================================
--- django_cas/models.py (revision 1175)
+++ django_cas/models.py (arbetskopia)
@@ -1,2 +1,55 @@
+from urlparse import urljoin
+from urllib import urlencode, urlopen
from django.db import models
-from django.contrib.auth.models import User
\ No newline at end of file
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.core.exceptions import ObjectDoesNotExist
+from django_cas.exceptions import CasTicketException, CasConfigException
+
+class Tgt(models.Model):
+ username = models.CharField(max_length = 255, unique = True)
+ tgt = models.CharField(max_length = 255)
+
+ def get_proxy_ticket_for(self, service):
+ """Verifies CAS 2.0+ XML-based authentication ticket.
+
+ Returns username on success and None on failure.
+ """
+ if not settings.CAS_PROXY_CALLBACK:
+ raise CasConfigException("No proxy callback set in settings")
+
+ try:
+ from xml.etree import ElementTree
+ except ImportError:
+ from elementtree import ElementTree
+
+ params = {'pgt': self.tgt, 'targetService': service}
+
+ url = (urljoin(settings.CAS_SERVER_URL, 'proxy') + '?' +
+ urlencode(params))
+
+ page = urlopen(url)
+
+ try:
+ response = page.read()
+ tree = ElementTree.fromstring(response)
+ if tree[0].tag.endswith('proxySuccess'):
+ return tree[0][0].text
+ else:
+ raise CasTicketException("Failed to get proxy ticket")
+ finally:
+ page.close()
+
+class PgtIOU(models.Model):
+ pgtIou = models.CharField(max_length = 255, unique = True)
+ tgt = models.CharField(max_length = 255)
+ timestamp = models.DateTimeField(auto_now = True)
+
+def get_tgt_for(user):
+ if not settings.CAS_PROXY_CALLBACK:
+ raise CasConfigException("No proxy callback set in settings")
+
+ try:
+ return Tgt.objects.get(username = user.username)
+ except ObjectDoesNotExist:
+ raise CasTicketException("no ticket found for user " + user.username)
Index: NEWS.txt
===================================================================
--- NEWS.txt (revision 1175)
+++ NEWS.txt (arbetskopia)
@@ -1,5 +1,9 @@
= Release Notes =
+== Version X.X.X ==
+
+ * Added support for CAS proxy authentication.
+
== Version 2.0.3 ==
* Added `CAS_EXTRA_LOGIN_PARAMS` setting (patched contributed by frasern).
Index: README.txt
===================================================================
--- README.txt (revision 1175)
+++ README.txt (arbetskopia)
@@ -43,7 +43,11 @@
http://sso.some.edu/cas/).
Optional settings include:
-
+ * `CAS_PROXY_CALLBACK`: The URL given to the CAS server in order to
+ initialize a proxy ticket. The ticket granting ticket will be sent
+ to this URL. The url must be registered in urls.py and handled
+ by django_cas.views.proxy_callback, e.g:
+ (r'^accounts/login/casProxyCallback$', 'django_cas.views.proxy_callback')
* `CAS_ADMIN_PREFIX`: The URL prefix of the Django administration site.
If undefined, the CAS middleware will check the view being rendered to
see if it lives in `django.contrib.admin.views`.
@@ -125,7 +129,23 @@
For more information see http://code.djangoproject.com/ticket/4617.
+== CAS proxy tickets ==
+Using CAS proxy tickets is quite a bit less trivial than ordinary tickets.
+First of all the CAS server requires that the Django site can be accessed
+via https, and it MUST have a properly signed certificate that the CAS
+server can verify.
+
+For the test-server this can be achieved using a tunneling application
+such as stunnel. However this is not enough. The CAS proxy auhentication
+requires that both the web browser and the CAS server simoultaneously can
+make requests to the Django server, which the Django test server does not
+support.
+
+However, there is a Django app you can use to be able to start a threaded
+test server hosted here:
+http://github.com/jaylett/django_concurrent_test_server
+
== Customizing the 403 Error Page ==
Django doesn't provide a simple way to customize 403 error pages, so you'll
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment