source: TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/openid/provider/authninterface/sessionmanager.py @ 7077

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg-security/TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/openid/provider/authninterface/sessionmanager.py@7077
Revision 7077, 6.6 KB checked in by pjkersha, 11 years ago (diff)
  • Property svn:keywords set to Id
Line 
1"""NDG Security OpenID Authentication Interface to a Session Manager.
2
3This enables an OpenID Provider's signin to link to a Session Manager running
4in the same WSGI stack or else running as a separate service via the Session
5Manager SOAP interface
6
7NERC DataGrid Project
8"""
9__author__ = "P J Kershaw"
10__date__ = "01/08/08"
11__copyright__ = "(C) 2009 Science and Technology Facilities Council"
12__license__ = "BSD - see LICENSE file in top-level directory"
13__contact__ = "Philip.Kershaw@stfc.ac.uk"
14__revision__ = "$Id$"
15import logging
16log = logging.getLogger(__name__)
17from string import Template
18from sqlalchemy import create_engine
19
20from ndg.security.server.wsgi.openid.provider.authninterface import \
21    AbstractAuthNInterface, AuthNInterfaceConfigError, \
22    AuthNInterfaceInvalidCredentials, AuthNInterfaceUsername2IdentifierMismatch
23   
24from ndg.security.server.wsgi.utils.sessionmanagerclient import \
25    WSGISessionManagerClient, AuthNServiceInvalidCredentials
26   
27
28class SessionManagerOpenIDAuthNInterface(AbstractAuthNInterface):
29    '''Authentication interface class for OpenIDProviderMiddleware to enable
30    authentication to a Session Manager instance running in the same WSGI
31    stack or via a SOAP call to a remote service
32   
33    @type dbParamNames: tuple
34    @cvar dbParamNames: permitted config keywords.  Nb. SQL queries takes
35    String Template style '$' substitutions for username, password and OpenID
36    identifier'''
37   
38    dbParamNames = (
39        'connectionString',
40        'logonSQLQuery', 
41        'userIdentifiersSQLQuery')
42   
43    def __init__(self, **prop):
44        """Make any initial settings
45       
46        Settings are held in a dictionary which can be set from **prop,
47        a call to setProperties() or by passing settings in an XML file
48        given by propFilePath
49       
50        @type **prop: dict
51        @param **prop: set properties via keywords
52        @raise AuthNInterfaceConfigError: error with configuration
53        """
54        try:
55            for name in SessionManagerOpenIDAuthNInterface.dbParamNames:
56                setattr(self, name, prop.pop(name))
57               
58        except KeyError, e:
59            raise AuthNInterfaceConfigError("Missing property setting for "
60                                            "database connection: %s" % e)
61
62        self._client = WSGISessionManagerClient(**prop)
63       
64        # Set at login
65        self.sessionId = None
66       
67    def logon(self, environ, userIdentifier, username, password):
68        """Interface login method
69       
70        @type environ: dict
71        @param environ: standard WSGI environ parameter
72
73        @type userIdentifier: basestring
74        @param userIdentifier: portion of user's identity URL which uniquely
75        identifies them e.g. 'joebloggs' in the identity URL
76        'https://joebloggs.somewhere.ac.uk/'
77       
78        @type username: basestring
79        @param username: username
80       
81        @type password: basestring
82        @param password: corresponding password for username givens
83       
84        @raise AuthNInterfaceUsername2IdentifierMismatch: no OpenID
85        identifiers match the given username
86        @raise AuthNInterfaceInvalidCredentials: invalid username/password
87        """
88        if userIdentifier is not None:
89            # Check for a match between the OpenID user identifier and the
90            # username
91            try:
92                dbEngine = create_engine(self.connectionString)
93                connection = dbEngine.connect()
94            except Exception, e:
95                log.error('Connecting database for user logon query : %s' % e)
96                raise
97           
98            try:
99                try:
100                    queryInputs = dict(username=username,
101                                       userIdentifier=userIdentifier)
102                    query=Template(self.logonSQLQuery).substitute(queryInputs)
103                    result = connection.execute(query)
104                except Exception, e:
105                    log.error('Connecting database for user logon query : %s'%
106                              e)
107                    raise
108               
109                if not result.rowcount:
110                    raise AuthNInterfaceUsername2IdentifierMismatch()
111            finally:
112                connection.close()
113       
114        try:
115            self._client.environ = environ
116            self.sessionId = self._client.connect(username, 
117                                                  passphrase=password)[-1]
118           
119        except AuthNServiceInvalidCredentials, e:
120            log.exception(e)
121            raise AuthNInterfaceInvalidCredentials()
122       
123   
124    def username2UserIdentifiers(self, environ, username):
125        """Map the login username to an identifier which will become the
126        unique path suffix to the user's OpenID identifier.  The
127        OpenIDProviderMiddleware takes the ID URL template and adds it to this
128        identifier e.g.
129       
130            identifier = self._authN.username2UserIdentifiers(username)
131            identityURL = http://mysite/openid/${userIdentifier}
132       
133        @type environ: dict
134        @param environ: standard WSGI environ parameter
135       
136        @type username: basestring
137        @param username: user identifier
138       
139        @rtype: tuple
140        @return: identifiers to be used to make OpenID user identity URLs.
141       
142        @raise AuthNInterfaceRetrieveError: error with retrieval of information
143        to identifier e.g. error with database look-up.
144        """
145        try:
146            dbEngine = create_engine(self.connectionString)
147            connection = dbEngine.connect()
148        except Exception, e:
149            log.error('Connecting database for user identifiers query : %s'%e)
150            raise
151           
152        try:
153            try:
154                tmpl = Template(self.userIdentifiersSQLQuery)
155                sqlQuery = tmpl.substitute(dict(username=username))
156                result = connection.execute(sqlQuery)
157                if not result.rowcount:
158                    raise AuthNInterfaceRetrieveError()
159               
160                userIdentifiers = tuple([row.values()[0] for row in result])
161            except Exception, e:
162                log.error('Querying database for user identifiers for user '
163                          '"%s": %s' (username, e))
164                raise
165        finally:
166            connection.close()
167           
168        return userIdentifiers
169
170    def logout(self):
171        """logout from the Session Manager
172        """
173        try:
174            self._client.disconnect(sessID=self.sessionId)
175           
176        except Exception, e:
177            log.exception(e)
178            raise AuthNInterfaceInvalidCredentials()
Note: See TracBrowser for help on using the repository browser.