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