Attachment 'cas.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - CAS authentication
4
5 Jasig CAS authentication module
6
7 @copyright: 2009 MoinMoin:RichardLiao
8 @license: GNU GPL, see COPYING for details.
9 """
10 import urlparse
11 import urllib, urllib2
12 import time, re
13
14 from MoinMoin import log
15 logging = log.getLogger(__name__)
16
17 from MoinMoin.auth import BaseAuth
18 from MoinMoin import user, wikiutil
19
20
21 class PyCAS(object):
22 """A class for working with a CAS server."""
23
24 def __init__(self, url, renew=False, **kwords):
25 self.url = url
26 self.renew = renew
27 self.paths = {
28 'login_path': '/login',
29 'logout_path': '/login',
30 'validate_path': '/validate',
31 }
32 self.paths.update(kwords)
33
34 def login_url(self, service):
35 """Return the login URL for the given service."""
36 base = self.url + self.paths['login_path'] + '?service=' + urllib.quote_plus(service)
37 if self.renew:
38 base += "&renew=true"
39 return base
40
41 def logout_url(self, url=None):
42 """Return the logout URL."""
43 base = self.url + self.paths['logout_path']
44 if url:
45 base += '?url=' + urllib.quote_plus(url)
46 return base
47
48 def validate_url(self, service, ticket):
49 """Return the validation URL for the given service. (For CAS 1.0)"""
50 base = self.url + self.paths['validate_path'] + '?service=' + urllib.quote_plus(service) + '&ticket=' + urllib.quote_plus(ticket)
51 if self.renew:
52 base += "&renew=true"
53 return base
54
55 def validate_ticket(self, service, ticket):
56 """Validate the given ticket against the given service."""
57 f = urllib2.urlopen(self.validate_url(service, ticket))
58 valid = f.readline()
59 valid = valid.strip() == 'yes'
60 user = f.readline().strip()
61
62 return (valid, user)
63
64 class CASAuth(BaseAuth):
65 """ handle login from CAS """
66 name = 'CAS'
67 logout_possible = True
68
69 def __init__(self, auth_server, login_path = "/login", logout_path = "/logout", validate_path = "/validate"):
70 BaseAuth.__init__(self)
71 self.auth_server = auth_server
72 self.login_path = login_path
73 self.logout_path = logout_path
74 self.validate_path = validate_path
75
76 def request(self, request, user_obj, **kw):
77 ticket = request.args.get('ticket')
78 action = request.args.get("action", [])
79 logoutRequest = request.args.get('logoutRequest', [])
80 url = request.getBaseURL() + urllib.quote_plus(request.getPathinfo().encode('utf-8'))
81
82 # # handle logout request from CAS
83 # if logoutRequest:
84 # logoutRequestMatch = re.search("<samlp:SessionIndex>(.*)</samlp:SessionIndex>", logoutRequest[0])
85 # service_ticket = logoutRequestMatch.group(1)
86 # if service_ticket:
87 # # TODO: logout
88 # return self.logout(request, user_obj)
89
90 # authenticated user
91 if user_obj and user_obj.valid:
92 return user_obj, True
93
94 # anonymous
95 if not ticket and not "login" in action:
96 return user_obj, True
97
98 # valid ticket on CAS
99 if ticket:
100 valid, username = self.cas.validate_ticket(url, ticket[0])
101 if valid:
102 u = user.User(request, auth_username=username, auth_method=self.name)
103 u.valid = valid
104 # auto create user
105 u.create_or_update(True)
106 return u, True
107
108 # login
109 request.http_redirect(self.cas.login_url(url))
110
111 return user_obj, True
112
113 def logout(self, request, user_obj, **kw):
114 if self.name and user_obj and user_obj.auth_method == self.name:
115 url = request.getBaseURL() + urllib.quote_plus(request.getPathinfo().encode('utf-8'))
116 request.http_redirect(self.cas.logout_url(url))
117
118 user_obj.valid = False
119
120 return user_obj, True
121
122 def _cas(self):
123 paths = {
124 'login_path': self.login_path,
125 'logout_path': self.logout_path,
126 'validate_path': self.validate_path,
127 }
128
129 return PyCAS(self.auth_server, **paths)
130 cas = property(_cas)
131
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.