move xml check to celery,
[redakcja.git] / apps / django_cas / backends.py
1 """CAS authentication backend"""
2
3 from urllib import urlencode, urlopen
4 from urlparse import urljoin
5 from django.conf import settings
6 from django_cas.models import User
7
8 __all__ = ['CASBackend']
9
10
11 def _verify_cas1(ticket, service):
12     """Verifies CAS 1.0 authentication ticket.
13
14     Returns username on success and None on failure.
15     """
16
17     params = {'ticket': ticket, 'service': service}
18     url = (urljoin(settings.CAS_SERVER_URL, 'validate') + '?' +
19            urlencode(params))
20     page = urlopen(url)
21     try:
22         verified = page.readline().strip()
23         if verified == 'yes':
24             return page.readline().strip()
25         else:
26             return None
27     finally:
28         page.close()
29
30
31 def _verify_cas2(ticket, service):
32     """Verifies CAS 2.0+ XML-based authentication ticket.
33
34     Returns username on success and None on failure.
35     """
36
37     try:
38         from lxml import etree as ElementTree
39     except ImportError:
40         from elementtree import ElementTree
41
42     params = {'ticket': ticket, 'service': service}
43     url = (urljoin(settings.CAS_SERVER_URL, 'serviceValidate') + '?' +
44            urlencode(params))
45     page = urlopen(url)
46     try:
47         response = page.read()
48         tree = ElementTree.fromstring(response)
49         if tree[0].tag.endswith('authenticationSuccess'):
50             return tree[0][0].text
51         else:
52             return None
53     except:
54         import traceback
55         traceback.print_exc()
56         print "****", url
57         print response
58         print "****"
59     finally:
60         page.close()
61
62
63 _PROTOCOLS = {'1': _verify_cas1, '2': _verify_cas2}
64
65 if settings.CAS_VERSION not in _PROTOCOLS:
66     raise ValueError('Unsupported CAS_VERSION %r' % settings.CAS_VERSION)
67
68 _verify = _PROTOCOLS[settings.CAS_VERSION]
69
70
71 class CASBackend(object):
72     """CAS authentication backend"""
73
74     def authenticate(self, ticket, service):
75         """Verifies CAS ticket and gets or creates User object"""
76
77         username = _verify(ticket, service)
78         if not username:
79             return None
80         try:
81             user = User.objects.get(username__iexact=username)
82         except User.DoesNotExist:
83             # user will have an "unusable" password
84             user = User.objects.create_user(username, '')
85             user.save()
86         return user
87
88     def get_user(self, user_id):
89         """Retrieve the user's entry in the User model if it exists"""
90
91         try:
92             return User.objects.get(pk=user_id)
93         except User.DoesNotExist:
94             return None