source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/relyingparty/__init__.py @ 4905

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid/relyingparty/__init__.py@4905
Revision 4905, 5.9 KB checked in by pjkersha, 11 years ago (diff)

Initial working version of OpenID Relying Party middleware - this is an RP factored out of the original functionality included in the SSO Pylons project.

Line 
1"""NDG Security OpenID Relying Party Middleware
2
3Wrapper to AuthKit OpenID Middleware
4
5NERC DataGrid Project
6"""
7__author__ = "P J Kershaw"
8__date__ = "20/01/2009"
9__copyright__ = "(C) 2009 Science and Technology Facilities Council"
10__license__ = "BSD - see top-level directory for LICENSE file"
11__contact__ = "Philip.Kershaw@stfc.ac.uk"
12__revision__ = "$Id$"
13import logging
14log = logging.getLogger(__name__)
15
16import httplib # to get official status code messages
17
18import authkit.authenticate
19import beaker.middleware
20
21from ndg.security.server.wsgi import NDGSecurityMiddlewareBase
22from ndg.security.common.utils.classfactory import instantiateClass
23
24class OpenIDRelyingPartyMiddlewareError(Exception):
25    """OpenID Relying Party WSGI Middleware Error"""
26
27class OpenIDRelyingPartyConfigError(OpenIDRelyingPartyMiddlewareError):
28    """OpenID Relying Party Configuration Error"""
29 
30class OpenIDRelyingPartyMiddleware(NDGSecurityMiddlewareBase):
31    '''Implementation of OpenID Relying Party based on AuthKit'''
32    propertyDefaults = {
33        'signinInterfaceMiddlewareClass': None
34    }
35    propertyDefaults.update(NDGSecurityMiddlewareBase.propertyDefaults)
36   
37    def __init__(self, app, global_conf, prefix='openid.relyingparty.', 
38                 **app_conf):
39        """Add AuthKit and Beaker middleware dependencies to WSGI stack
40       
41        @type app: callable following WSGI interface signature
42        @param app: next middleware application in the chain     
43        @type global_conf: dict       
44        @param global_conf: PasteDeploy application global configuration -
45        must follow format of propertyDefaults class variable
46        @type prefix: basestring
47        @param prefix: prefix for OpenID Relying Party configuration items
48        @type app_conf: dict
49        @param app_conf: application specific configuration - must follow
50        format of propertyDefaults class variable"""   
51
52           
53        authKitApp = authkit.authenticate.middleware(app, app_conf)
54        app = beaker.middleware.SessionMiddleware(authKitApp)
55               
56        # Check for sign in template settings
57        if prefix+'signinInterfaceMiddlewareClass' in app_conf:
58            if 'authkit.openid.template.obj' in app_conf:
59                log.warning("OpenID Relying Party "
60                            "'signinInterfaceMiddlewareClass' "
61                            "setting overrides 'authkit.openid.template.obj' "
62                            "AuthKit setting")
63               
64            moduleName, className = \
65                app_conf[prefix+'signinInterfaceMiddlewareClass'].rsplit('.',1)
66           
67            signinInterfacePrefix = prefix+'signinInterface.'
68            classProperties = {'prefix': signinInterfacePrefix}
69            classProperties.update(app_conf)
70            app = instantiateClass(moduleName, className, 
71                                   objectType=SigninInterface, 
72                                   classArgs=(app, global_conf),
73                                   classProperties=classProperties)           
74           
75            # Delete sign in interface middleware settings
76            for conf in app_conf, global_conf or {}:
77                for k in conf.keys():
78                    if k.startswith(signinInterfacePrefix):
79                        del conf[k]
80       
81            authKitApp.template = app.getTemplateFunc()#app.makeTemplate()
82
83        super(OpenIDRelyingPartyMiddleware, self).__init__(app, 
84                                                           global_conf, 
85                                                           prefix=prefix, 
86                                                           **app_conf)
87               
88    def __call__(self, environ, start_response):
89        '''Alter start_response to override the status code and force to 401.
90        This will non-browser based client code to bypass the OpenID interface
91        '''
92        def setUnauthorizedResponse(status, header, exc_info=None):
93            return start_response("%s %s" % (401, httplib.responses[401]), 
94                                  header,
95                                  exc_info)
96           
97        return self._app(environ, setUnauthorizedResponse)
98
99class SigninInterfaceError(Exception):
100    """Base class for SigninInterface exceptions
101   
102    A standard message is raised set by the msg class variable but the actual
103    exception details are logged to the error log.  The use of a standard
104    message enables callers to use its content for user error messages.
105   
106    @type msg: basestring
107    @cvar msg: standard message to be raised for this exception"""
108    userMsg = ("An internal error occurred with the page layout,  Please "
109               "contact your system administrator")
110    errorMsg = "SigninInterface error"
111   
112    def __init__(self, *arg, **kw):
113        if len(arg) > 0:
114            msg = arg[0]
115        else:
116            msg = self.__class__.errorMsg
117           
118        log.error(msg)
119        Exception.__init__(self, msg, **kw)
120       
121class SigninInterfaceInitError(SigninInterfaceError):
122    """Error with initialisation of SigninInterface.  Raise from __init__"""
123    errorMsg = "SigninInterface initialisation error"
124   
125class SigninInterfaceConfigError(SigninInterfaceError):
126    """Error with configuration settings.  Raise from __init__"""
127    errorMsg = "SigninInterface configuration error"   
128
129class SigninInterface(NDGSecurityMiddlewareBase):
130    """Base class for sign in rendering.  This is implemented as WSGI
131    middleware to enable additional middleware to be added into the call
132    stack e.g. StaticFileParser to enable rendering of graphics and other
133    static content in the Sign In page"""
134   
135    def getTemplateFunc(self):
136        """Return template function for AuthKit to render OpenID Relying
137        Party Sign in page"""
138        raise NotImplementedError()
139   
140    def __call__(self, environ, start_response):
141        return self._app(self, environ, start_response)
Note: See TracBrowser for help on using the repository browser.