source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/sso/sso/controllers/logout.py @ 5181

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/sso/sso/controllers/logout.py@5181
Revision 5181, 5.0 KB checked in by pjkersha, 11 years ago (diff)

Added a Policy Information Point to encapsulate subject attribute retrieval.

Line 
1"""Single Sign On Service Logout Controller
2
3NERC DataGrid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "10/12/08"
7__copyright__ = "(C) 2009 Science and Technology Facilities Council"
8__license__ = "BSD - see LICENSE file in top-level directory"
9__contact__ = "Philip.Kershaw@stfc.ac.uk"
10__revision__ = '$Id$'
11from ndg.security.server.sso.sso.lib.base import *
12from ndg.security.common.pylons.security_util import SecuritySession
13import logging
14log = logging.getLogger(__name__)
15
16import sys # include in case tracefile is set to sys.stderr
17import base64 # decode the return to address
18from urlparse import urlsplit, urlunsplit
19
20from ndg.security.server.wsgi.utils.sessionmanagerclient import \
21    WSGISessionManagerClient, SessionExpired, AttributeRequestDenied
22
23
24class LogoutController(BaseController):
25    '''Provides the pylons controller for logging out and removing security
26    session cookie content
27    '''
28
29    def index(self):
30        '''Logout - remove session from Session Manager tidy up cookie'''
31
32        log.info("LogoutController.index ...")
33       
34        # Convenience alias
35        cfg = g.ndg.security.server.sso.cfg
36       
37
38        if 'ndgSec' not in session:
39            # There's no handle to a security session
40            log.error("logout called but no 'ndgSec' key in session object")
41            c.loggedIn = False
42            return self._redirect()
43       
44        try:
45            smClnt = WSGISessionManagerClient(uri=session['ndgSec']['h'],
46                        environ=request.environ,
47                        environKeyName=self.cfg.smEnvironKeyName,
48                        tracefile=cfg.tracefile,
49                        sslCACertFilePathList=cfg.sslCACertFilePathList,
50                        **cfg.wss)       
51        except Exception, e:
52            log.error("logout - creating Session Manager client: %s" % e)
53            return self._cleanupAndRedirect() 
54       
55        # Disconnect from Session Manager
56        log.info('Calling Session Manager "%s" disconnect for logout...' %
57                 session['ndgSec']['h'])
58        try:
59            smClnt.disconnect(sessID=session['ndgSec']['sid'])
60        except Exception, e:
61            log.error("Error with Session Manager logout: %s" % e)
62            # don't exit here - instead proceed to delete session and
63            # redirect ...
64
65        c.loggedIn = False
66        return self._cleanupAndRedirect()
67
68
69    def _cleanupAndRedirect(self):
70        """Remove security session and call _redirect"""
71        try:
72            # easy to kill our cookie
73            SecuritySession.delete()
74            if 'ndgCleared' in session: del session['ndgCleared']
75            session.save()
76           
77        except Exception, e:   
78            log.error("logout - clearing security session: %s" % e)
79
80        return self._redirect()
81   
82   
83    def _redirect(self):
84        """Handle redirect back to previous page"""
85       
86        # Redirect URL is held in 'r' URL arg of this request
87        b64encReturnTo = str(request.params.get('r', ''))
88
89        if b64encReturnTo:
90            # Decode the return to address
91            try:
92                b64decReturnTo = base64.urlsafe_b64decode(b64encReturnTo)
93            except Exception, e:
94                log.error("logout - decoding return URL: %s" % e) 
95                c.xml = "Error carrying out browser redirect following logout"
96                response.status_code = 400
97                return render('ndg.security.kid', 'ndg.security.error')
98           
99            # Check for 'getCredentials' - avoid in case username/password
100            # contained in the URL!
101            getCredentialsIdx = b64decReturnTo.rfind('/getCredentials')
102            if getCredentialsIdx != -1:
103                log.debug("Reverting request URL from getCredentials to "
104                          "login...")
105                b64decReturnTo = b64decReturnTo[:getCredentialsIdx] + '/login'
106           
107            # Add flag indicating to caller that logout succeeded.  The caller
108            # can use this to remove any security cookie present in their
109            # domain - See:
110            # ndg.security.client.ssoclient.ssoclient.lib.base.BaseController
111            if '?' in b64decReturnTo:
112                b64decReturnTo += '&logout=1'
113            else:
114                b64decReturnTo += '?logout=1'
115
116            # and now go back to whence we had come
117            log.debug("LogoutController._redirect: redirect to %s" %
118                                                              b64decReturnTo)
119            h.redirect_to(b64decReturnTo)
120        else:
121            log.debug("LogoutController._redirect: no redirect URL set.")
122            response.status_code = 400
123            c.errorPageHeading = "Log out"
124            if getattr(c, "loggedIn", False):
125                c.xml = "Logged out"
126            else:
127                c.xml = ("An error occurred logging out.  Please report the "
128                         "problem to your site administrator") 
129               
130            return render('ndg.security.kid', 'ndg.security.error')
Note: See TracBrowser for help on using the repository browser.