def __init__(self, app, global_conf, prefix='', **app_conf): ''' :type app: callable following WSGI interface :param app: next middleware application in the chain :type global_conf: dict :param global_conf: PasteDeploy global configuration dictionary :type prefix: basestring :param prefix: prefix for configuration items :type app_conf: dict :param app_conf: PasteDeploy application specific configuration dictionary ''' # Set logout URI parameter from AuthKit settings if not otherwise set sessionHandlerPrefix = prefix + SessionHandlerMiddleware.PARAM_PREFIX app = SessionHandlerMiddleware(app, global_conf, prefix=sessionHandlerPrefix, **app_conf) # Remove session handler middleware specific parameters for k in app_conf.keys(): if k.startswith(sessionHandlerPrefix): del app_conf[k] # Override AuthKit cookie handling to use version compatible with # CEDA site services dj_security app_conf['authkit.cookie.ticket_class'] = SecureCookie # Hack to force authkit to use SecureCookie's parse_ticket function import authkit.authenticate.cookie authkit.authenticate.cookie.parse_ticket = SecureCookie.parse_ticket # This also requires special handling of cookie secret - the secret is # include in the ini file base 64 encoded but for actual use, needs to # be in decoded form encoded_cookie_secret = app_conf.get('authkit.cookie.secret') if not encoded_cookie_secret: raise AuthnConfigError('Error, "authkit.cookie.secret" setting ' 'is missing. It must be set as a base 64 ' 'encoded string') app_conf['authkit.cookie.secret'] = encoded_cookie_secret.decode( 'base64') app = authkit.authenticate.middleware(app, app_conf) MultiHandler.__init__(self, app) # Redirection middleware is invoked based on a check method which # catches HTTP 401 responses. self.add_method(AuthnRedirectInitiatorMiddleware.MIDDLEWARE_ID, AuthnRedirectInitiatorMiddleware.filter_app_factory, global_conf, prefix=prefix, **app_conf) self.add_checker(AuthnRedirectInitiatorMiddleware.MIDDLEWARE_ID, AuthnRedirectInitiatorMiddleware.checker)
def filter_app_factory(cls, app, global_conf, prefix='', **app_conf): """Set-up Policy Enforcement Point to enforce access control decisions based on the URI path requested and/or the HTTP response code set by application(s) to be protected. An AuthKit ``MultiHandler`` is setup to handle the latter. ``PEPResultHandlerMiddleware`` handles the output set following an access denied decision :type app: callable following WSGI interface :param app: next middleware application in the chain :type global_conf: dict :param global_conf: ``PasteDeploy`` global configuration dictionary :type prefix: basestring :param prefix: prefix for configuration items :type app_conf: dict :param app_conf: ``PasteDeploy`` application specific configuration \ dictionary """ # Allow for static content for use with PEP result handler middleware resultHandlerParamPrefix = prefix + cls.RESULT_HANDLER_PARAM_PREFIX resultHandlerStaticContentDirParamName = \ resultHandlerParamPrefix + \ cls.RESULT_HANDLER_STATIC_CONTENT_DIR_PARAMNAME resultHandlerStaticContentDir = app_conf.get( resultHandlerStaticContentDirParamName) if resultHandlerStaticContentDir is not None: staticApp = StaticURLParser(resultHandlerStaticContentDir) app = Cascade([app, staticApp], catch=(httplib.NOT_FOUND,)) pepPrefix = prefix + cls.PEP_PARAM_PREFIX pepFilter = cls.PEP_FILTER.filter_app_factory(app, global_conf, prefix=pepPrefix, **app_conf) # Now add the multi-handler to enable result handler to be invoked on # 403 forbidden status from upstream middleware app = MultiHandler(pepFilter) resultHandlerClassName = app_conf.pop( prefix+cls.RESULT_HANDLER_PARAMNAME, None) if resultHandlerClassName is None: resultHandler = PEPResultHandlerMiddleware else: resultHandler = importClass(resultHandlerClassName, objectType=PEPResultHandlerMiddlewareBase) app.add_method(resultHandler.__class__.__name__, resultHandler.filter_app_factory, global_conf, prefix=resultHandlerParamPrefix, **app_conf) app.add_checker(resultHandler.__class__.__name__, Http403ForbiddenStatusHandler.intercept) return app
def make_passurl_handler( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.openid', ): app, auth_handler_params, user_setter_params = load_openid_config( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.openid', ) # Note, the session middleware should already be setup by now # if we are not using beaker app = MultiHandler(app) app.add_method( 'openid', OpenIDAuthHandler, template=auth_handler_params['template'], path_verify=auth_handler_params['path_verify'], baseurl=auth_handler_params['baseurl'], charset=auth_handler_params['charset'], ) app.add_checker('openid', status_checker) # XXX Some of this functionality should be moved into OpenIDAuthHandler app = OpenIDUserSetter(app, **user_setter_params) return app
def make_basic_auth_handler( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.basic', ): app, auth_handler_params, user_setter_params = load_basic_config( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.basic', ) app = MultiHandler(app) app.add_method('basic', BasicAuthHandler, auth_handler_params['realm'], auth_handler_params['authfunc']) app.add_checker('basic', status_checker) app = BasicUserSetter( app, user_setter_params['realm'], user_setter_params['authfunc'], user_setter_params['users'], ) return app
def make_digest_auth_handler( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.digest', ): app, auth_handler_params, user_setter_params = load_digest_config( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.digest', ) app = MultiHandler(app) app.add_method( 'digest', DigestAuthHandler, auth_handler_params['realm'], auth_handler_params['authfunc'] ) app.add_checker('digest', status_checker) app = DigestUserSetter( app, user_setter_params['realm'], user_setter_params['authfunc'], user_setter_params['users'], ) return app
def make_form_handler( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.method.form', ): app, auth_handler_params, user_setter_params = load_form_config( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.method.form', ) app = MultiHandler(app) app.add_method( 'form', FormAuthHandler, authfunc=auth_handler_params['authfunc'], template=auth_handler_params['template'], charset=auth_handler_params['charset'], method=auth_handler_params['method'], action=auth_handler_params['action'], user_data=auth_handler_params['user_data'], ) app.add_checker('form', status_checker) return app
def find_multi_app(app): """Walks an app assuming it is a middleware stack with apps glued on at either self.app or self.application Returns a tuple of the MultiHandler app ref and the possibly new app stack. If a multihandler app wasn't found, then it will be at the top of the returned app. """ tempref = app while not isinstance(tempref, MultiHandler): tempref = getattr(tempref, 'app', getattr(tempref, 'application', None)) if tempref is None: app = MultiHandler(app) tempref = app return tempref, app
def make_forward_handler( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.forward', ): if not auth_conf.has_key('internalpath'): raise AuthKitConfigError("No %sinternalpath key specified" % prefix) app = MultiHandler(app) app.add_method('forward', Redirect, auth_conf['internalpath']) app.add_checker('forward', status_checker) app = MyRecursive(RecursiveMiddleware(app)) return app
def make_redirect_handler( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.method.redirect.', ): app = MultiHandler(app) app.add_method('redirect', HandleRedirect, redirect_to=auth_conf['url']) app.add_checker('redirect', status_checker) return app
def make_forward_handler( app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.forward', ): signin_path = None if auth_conf.has_key('internalpath'): warnings.warn( 'The %sinternalpath key is deprecated. Please use ' '%ssigninpath.' % (prefix, prefix), DeprecationWarning, 2) signin_path = auth_conf['internalpath'] elif auth_conf.has_key('signinpath'): signin_path = auth_conf['signinpath'] else: raise AuthKitConfigError("No %ssigninpath key specified" % prefix) app = MultiHandler(app) app.add_method('forward', Redirect, signin_path) app.add_checker('forward', status_checker) app = MyRecursive(RecursiveMiddleware(app)) return app
def make_multi_middleware(app, auth_conf, app_conf=None, global_conf=None, prefix='authkit.'): # Load the configurations and any associated middleware app, oid_auth_params, oid_user_params = load_openid_config( app, strip_base(auth_conf, 'openid.')) app, form_auth_params, form_user_params = load_form_config( app, strip_base(auth_conf, 'form.')) app, cookie_auth_params, cookie_user_params = load_cookie_config( app, strip_base(auth_conf, 'cookie.')) app, basic_auth_params, basic_user_params = load_basic_config( app, strip_base(auth_conf, 'basic.')) app, digest_auth_params, digest_user_params = load_digest_config( app, strip_base(auth_conf, 'digest.')) # The cookie plugin doesn't provide an AuthHandler so no config assert cookie_auth_params == None # The form plugin doesn't provide a UserSetter (it uses cookie) assert form_user_params == None # Setup the MultiHandler to switch between authentication methods # based on the value of environ['authkit.authhandler'] if a 401 is # raised app = MultiHandler(app) app.add_method('openid', OpenIDAuthHandler, **oid_auth_params) app.add_checker('openid', EnvironKeyAuthSwitcher('openid')) app.add_method('basic', BasicAuthHandler, **basic_auth_params) app.add_checker('basic', EnvironKeyAuthSwitcher('basic')) app.add_method('digest', DigestAuthHandler, **digest_auth_params) app.add_checker('digest', EnvironKeyAuthSwitcher('digest')) app.add_method('form', FormAuthHandler, **form_auth_params) app.add_checker('form', Default()) # Add the user setters to set REMOTE_USER on each request once the # user is signed on. app = DigestUserSetter(app, **digest_user_params) app = BasicUserSetter(app, **basic_user_params) # OpenID relies on cookie so needs to be set up first app = OpenIDUserSetter(app, **oid_user_params) app = CookieUserSetter(app, **cookie_user_params) return app