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

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@3699
Revision 3699, 5.5 KB checked in by pjkersha, 12 years ago (diff)

Separated LoginService? into server and client components sso and ssoClient respectively. Packaging needs re-organising.

  • Made important fix to redirect_to - this doesn't work when called from a BaseController?.call in Pylons 0.9.6 - moved to before method instead.
Line 
1from sso.lib.base import *
2from ndg.security.common.pylons.security_util import SecuritySession
3import logging
4log = logging.getLogger(__name__)
5
6import sys # include in case tracefile is set to sys.stderr
7import base64 # decode the return to address
8from urlparse import urlsplit, urlunsplit
9
10from ndg.security.common.SessionMgr import SessionMgrClient
11
12
13class LogoutController(BaseController):
14    '''Provides the pylons controller for logging out and removing security
15    session cookie content
16    '''
17#   
18#    def __before__(self):
19#        """Get return to URL"""
20#        log.debug("LogoutController.__before__ ...")
21#        log.debug("LogoutController.__before__ ...")
22#
23#        c.returnTo = request.params.get('r', '')
24#       
25#        # Check return to address - getCredentials should NOT be returned to
26#        # with its query args intact
27#        try:
28#            b64decReturnTo = base64.urlsafe_b64decode(c.returnTo)
29#        except Exception, e:
30#            log.error("Decoding return to address: %s" % e)
31#            return
32#       
33#        scheme, netloc, pathInfo, query, frag = urlsplit(b64decReturnTo)
34##        if 'getCredentials' in pathInfo:
35##            # Swap back to login and remove sensitive creds query args
36##            #
37##            # TODO: re-write to be more robust and modular.  Nb.
38##            # BaseController.__call__ should filter out 'getCredentials'
39##            # calls from c.requestURL so this code should never need to be
40##            # executed.
41##            filteredReturnTo = urlunsplit((scheme,netloc,'/login','',''))
42##            c.returnTo = base64.urlsafe_b64encode(filteredReturnTo)
43
44   
45    def index(self):
46        '''Logout - remove session from Session Manager tidy up cookie'''
47
48        log.info("LogoutController.index ...")
49       
50
51        if 'ndgSec' not in session:
52            # There's no handle to a security session
53            log.error("logout called but no 'ndgSec' key in session object")
54            return self._redirect()
55       
56        # Fixed URI to be equal to the session's security settings 'h' param!
57        # This contains the location of the Session Manager where the users
58        # session is held.
59        #
60
61       
62        # Inclusive namespace prefixes for WS-Security digital signature
63        # (Exclusive C14N only)
64        refC14nKw={'unsuppressedPrefixes':g.securityCfg.wssRefInclNS}
65        signedInfoC14nKw = {'unsuppressedPrefixes':
66                            g.securityCfg.wssSignedInfoInclNS}
67
68        try:
69            smClnt = SessionMgrClient(uri=session['ndgSec']['h'],
70                    sslCACertFilePathList=g.securityCfg.sslCACertFilePathList,
71                    signingCertFilePath=g.securityCfg.wssCertFilePath,
72                    signingPriKeyFilePath=g.securityCfg.wssPriKeyFilePath,
73                    signingPriKeyPwd=g.securityCfg.wssPriKeyPwd,
74                    caCertFilePathList=g.securityCfg.wssCACertFilePathList,
75                    refC14nKw=refC14nKw,
76                    signedInfoC14nKw=signedInfoC14nKw,
77                    tracefile=g.securityCfg.tracefile)       
78        except Exception, e:
79            log.error("logout - creating Session Manager client: %s" % e)
80            return self._cleanupAndRedirect() 
81       
82        # Disconnect from Session Manager
83        log.info('Calling Session Manager "%s" disconnect for logout...' % \
84                 g.securityCfg.smURI)
85        try:
86            smClnt.disconnect(sessID=session['ndgSec']['sid'])
87        except Exception, e:
88            log.error("Error with Session Manager logout: %s" % e)
89            # don't exit here - instead proceed to delete session and
90            # redirect ...
91
92        return self._cleanupAndRedirect()
93
94
95    def _cleanupAndRedirect(self):
96        """Remove security session and call _redirect"""
97        try:
98            # easy to kill our cookie
99            SecuritySession.delete()
100            if 'ndgCleared' in session: del session['ndgCleared']
101            session.save()
102           
103        except Exception, e:   
104            log.error("logout - clearing security session: %s" % e)
105
106        return self._redirect()
107   
108   
109    def _redirect(self):
110        """Handle redirect back to previous page"""
111       
112        # Redirect URL is held in 'r' URL arg of this request
113        b64encReturnTo = str(request.params.get('r', ''))
114
115        if b64encReturnTo:
116            # Decode the return to address
117            try:
118                b64decReturnTo = base64.urlsafe_b64decode(b64encReturnTo)
119            except Exception, e:
120                log.error("logout - decoding return URL: %s" % e) 
121                c.xml = "Error carrying out browser redirect following logout"
122                return render('ndg.security.error')
123           
124            # Check for 'getCredentials' - avoid in case username/password
125            # contained in the URL!
126            getCredentialsIdx = b64decReturnTo.rfind('/getCredentials')
127            if getCredentialsIdx != -1:
128                log.debug(\
129                    "Reverting request URL from getCredentials to login...")
130                b64decReturnTo = b64decReturnTo[:getCredentialsIdx] + '/login'
131           
132            # and now go back to whence we had come
133            log.debug("LogoutController._redirect: redirect to %s" % \
134                                                              b64decReturnTo)
135            h.redirect_to(b64decReturnTo)
136        else:
137            log.debug("LogoutController._redirect: no redirect URL set.")
138            return render('ndg.security.error')
Note: See TracBrowser for help on using the repository browser.