def who_args(config): auth_by_username = MediaDropAuthenticatorPlugin.by_attribute('user_name') form = FriendlyFormPlugin( login_form_url, login_handler_url, post_login_url, logout_handler_url, post_logout_url, rememberer_name='cookie', charset='utf-8', ) cookie_secret = config['sa_auth.cookie_secret'] seconds_30_days = 30*24*60*60 # session expires after 30 days cookie = MediaDropCookiePlugin(cookie_secret, cookie_name='authtkt', timeout=seconds_30_days, # session expires after 30 days reissue_time=seconds_30_days/2, # reissue cookie after 15 days ) who_args = { 'authenticators': [ ('auth_by_username', auth_by_username) ], 'challenge_decider': default_challenge_decider, 'challengers': [('form', form)], 'classifier': classifier_for_flash_uploads, 'identifiers': [('main_identifier', form), ('cookie', cookie)], 'mdproviders': [], } return who_args
def make_faswho_middleware(app, log_stream, login_handler='/login_handler', login_form_url='/login', logout_handler='/logout_handler', post_login_url='/post_login', post_logout_url=None): faswho = FASWhoPlugin(FAS_URL) csrf_mdprovider = CSRFMetadataProvider(login_handler=login_handler) form = FriendlyFormPlugin(login_form_url, login_handler, post_login_url, logout_handler, post_logout_url, rememberer_name='fasident') form.classifications = { IIdentifier: ['browser'], IChallenger: ['browser'] } # only for browser identifiers = [('form', form), ('fasident', faswho)] authenticators = [('fasauth', faswho)] challengers = [('form', form)] mdproviders = [('fasmd', faswho), ('csrfmd', csrf_mdprovider)] if os.environ.get('FAS_WHO_LOG'): log_stream = sys.stdout app = CSRFProtectionMiddleware(app) app = PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, default_request_classifier, default_challenge_decider, log_stream = log_stream, ) return app
def setup_auth(app, config): groupadapter = InstanceGroupSourceAdapter() #groupadapter.translations.update({'sections': 'groups'}) permissionadapter = SqlPermissionsAdapter(model.Permission, model.Group, model.meta.Session) #permissionadapter.translations.update(permission_translations) group_adapters = {'sql_auth': groupadapter} permission_adapters = {'sql_auth': permissionadapter} basicauth = BasicAuthPlugin('Adhocracy HTTP Authentication') auth_tkt = InstanceAuthTktCookiePlugin( '41d207498d3812741e27c6441760ae494a4f9fbf', cookie_name='adhocracy_login', timeout=86400 * 2, reissue_time=3600) form = FriendlyFormPlugin( '/login', '/perform_login', '/post_login', '/logout', '/post_logout', login_counter_name='_login_tries', rememberer_name='auth_tkt') sqlauth = SQLAlchemyAuthenticatorPlugin(model.User, model.meta.Session) sql_user_md = SQLAlchemyUserMDPlugin(model.User, model.meta.Session) identifiers = [('form', form), ('basicauth', basicauth), ('auth_tkt', auth_tkt)] authenticators = [('sqlauth', sqlauth), ('auth_tkt', auth_tkt)] challengers = [('form', form), ('basicauth', basicauth)] mdproviders = [('sql_user_md', sql_user_md)] log_stream = None #log_stream = sys.stdout return setup_what(app, group_adapters, permission_adapters, identifiers=identifiers, authenticators=authenticators, challengers=challengers, mdproviders=mdproviders, log_stream=log_stream, log_level=logging.DEBUG, # kwargs passed to repoze.who.plugins.testutils: skip_authentication=config.get('skip_authentication'), remote_user_key='HTTP_REMOTE_USER')
def AuthenticationMiddleware(app, config): from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin from repoze.who.plugins.basicauth import BasicAuthPlugin from repoze.who.plugins.friendlyform import FriendlyFormPlugin from repoze.who.plugins.cookie import InsecureCookiePlugin from repoze.what.plugins.ini import INIPermissionsAdapter from repoze.what.middleware import setup_auth conn = ldap.get_conn() cookie = InsecureCookiePlugin('__ac') loginform = FriendlyFormPlugin(login_form_url="/login", login_handler_path="/do_login", post_login_url="/login", logout_handler_path="/logout", post_logout_url="/login", rememberer_name="_ac") authenticator = auth.Authenticator(conn) groups = auth.GroupAdapter(conn) groups = {'all_groups': groups} basicauth = BasicAuthPlugin('Private web site') if 'auth.basic' in config: identifiers = [("basicauth", basicauth)] challengers = [("basicauth", basicauth)] else: identifiers = [("loginform", loginform), ("_ac", cookie), ("basicauth", basicauth)] challengers = [("loginform", loginform)] authenticators = [("accounts", authenticator)] mdproviders = [("accounts", auth.MDPlugin(conn))] permissions = { 'all_perms': INIPermissionsAdapter(config['auth.permissions']) } return setup_auth(app, groups, permissions, identifiers=identifiers, authenticators=authenticators, challengers=challengers, mdproviders=mdproviders)
def make_plugin(login_form_url, login_handler_path, logout_handler_path, rememberer_name, post_login_url=None, post_logout_url=None, login_counter_name=None): if login_form_url is None: raise ValueError('must include login_form_url in configuration') if login_handler_path is None: raise ValueError('login_handler_path must not be None') if logout_handler_path is None: raise ValueError('logout_handler_path must not be None') if rememberer_name is None: raise ValueError( 'must include rememberer key (name of another IIdentifier plugin)') plugin = FriendlyFormPlugin(login_form_url, login_handler_path, post_login_url, logout_handler_path, post_logout_url, rememberer_name, login_counter_name) return plugin
def setup_sql_auth(app, user_class, group_class, permission_class, dbsession, form_plugin=None, form_identifies=True, cookie_secret='secret', cookie_name='authtkt', login_url='/login', login_handler='/login_handler', post_login_url=None, logout_handler='/logout_handler', post_logout_url=None, login_counter_name=None, translations={}, cookie_timeout=None, cookie_reissue_time=None, charset="iso-8859-1", use_default_authenticator=True, **who_args): """ Configure :mod:`repoze.who` and :mod:`repoze.what` with SQL-only authentication and authorization, respectively. :param app: Your WSGI application. :param user_class: The SQLAlchemy/Elixir class for the users. :param group_class: The SQLAlchemy/Elixir class for the groups. :param permission_class: The SQLAlchemy/Elixir class for the permissions. :param dbsession: The SQLAlchemy/Elixir session. :param form_plugin: The main :mod:`repoze.who` challenger plugin; this is usually a login form. :param form_identifies: Whether the ``form_plugin`` may and should act as an :mod:`repoze.who` identifier. :type form_identifies: bool :param cookie_secret: The "secret" for the AuthTktCookiePlugin (**set a custom one!**). :type cookie_secret: str :param cookie_name: The name for the AuthTktCookiePlugin. :type cookie_name: str :param login_url: The URL where the login form is displayed. :type login_url: str :param login_handler: The URL where the login form is submitted. :type login_handler: str :param post_login_url: The URL/path where users should be redirected to after login. :type post_login_url: str :param logout_handler: The URL where the logout is handled. :type login_handler: str :param post_logout_url: The URL/path where users should be redirected to after logout. :type post_logout_url: str :param login_counter_name: The name of the variable in the query string that represents the login counter; defaults to ``__logins``. :type login_counter_name: str :param translations: The model translations. :type translations: dict :param cookie_timeout: The time (in seconds) during which the session cookie would be valid. :type cookie_timeout: :class:`int` :param cookie_reissue_time: How often should the session cookie be reissued (in seconds); must be less than ``timeout``. :type cookie_reissue_time: :class:`int` :param use_default_authenticator: Whether the default SQL authenticator should be used. :type use_default_authenticator: :class:`bool` :return: The WSGI application with authentication and authorization middleware. It configures :mod:`repoze.who` with the following plugins: * Identifiers: * :class:`repoze.who.plugins.friendlyform.FriendlyFormPlugin` as the first identifier and challenger -- using ``login`` as the URL/path where the login form will be displayed, ``login_handler`` as the URL/path where the form will be sent and ``logout_handler`` as the URL/path where the user will be logged out. The so-called *rememberer* of such an identifier will be the identifier below. If ``post_login_url`` is defined, the user will be redirected to that page after login. Likewise, if ``post_logout_url`` is defined, the user will be redirected to that page after logout. You can override the :class:`repoze.who.plugins.friendlyform.FriendlyFormPlugin`'s login counter variable name (which defaults to ``__logins``) by defining ``login_counter_name``. .. tip:: This plugin may be overridden with the ``form_plugin`` argument. See also the ``form_identifies`` argument. * :class:`repoze.who.plugins.auth_tkt.AuthTktCookiePlugin`. You can customize the cookie name and secret using the ``cookie_name`` and ``cookie_secret`` arguments, respectively. Then it will append the identifiers you pass through the ``identifiers`` keyword argument, if any. * Authenticators: * :class:`repoze.who.plugins.sa.SQLAlchemyAuthenticatorPlugin` (unless ``use_default_authenticator`` is ``False``), using the ``user_class`` and ``dbsession`` arguments as its user class and DB session, respectively. Then it will be appended to the authenticators you pass through the ``authenticators`` keyword argument, if any. The default authenticator would have the lowest precedence. * Challengers: * The same Form-based plugin used in the identifiers. Then it will append the challengers you pass through the ``challengers`` keyword argument, if any. * Metadata providers: * :class:`repoze.who.plugins.sa.SQLAlchemyUserMDPlugin`, using the ``user_class`` and ``dbsession`` arguments as its user class and DB session, respectively. Then it will append the metadata providers you pass through the ``mdproviders`` keyword argument, if any. The ``charset`` is passed to any component which needs to decode/encode data to/from the user. At present, only :class:`~repoze.who.plugins.friendlyform.FriendlyFormPlugin` does. Additional keyword arguments will be passed to :class:`repoze.who.middleware.PluggableAuthenticationMiddleware`. .. warning:: It's very important to set a custom ``cookie_secret``! It's the key to encrypt *and* decrypt the cookies, so you shouldn't leave the default one. .. note:: If you don't want to use the groups/permissions-based authorization pattern, then set ``group_class`` and ``permission_class`` to ``None``. .. versionchanged:: 1.0.5 Introduced the ``cookie_timeout`` and ``cookie_reissue_time`` arguments. .. versionchanged:: 1.0.6 Introduced the ``charset`` argument. .. versionchanged:: 1.0.8 Introduced the ``use_default_authenticator`` argument. """ plugin_translations = find_plugin_translations(translations) source_adapters = configure_sql_adapters( user_class, group_class, permission_class, dbsession, plugin_translations['group_adapter'], plugin_translations['permission_adapter']) group_adapters= {} group_adapter = source_adapters.get('group') if group_adapter: group_adapters = {'sql_auth': group_adapter} permission_adapters = {} permission_adapter = source_adapters.get('permission') if permission_adapter: permission_adapters = {'sql_auth': permission_adapter} # Setting the repoze.who authenticators: if 'authenticators' not in who_args: who_args['authenticators'] = [] if use_default_authenticator: sqlauth = SQLAlchemyAuthenticatorPlugin(user_class, dbsession) sqlauth.translations.update(plugin_translations['authenticator']) who_args['authenticators'].append(('sqlauth', sqlauth)) cookie = AuthTktCookiePlugin(cookie_secret, cookie_name, timeout=cookie_timeout, reissue_time=cookie_reissue_time) # Setting the repoze.who identifiers if 'identifiers' not in who_args: who_args['identifiers'] = [] who_args['identifiers'].append(('cookie', cookie)) if form_plugin is None: form = FriendlyFormPlugin( login_url, login_handler, post_login_url, logout_handler, post_logout_url, login_counter_name=login_counter_name, rememberer_name='cookie', charset=charset, ) else: form = form_plugin if form_identifies: who_args['identifiers'].insert(0, ('main_identifier', form)) # Setting the repoze.who challengers: if 'challengers' not in who_args: who_args['challengers'] = [] who_args['challengers'].append(('form', form)) # Setting up the repoze.who mdproviders: sql_user_md = SQLAlchemyUserMDPlugin(user_class, dbsession) sql_user_md.translations.update(plugin_translations['mdprovider']) if 'mdproviders' not in who_args: who_args['mdproviders'] = [] who_args['mdproviders'].append(('sql_user_md', sql_user_md)) # Including logging log_file = who_args.pop('log_file', None) if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout elif log_file.lower() == 'stderr': log_stream = sys.stderr else: log_stream = open(log_file, 'wb') who_args['log_stream'] = log_stream log_level = who_args.get('log_level', None) if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] who_args['log_level'] = log_level middleware = setup_auth(app, group_adapters, permission_adapters, **who_args) return middleware
def setup_sql_auth(app, user_class, group_class, permission_class, dbsession, form_plugin=None, form_identifies=True, cookie_secret='secret', cookie_name='authtkt', login_url='/login', login_handler='/login_handler', post_login_url=None, logout_handler='/logout_handler', post_logout_url=None, login_counter_name=None, translations={}, **who_args): """ Configure :mod:`repoze.who` and :mod:`repoze.what` with SQL-only authentication and authorization, respectively. :param app: Your WSGI application. :param user_class: The SQLAlchemy/Elixir class for the users. :param group_class: The SQLAlchemy/Elixir class for the groups. :param permission_class: The SQLAlchemy/Elixir class for the permissions. :param dbsession: The SQLAlchemy/Elixir session. :param form_plugin: The main :mod:`repoze.who` challenger plugin; this is usually a login form. :param form_identifies: Whether the ``form_plugin`` may and should act as an :mod:`repoze.who` identifier. :type form_identifies: bool :param cookie_secret: The "secret" for the AuthTktCookiePlugin. :type cookie_secret: str :param cookie_name: The name for the AuthTktCookiePlugin. :type cookie_name: str :param login_url: The URL where the login form is displayed. :type login_url: str :param login_handler: The URL where the login form is submitted. :type login_handler: str :param post_login_url: The URL/path where users should be redirected to after login. :type post_login_url: str :param logout_handler: The URL where the logout is handled. :type login_handler: str :param post_logout_url: The URL/path where users should be redirected to after logout. :type post_logout_url: str :param login_counter_name: The name of the variable in the query string that represents the login counter; defaults to ``__logins``. :type login_counter_name: str :param translations: The model translations. :type translations: dict :return: The WSGI application with authentication and authorization middleware. It configures :mod:`repoze.who` with the following plugins: * Identifiers: * :class:`repoze.who.plugins.friendlyform.FriendlyFormPlugin` as the first identifier and challenger -- using ``login`` as the URL/path where the login form will be displayed, ``login_handler`` as the URL/path where the form will be sent and ``logout_handler`` as the URL/path where the user will be logged out. The so-called *rememberer* of such an identifier will be the identifier below. If ``post_login_url`` is defined, the user will be redirected to that page after login. Likewise, if ``post_logout_url`` is defined, the user will be redirected to that page after logout. You can override the :class:`repoze.who.plugins.friendlyform.FriendlyFormPlugin`'s login counter variable name (which defaults to ``__logins``) by defining ``login_counter_name``. .. tip:: This plugin may be overridden with the ``form_plugin`` argument. See also the ``form_identifies`` argument. * :class:`repoze.who.plugins.auth_tkt.AuthTktCookiePlugin`. You can customize the cookie name and secret using the ``cookie_name`` and ``cookie_secret`` arguments, respectively. Then it will append the identifiers you pass through the ``identifiers`` keyword argument, if any. * Authenticators: * :class:`repoze.who.plugins.sa.SQLAlchemyAuthenticatorPlugin`, using the ``user_class`` and ``dbsession`` arguments as its user class and DB session, respectively. Then it will append the authenticators you pass through the ``authenticators`` keyword argument, if any. * Challengers: * The same Form-based plugin used in the identifiers. Then it will append the challengers you pass through the ``challengers`` keyword argument, if any. * Metadata providers: * :class:`repoze.who.plugins.sa.SQLAlchemyUserMDPlugin`, using the ``user_class`` and ``dbsession`` arguments as its user class and DB session, respectively. Then it will append the metadata providers you pass through the ``mdproviders`` keyword argument, if any. Additional keyword arguments will be passed to :class:`repoze.who.middleware.PluggableAuthenticationMiddleware`. .. note:: If you don't want to use the groups/permissions-based authorization pattern, then set ``group_class`` and ``permission_class`` to ``None``. """ plugin_translations = find_plugin_translations(translations) if group_class is None or permission_class is None: group_adapters = permission_adapters = None else: source_adapters = configure_sql_adapters( user_class, group_class, permission_class, dbsession, plugin_translations['group_adapter'], plugin_translations['permission_adapter']) group_adapters = {'sql_auth': source_adapters['group']} permission_adapters = {'sql_auth': source_adapters['permission']} # Setting the repoze.who authenticators: sqlauth = SQLAlchemyAuthenticatorPlugin(user_class, dbsession) sqlauth.translations.update(plugin_translations['authenticator']) if 'authenticators' not in who_args: who_args['authenticators'] = [] who_args['authenticators'].append(('sqlauth', sqlauth)) cookie = AuthTktCookiePlugin(cookie_secret, cookie_name) # Setting the repoze.who identifiers if 'identifiers' not in who_args: who_args['identifiers'] = [] who_args['identifiers'].append(('cookie', cookie)) if form_plugin is None: form = FriendlyFormPlugin(login_url, login_handler, post_login_url, logout_handler, post_logout_url, login_counter_name=login_counter_name, rememberer_name='cookie') else: form = form_plugin if form_identifies: who_args['identifiers'].insert(0, ('main_identifier', form)) # Setting the repoze.who challengers: if 'challengers' not in who_args: who_args['challengers'] = [] who_args['challengers'].append(('form', form)) # Setting up the repoze.who mdproviders: sql_user_md = SQLAlchemyUserMDPlugin(user_class, dbsession) sql_user_md.translations.update(plugin_translations['mdprovider']) if 'mdproviders' not in who_args: who_args['mdproviders'] = [] who_args['mdproviders'].append(('sql_user_md', sql_user_md)) middleware = setup_auth(app, group_adapters, permission_adapters, **who_args) return middleware
def make_faswho_middleware(app, log_stream=None, login_handler='/login_handler', login_form_url='/login', logout_handler='/logout_handler', post_login_url='/post_login', post_logout_url=None, fas_url=FAS_URL, insecure=False, ssl_cookie=True, httponly=True): ''' :arg app: WSGI app that is being wrapped :kwarg log_stream: :class:`logging.Logger` to log auth messages :kwarg login_handler: URL where the login form is submitted :kwarg login_form_url: URL where the login form is displayed :kwarg logout_handler: URL where the logout form is submitted :kwarg post_login_url: URL to redirect the user to after login :kwarg post_logout_url: URL to redirect the user to after logout :kwarg fas_url: Base URL to the FAS server :kwarg insecure: Allow connecting to a fas server without checking the server's SSL certificate. Opens you up to MITM attacks but can be useful when testing. *Do not enable this in production* :kwarg ssl_cookie: If :data:`True` (default), tell the browser to only send the session cookie back over https. :kwarg httponly: If :data:`True` (default), tell the browser that the session cookie should only be read for sending to a server, not for access by JavaScript or other clientside technology. This prevents using the session cookie to pass information to JavaScript clients but also prevents XSS attacks from stealing the session cookie information. ''' # Because of the way we override values (via a dict in AppConfig), we # need to make this a keyword arg and then check it here to make it act # like a positional arg. if not log_stream: raise TypeError( 'log_stream must be set when calling make_fasauth_middleware()') faswho = FASWhoPlugin(fas_url, insecure=insecure, ssl_cookie=ssl_cookie, httponly=httponly) csrf_mdprovider = CSRFMetadataProvider() form = FriendlyFormPlugin(login_form_url, login_handler, post_login_url, logout_handler, post_logout_url, rememberer_name='fasident', charset='utf-8') form.classifications = { IIdentifier: ['browser'], IChallenger: ['browser'] } # only for browser basicauth = BasicAuthPlugin('repoze.who') identifiers = [('form', form), ('fasident', faswho), ('basicauth', basicauth)] authenticators = [('fasauth', faswho)] challengers = [('form', form), ('basicauth', basicauth)] mdproviders = [('fasmd', faswho), ('csrfmd', csrf_mdprovider)] if os.environ.get('FAS_WHO_LOG'): log_stream = sys.stdout app = CSRFProtectionMiddleware(app) app = PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, fas_request_classifier, default_challenge_decider, log_stream=log_stream, ) return app
def make_faswho_middleware( app, log_stream=None, login_handler='/login_handler', login_form_url='/login', logout_handler='/logout_handler', post_login_url='/post_login', post_logout_url=None, fas_url=FAS_URL, insecure=False, ssl_cookie=True, httponly=True): ''' :arg app: WSGI app that is being wrapped :kwarg log_stream: :class:`logging.Logger` to log auth messages :kwarg login_handler: URL where the login form is submitted :kwarg login_form_url: URL where the login form is displayed :kwarg logout_handler: URL where the logout form is submitted :kwarg post_login_url: URL to redirect the user to after login :kwarg post_logout_url: URL to redirect the user to after logout :kwarg fas_url: Base URL to the FAS server :kwarg insecure: Allow connecting to a fas server without checking the server's SSL certificate. Opens you up to MITM attacks but can be useful when testing. *Do not enable this in production* :kwarg ssl_cookie: If :data:`True` (default), tell the browser to only send the session cookie back over https. :kwarg httponly: If :data:`True` (default), tell the browser that the session cookie should only be read for sending to a server, not for access by JavaScript or other clientside technology. This prevents using the session cookie to pass information to JavaScript clients but also prevents XSS attacks from stealing the session cookie information. ''' # Because of the way we override values (via a dict in AppConfig), we # need to make this a keyword arg and then check it here to make it act # like a positional arg. if not log_stream: raise TypeError( 'log_stream must be set when calling make_fasauth_middleware()') faswho = FASWhoPlugin(fas_url, insecure=insecure, ssl_cookie=ssl_cookie, httponly=httponly) csrf_mdprovider = CSRFMetadataProvider() form = FriendlyFormPlugin(login_form_url, login_handler, post_login_url, logout_handler, post_logout_url, rememberer_name='fasident', charset='utf-8') form.classifications = {IIdentifier: ['browser'], IChallenger: ['browser']} # only for browser basicauth = BasicAuthPlugin('repoze.who') identifiers = [ ('form', form), ('fasident', faswho), ('basicauth', basicauth) ] authenticators = [('fasauth', faswho)] challengers = [('form', form), ('basicauth', basicauth)] mdproviders = [('fasmd', faswho), ('csrfmd', csrf_mdprovider)] if os.environ.get('FAS_WHO_LOG'): log_stream = sys.stdout app = CSRFProtectionMiddleware(app) app = PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, fas_request_classifier, default_challenge_decider, log_stream=log_stream, ) return app
def setup_auth(app, config): groupadapter = InstanceGroupSourceAdapter() #groupadapter.translations.update({'sections': 'groups'}) permissionadapter = SqlPermissionsAdapter(model.Permission, model.Group, model.meta.Session) #permissionadapter.translations.update(permission_translations) group_adapters = {'sql_auth': groupadapter} permission_adapters = {'sql_auth': permissionadapter} basicauth = BasicAuthPlugin('Adhocracy HTTP Authentication') auth_tkt = InstanceAuthTktCookiePlugin( config, config.get('adhocracy.auth.secret', config['beaker.session.secret']), cookie_name='adhocracy_login', timeout=86400 * 2, reissue_time=3600, secure=config.get('adhocracy.protocol', 'http') == 'https') sqlauth = EmailSQLAlchemyAuthenticatorPlugin(model.User, model.meta.Session) sql_user_md = SQLAlchemyUserMDPlugin(model.User, model.meta.Session) login_urls = [ '/login', '/perform_login', '/post_login', '/logout', '/post_logout', ] login_options = dict( login_counter_name='_login_tries', rememberer_name='auth_tkt', charset='utf-8', ) if config.get('adhocracy.login_style') == 'alternate': form = AlternateLoginFriendlyFormPlugin(sqlauth.get_user, *login_urls, **login_options) else: form = FriendlyFormPlugin(*login_urls, **login_options) identifiers = [('form', form), ('basicauth', basicauth), ('auth_tkt', auth_tkt)] authenticators = [('sqlauth', sqlauth), ('auth_tkt', auth_tkt)] challengers = [('form', form), ('basicauth', basicauth)] mdproviders = [('sql_user_md', sql_user_md)] welcome.setup_auth(config, identifiers, authenticators) log_stream = None #log_stream = sys.stdout # If a webserver already sets a HTTP_REMOTE_USER environment variable, # repoze.who merely acts as a pass through and doesn't set up the proper # environment (e.g. environ['repoze.who.api'] is missing). # # This happens for example in the case of Shibboleth based authentication - # we weren't able to prevent mod_shibboleth from setting the header. # Therefore the remote user key to look for is not set to HTTP_REMOTE_USER, # but to the non-existing DONT_USE_HTTP_REMOTE_USER environment variable. REMOTE_USER_KEY = 'DONT_USE_HTTP_REMOTE_USER' return setup_what( app, group_adapters, permission_adapters, identifiers=identifiers, authenticators=authenticators, challengers=challengers, mdproviders=mdproviders, log_stream=log_stream, log_level=logging.DEBUG, # kwargs passed to repoze.who.plugins.testutils: skip_authentication=config.get('skip_authentication'), remote_user_key=REMOTE_USER_KEY)
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp() # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) basicauth = BasicAuthPlugin('OpenSpending') auth_tkt = AuthTktCookiePlugin( 'RANDOM_KEY_THAT_ONLY_LOOKS_LIKE_A_PLACEHOLDER', cookie_name='openspending_login', timeout=86400 * 90, reissue_time=3600) form = FriendlyFormPlugin('/login', '/perform_login', '/after_login', '/logout', '/after_logout', rememberer_name='auth_tkt') identifiers = [('auth_tkt', auth_tkt), ('basicauth', basicauth), ('form', form)] authenticators = [('auth_tkt', auth_tkt), ('username', UsernamePasswordAuthenticator()), ('apikey', ApiKeyAuthenticator())] challengers = [('form', form), ('basicauth', basicauth)] log_stream = sys.stdout app = PluggableAuthenticationMiddleware(app, identifiers, authenticators, challengers, [], default_request_classifier, default_challenge_decider, log_stream=log_stream, log_level=logging.WARN) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): max_age = None if asbool(config['debug']) else 3600 # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=max_age) static_parsers = [static_app, app] app = Cascade(static_parsers) return app
def make_app(global_conf, full_stack=True, **app_conf): """ Set munkireport up with the settings found in the PasteDeploy configuration file used. :param global_conf: The global settings for munkireport (those defined under the ``[DEFAULT]`` section). :type global_conf: dict :param full_stack: Should the whole TG2 stack be set up? :type full_stack: str or bool :return: The munkireport application with all the relevant middleware loaded. This is the PasteDeploy factory for the munkireport application. ``app_conf`` contains all the application-specific settings (those defined under ``[app:main]``. """ app = make_base_app(global_conf, full_stack=True, **app_conf) # Wrap your base TurboGears 2 application with custom middleware here # Initialize repoze.what plugins. groups_path = os.path.join(global_conf.get("appsupport_dir"), "groups.ini") groups = { "ini_groups": INIGroupAdapter(app_conf.get("what.groups_file", groups_path)), "dscl_groups": MacOSXGroupAdapter() } permissions_path = os.path.join(global_conf.get("appsupport_dir"), "permissions.ini") permissions = { "ini_permissions": INIPermissionsAdapter(app_conf.get("what.permissions_file", permissions_path)) } # Initialize repoze.who plugins. friendlyform = FriendlyFormPlugin( "/login", "/login_handler", None, "/logout_handler", None, "auth_tkt", login_counter_name=None ) friendlyform.classifications = { IIdentifier: ['browser'], IChallenger: ['browser'] } auth_tkt = AuthTktPlugin(secret=app_conf["beaker.session.secret"]) macosx_authenticator = MacOSXAuthenticator() macosx_metadataprovider = MacOSXMetadataProvider() file_authenticator = FileAuthenticator() file_metadataprovider = FileMetadataProvider() # Configuration for repoze.who. identifiers = [ ('friendlyform', friendlyform), ('auth_tkt', auth_tkt) ] authenticators = [ ('macosx_authenticator', macosx_authenticator), ('file_authenticator', file_authenticator) ] challengers = [ ('friendlyform', friendlyform) ] mdproviders = [ ('macosx_metadataprovider', macosx_metadataprovider), ('file_metadataprovider', file_metadataprovider) ] # Setup authentication and authorization through repoze.what. app = setup_auth( app, groups, permissions, identifiers=identifiers, authenticators=authenticators, challengers=challengers, mdproviders=mdproviders, #log_stream=sys.stdout, #log_level=logging.DEBUG ) return app
def setup_auth(app, authmetadata, form_plugin=None, form_identifies=True, cookie_secret='secret', cookie_name='authtkt', login_url='/login', login_handler='/login_handler', post_login_url=None, logout_handler='/logout_handler', post_logout_url=None, login_counter_name=None, cookie_timeout=None, cookie_reissue_time=None, charset="iso-8859-1", **who_args): """ Sets :mod:`repoze.who` up with the provided authenticators and options to create FriendlyFormPlugin. It returns a middleware that provides identification, authentication and authorization in a way that is compatible with repoze.who and repoze.what. """ # If no identifiers are provided in repoze setup arguments # then create a default one using AuthTktCookiePlugin. if 'identifiers' not in who_args: from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin cookie = AuthTktCookiePlugin(cookie_secret, cookie_name, timeout=cookie_timeout, reissue_time=cookie_reissue_time) who_args['identifiers'] = [('cookie', cookie)] who_args['authenticators'].insert(0, ('cookie', cookie)) # If no form plugin is provided then create a default # one using the provided options. if form_plugin is None: from repoze.who.plugins.friendlyform import FriendlyFormPlugin form = FriendlyFormPlugin(login_url, login_handler, post_login_url, logout_handler, post_logout_url, login_counter_name=login_counter_name, rememberer_name='cookie', charset=charset) else: form = form_plugin if form_identifies: who_args['identifiers'].insert(0, ('main_identifier', form)) # Setting the repoze.who challengers: if 'challengers' not in who_args: who_args['challengers'] = [] who_args['challengers'].append(('form', form)) # Including logging log_file = who_args.pop('log_file', None) if log_file is not None: if log_file.lower() == 'stdout': log_stream = sys.stdout elif log_file.lower() == 'stderr': log_stream = sys.stderr else: log_stream = open(log_file, 'wb') who_args['log_stream'] = log_stream log_level = who_args.get('log_level', None) if log_level is None: log_level = logging.INFO else: log_level = _LEVELS[log_level.lower()] who_args['log_level'] = log_level # Setting up the metadata provider for the user informations if 'mdproviders' not in who_args: who_args['mdproviders'] = [] if authmetadata: authmd = _AuthMetadataProvider(authmetadata) who_args['mdproviders'].append(('authmd', authmd)) # Set up default classifier if 'classifier' not in who_args: who_args['classifier'] = default_request_classifier # Set up default challenger decider if 'challenge_decider' not in who_args: who_args['challenge_decider'] = default_challenge_decider skip_authn = who_args.pop('skip_authentication', False) if asbool(skip_authn): return _AuthenticationForgerMiddleware(app, **who_args) else: return PluggableAuthenticationMiddleware(app, **who_args)