[wiki/auth/cas] Sigle Sign Out

This commit is contained in:
Valentin Samir 2013-06-04 18:53:05 +02:00
parent 90875b1faf
commit d885233c75

View file

@ -9,9 +9,12 @@
""" """
import sys import sys
import os
import time, re import time, re
import urlparse import urlparse
import urllib, urllib2 import urllib, urllib2
from lxml import etree
from lxml.etree import XMLSyntaxError
from MoinMoin import log from MoinMoin import log
logging = log.getLogger(__name__) logging = log.getLogger(__name__)
@ -19,7 +22,6 @@ logging = log.getLogger(__name__)
from MoinMoin.auth import BaseAuth from MoinMoin.auth import BaseAuth
from MoinMoin import user, wikiutil from MoinMoin import user, wikiutil
class PyCAS(object): class PyCAS(object):
"""A class for working with a CAS server.""" """A class for working with a CAS server."""
@ -53,6 +55,14 @@ class PyCAS(object):
url += "&renew=true" url += "&renew=true"
return url return url
def singlesignout(self, callback, body):
try:
nodes = etree.fromstring(body).xpath("/samlp:LogoutRequest/samlp:SessionIndex", namespaces={'samlp' : 'urn:oasis:names:tc:SAML:2.0:protocol'})
for node in nodes:
callback(node.text)
except XMLSyntaxError:
pass
def validate_ticket(self, service, ticket): def validate_ticket(self, service, ticket):
"""Validate the given ticket against the given service.""" """Validate the given ticket against the given service."""
f = urllib2.urlopen(self.validate_url(service, ticket)) f = urllib2.urlopen(self.validate_url(service, ticket))
@ -68,13 +78,14 @@ class CASAuth(BaseAuth):
login_inputs = ['username', 'password'] login_inputs = ['username', 'password']
logout_possible = True logout_possible = True
def __init__(self, auth_server, login_path="/login", logout_path="/logout", validate_path="/validate", action="login_cas", create_user=False, fallback_url=None): def __init__(self, auth_server, login_path="/login", logout_path="/logout", validate_path="/validate", action="login_cas", create_user=False, fallback_url=None, ticket_path=None):
BaseAuth.__init__(self) BaseAuth.__init__(self)
self.cas = PyCAS(auth_server, login_path=login_path, self.cas = PyCAS(auth_server, login_path=login_path,
validate_path=validate_path, logout_path=logout_path) validate_path=validate_path, logout_path=logout_path)
self.action = action self.action = action
self.create_user = create_user self.create_user = create_user
self.fallback_url = fallback_url self.fallback_url = fallback_url
self.ticket_path = ticket_path
def request(self, request, user_obj, **kw): def request(self, request, user_obj, **kw):
ticket = request.args.get("ticket", "") ticket = request.args.get("ticket", "")
@ -84,10 +95,46 @@ class CASAuth(BaseAuth):
p = urlparse.urlparse(request.url) p = urlparse.urlparse(request.url)
url = urlparse.urlunparse(('https', p.netloc, p.path, "", "", "")) url = urlparse.urlunparse(('https', p.netloc, p.path, "", "", ""))
def store_ticket(ticket, username):
with open(self.ticket_path + ticket, 'w') as f:
f.write(username)
def username_of_ticket(ticket):
try:
with open(self.ticket_path + ticket) as f:
username = f.read()
os.remove(self.ticket_path + ticket)
return username
except IOError:
return None
def logout_user(ticket):
username = username_of_ticket(ticket)
if username:
u = user.User(request, None, username)
checks = []
if u.exists():
def user_matches(session):
try:
return session['user.id'] == u.id
except KeyError:
return False
session_service = request.cfg.session_service
for sid in session_service.get_all_session_ids(request):
session = session_service.get_session(request, sid)
if user_matches(session):
session_service.destroy_session(request, session)
# authenticated user # authenticated user
if not force and user_obj and user_obj.valid: if not force and user_obj and user_obj.valid:
return user_obj, True return user_obj, True
if self.ticket_path and request.method == 'POST':
logoutRequest=request.form.get('logoutRequest', None)
if logoutRequest is not None:
self.cas.singlesignout(logout_user, logoutRequest)
# anonymous # anonymous
if not ticket and not self.action == action: if not ticket and not self.action == action:
return user_obj, True return user_obj, True
@ -105,6 +152,8 @@ class CASAuth(BaseAuth):
u.valid = u.exists() u.valid = u.exists()
if self.fallback_url and not u.valid: if self.fallback_url and not u.valid:
request.http_redirect("%s?action=%s&wiki_url=%s" % (self.fallback_url, self.action, url)) request.http_redirect("%s?action=%s&wiki_url=%s" % (self.fallback_url, self.action, url))
if u.valid:
store_ticket(ticket, username)
return u, True return u, True
# login # login