def make_app(controller_klass, environ={}): """Creates a ``TestApp`` instance.""" # The basic middleware: app = ControllerWrap(controller_klass) app = SetupCacheGlobal(app, environ, setup_cache=True, setup_session=True) app = RegistryManager(app) app = SessionMiddleware(app, {}, data_dir=session_dir) app = CacheMiddleware(app, {}, data_dir=os.path.join(data_dir, 'cache')) # We're not going to use groups or permissions-related predicates here: groups_adapters = None permissions_adapters = None # Setting repoze.who up: cookie = AuthTktCookiePlugin('secret', 'authtkt') identifiers = [('cookie', cookie)] app = setup_auth(app, groups_adapters, permissions_adapters, identifiers=identifiers, authenticators=[], challengers=[], skip_authentication=True) app = httpexceptions.make_middleware(app) return TestApp(app)
def make_auth_app(global_conf, **app_conf): """example authenticated app with an htpasswd file""" assert 'auth.htpasswd' in app_conf assert os.path.exists(app_conf['auth.htpasswd']) app_conf['traclegos.auth'] = True # make the app app = make_app(global_conf, **app_conf) # wrap in repoze.who authentication middleware htpasswd_auth = HTPasswdPlugin(app_conf['auth.htpasswd'], check) auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') form = RedirectingFormPlugin('/', '/login', '/logout', 'auth_tkt') identifiers = [('form', form), ('auth_tkt', auth_tkt)] authenticators = [('htpasswd_auth', htpasswd_auth)] challengers = [('form', form)] from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider log_stream = None return PluggableAuthenticationMiddleware(app, identifiers, authenticators, challengers, [], default_request_classifier, default_challenge_decider, log_stream=None, log_level=logging.DEBUG)
def make_app(controller_klass, environ=None, with_errors=False, config_options=None): """Creates a ``TestApp`` instance.""" authmetadata = TestAuthMetadata() config_options = config_options or {} config_options.setdefault('sa_auth', {}) sa_auth = config_options['sa_auth'] sa_auth.update({'authmetadata': authmetadata}) app = base_make_app(controller_klass, environ or {}, config_options, with_errors).app # Setting repoze.who up: from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin cookie = AuthTktCookiePlugin('secret', 'authtkt') identifiers = [('cookie', cookie)] app = setup_auth(app, identifiers=identifiers, skip_authentication=True, authenticators=[], challengers=[]) # As setup_auth with skip_authentication sets empty authenticators always # we must manually append it after creating the middleware. app.api_factory.authenticators.append(('cookie', cookie)) return TestApp(app)
def _makeApp(self, groups, permissions, **who_args): cookie = AuthTktCookiePlugin('secret', 'authtkt') form = RedirectingFormPlugin('/login', '/login_handler', '/logout_handler', rememberer_name='cookie') identifiers = [('main_identifier', form), ('cookie', cookie)] authenticators = [('fake_authenticator', FakeAuthenticator())] challengers = [('form', form)] if groups is None: app_with_auth = setup_auth(DummyApp(), identifiers=identifiers, authenticators=authenticators, challengers=challengers, **who_args) else: app_with_auth = setup_auth(DummyApp(), groups, permissions, identifiers=identifiers, authenticators=authenticators, challengers=challengers, **who_args) return app_with_auth
def make_app(controller_klass, environ={}, with_errors=False): """Creates a ``TestApp`` instance.""" # The basic middleware: app = TGApp(config=default_config) app.controller_classes['root'] = ControllerWrap(controller_klass) app = FakeRoutes(app) if with_errors: app = ErrorHandler(app, {}, debug=False) app = StatusCodeRedirect(app, [403, 404, 500]) app = RegistryManager(app) app = SessionMiddleware(app, {}, data_dir=session_dir) app = CacheMiddleware(app, {}, data_dir=os.path.join(data_dir, 'cache')) # Setting repoze.who up: from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin cookie = AuthTktCookiePlugin('secret', 'authtkt') identifiers = [('cookie', cookie)] app = setup_auth(app, TGAuthMetadata(), identifiers=identifiers, skip_authentication=True, authenticators=[], challengers=[]) return TestApp(app)
def test_skip_authentication_is_not_boolean(self): identifiers = [('cookie', AuthTktCookiePlugin('something'))] authenticators = challengers = mdproviders = [] # Skipping authentication: mw = make_middleware('True', None, identifiers, authenticators, challengers, mdproviders, None, None) self.assertEqual(mw.__class__, AuthenticationForgerMiddleware) # With authentication: mw = make_middleware('False', None, identifiers, authenticators, challengers, mdproviders, None, None) self.assertEqual(mw.__class__, PluggableAuthenticationMiddleware) # With skip_authentication==None -> authentication enabled: mw = make_middleware(None, None, identifiers, authenticators, challengers, mdproviders, None, None) self.assertEqual(mw.__class__, PluggableAuthenticationMiddleware)
def test_without_skipping_authentication(self): identifiers = [('cookie', AuthTktCookiePlugin('something'))] authenticators = challengers = mdproviders = [] mw = make_middleware(False, None, identifiers, authenticators, challengers, mdproviders, None, None) assert isinstance(mw, PluggableAuthenticationMiddleware) # Checking the identifiers: final_identifiers = mw.registry[IIdentifier] self.assertEqual(1, len(final_identifiers)) assert isinstance(final_identifiers[0], AuthTktCookiePlugin) # Checking the other plugins: assert IAuthenticator not in mw.registry assert IChallenger not in mw.registry assert IMetadataProvider not in mw.registry # Checking REMOTE_USER keys: self.assertEqual(mw.remote_user_key, 'REMOTE_USER')
def test_it_with_fake_user_key(self): identifiers = [('cookie', AuthTktCookiePlugin('something'))] authenticators = challengers = mdproviders = [] mw = AuthenticationForgerMiddleware(None, identifiers, authenticators, challengers, mdproviders, None, None, remote_user_key='userid') assert isinstance(mw, AuthenticationForgerMiddleware) final_identifiers = mw.registry[IIdentifier] auth_forger = final_identifiers[0] # Checking REMOTE_USER keys: self.assertEqual(mw.remote_user_key, 'repoze.who.testutil.userid') self.assertEqual(mw.actual_remote_user_key, 'userid') # Finally, let's check the AuthenticationForgerPlugin in detail: self.assertEqual(auth_forger.fake_user_key, 'userid') self.assertEqual(auth_forger.remote_user_key, 'repoze.who.testutil.userid')
def AuthBasicMiddleware(app, conf, user_class): groups = GroupAdapter(user_class) groups = {'all_groups': groups} permissions = {'all_perms': PermissionAdapter(conf["couchdb.db"])} basicauth = BasicAuth() cookie = AuthTktCookiePlugin(conf['cookies.secret']) who_args = {} who_args['authenticators'] = [('accounts', Authenticator(user_class))] who_args['challengers'] = [('basicauth', basicauth)] who_args['identifiers'] = [('basicauth', basicauth), ('cookie', cookie)] who_args['mdproviders'] = [('accounts', MDPlugin(user_class))] who_args['log_stream'] = sys.stdout who_args['log_level'] = logging.DEBUG return setup_auth(app, groups, permissions, **who_args)
def make_ldap_auth_app(global_conf, **app_conf): """example authenticated app with ldap""" assert 'auth.base_dn' in app_conf, "No base_dn specified" assert 'auth.ldap_host' in app_conf, "No ldap_host specified" app_conf['traclegos.auth'] = True # make the app app = make_app(global_conf, **app_conf) # XXX bad touch # this should really be passed to the make_app factory and used there # but there's no current way of doing this intelligently app.application.remote_user_name = ldap_remote_user # get the ldap connection conn = ldap.open(app_conf['auth.ldap_host']) if app_conf.get('auth.use_tls', 'False').lower() == 'true': conn.start_tls_s() # wrap in repoze.who authentication middleware ldap_auth = LDAPAuthenticatorPlugin(conn, app_conf['auth.base_dn']) auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') form = RedirectingFormPlugin('/', '/login', '/logout', 'auth_tkt') identifiers = [('form', form), ('auth_tkt', auth_tkt)] authenticators = [('ldap_auth', ldap_auth)] challengers = [('form', form)] from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider log_stream = None #import logging #logger = logging.getLogger('something') #logger.setLevel(logging.DEBUG) return PluggableAuthenticationMiddleware(app, identifiers, authenticators, challengers, [], default_request_classifier, default_challenge_decider, log_stream=None, log_level=logging.DEBUG)
def make_app(controller_klass, environ={}, with_errors=False): """Creates a ``TestApp`` instance.""" # The basic middleware: app = ControllerWrap(controller_klass) app = SetupCacheGlobal(app, environ, setup_cache=True, setup_session=True) if with_errors: app = ErrorHandler(app, {}, debug=False) app = StatusCodeRedirect(app, [403, 404, 500]) app = RegistryManager(app) app = SessionMiddleware(app, {}, data_dir=session_dir) app = CacheMiddleware(app, {}, data_dir=os.path.join(data_dir, 'cache')) # Setting repoze.who up: cookie = AuthTktCookiePlugin('secret', 'authtkt') identifiers = [('cookie', cookie)] app = setup_auth(app, TGAuthMetadata(), identifiers=identifiers, skip_authentication=True, authenticators=[], challengers=[]) app = httpexceptions.make_middleware(app) return TestApp(app)
def make_app(controller_klass, environ=None, with_errors=False, config_options=None): """Creates a ``TestApp`` instance.""" # Setting repoze.who up: from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin cookie = AuthTktCookiePlugin('secret', 'authtkt') from tg.configurator.base import ConfigurationComponent class ForceAuthenticatorComponent(ConfigurationComponent): id = "test_force_auth" def get_actions(self): from tg.configurator.base import AppReadyConfigurationAction return ( AppReadyConfigurationAction(self._add_middleware), ) def _add_middleware(self, conf, app): # As setup_auth with skip_authentication sets empty authenticators always # we must manually append it after creating the middleware. app.api_factory.authenticators.append(('cookie', cookie)) return app config_options = config_options or {} config_options.setdefault('sa_auth', {}) sa_auth = config_options['sa_auth'] sa_auth.update({ 'authmetadata': TestAuthMetadata(), 'challengers': [], 'identifiers': [('cookie', cookie)], 'form_identifies': True }) config_options['skip_authentication'] = True config_options['auth_backend'] = 'sqlalchemy' conf = base_make_app(controller_klass, with_errors=with_errors, config_options=config_options, make_app=False) conf._configurator.register(ForceAuthenticatorComponent, after='sa_auth') return TestApp(conf.make_wsgi_app())
def AuthenticationMiddleware(app): import isitopen.model as model import isitopen.lib.helpers as h modelpassword = ModelPasswordPlugin(model) basicauth = BasicAuthPlugin('repoze.who') auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') form = RedirectingFormPlugin( login_form_url=h.url_for(controller='account', action='login'), login_handler_path=h.url_for('login-handler'), logout_handler_path=h.url_for('logout-handler'), rememberer_name='auth_tkt', ) form.classifications = { IIdentifier:['browser'], IChallenger:['browser'] } # only for browser identifiers = [('form', form),('auth_tkt',auth_tkt),('basicauth',basicauth)] authenticators = [('modelpassword', modelpassword)] challengers = [('form',form), ('basicauth',basicauth)] mdproviders = [] from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider log_stream = None import os if os.environ.get('WHO_LOG'): log_stream = sys.stdout return PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, default_request_classifier, default_challenge_decider, log_stream = log_stream, log_level = logging.DEBUG )
def test_skipping_authentication(self): identifiers = [('cookie', AuthTktCookiePlugin('something'))] authenticators = challengers = mdproviders = [] mw = make_middleware(True, None, identifiers, authenticators, challengers, mdproviders, None, None) assert isinstance(mw, AuthenticationForgerMiddleware) # Checking the identifiers: final_identifiers = mw.registry[IIdentifier] self.assertEqual(2, len(final_identifiers)) assert isinstance(final_identifiers[0], AuthenticationForgerPlugin) assert isinstance(final_identifiers[1], AuthTktCookiePlugin) # Checking the other plugins: auth_forger = final_identifiers[0] self.assertEqual([auth_forger], mw.registry[IAuthenticator]) self.assertEqual([auth_forger], mw.registry[IChallenger]) assert IMetadataProvider not in mw.registry # Checking REMOTE_USER keys: self.assertEqual(mw.remote_user_key, 'repoze.who.testutil.userid') self.assertEqual(mw.actual_remote_user_key, 'REMOTE_USER') # Finally, let's check the AuthenticationForgerPlugin in detail: self.assertEqual(auth_forger.fake_user_key, 'REMOTE_USER') self.assertEqual(auth_forger.remote_user_key, 'repoze.who.testutil.userid')
def make_app(controller_klass, environ={}): """Creates a `TestApp` instance.""" app = ControllerWrap(controller_klass) app = SetupCacheGlobal(app, environ, setup_cache=True, setup_session=True) app = RegistryManager(app) app = SessionMiddleware(app, {}, data_dir=session_dir) app = CacheMiddleware(app, {}, data_dir=os.path.join(data_dir, 'cache')) # Setting up the source adapters: groups_adapters = {'my_groups': FakeGroupSourceAdapter()} permissions_adapters = {'my_permissions': FakePermissionSourceAdapter()} # Setting up repoze.who: cookie = AuthTktCookiePlugin('secret', 'authtkt') identifiers = [('cookie', cookie)] app = setup_auth(app, groups_adapters, permissions_adapters, identifiers=identifiers, authenticators=[], challengers=[], skip_authentication=True) app = httpexceptions.make_middleware(app) return TestApp(app)
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_test_middleware(app, global_conf): """ Functionally equivalent to [plugin:redirector] use = repoze.who.plugins.redirector.RedirectorPlugin login_url = /login.html [plugin:auth_tkt] use = repoze.who.plugins.auth_tkt:AuthTktCookiePlugin secret = SEEKRIT cookie_name = oatmeal [plugin:basicauth] use = repoze.who.plugins.basicauth.BasicAuthPlugin realm = repoze.who [plugin:htpasswd] use = repoze.who.plugins.htpasswd.HTPasswdPlugin filename = <...> check_fn = repoze.who.plugins.htpasswd:crypt_check [general] request_classifier = repoze.who.classifiers:default_request_classifier challenge_decider = repoze.who.classifiers:default_challenge_decider [identifiers] plugins = authtkt basicauth [authenticators] plugins = authtkt htpasswd [challengers] plugins = redirector:browser basicauth """ # be able to test without a config file from repoze.who.plugins.basicauth import BasicAuthPlugin from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin from repoze.who.plugins.redirector import RedirectorPlugin from repoze.who.plugins.htpasswd import HTPasswdPlugin io = StringIO() for name, password in [('admin', 'admin'), ('chris', 'chris')]: io.write('%s:%s\n' % (name, password)) io.seek(0) def cleartext_check(password, hashed): return password == hashed #pragma NO COVERAGE htpasswd = HTPasswdPlugin(io, cleartext_check) basicauth = BasicAuthPlugin('repoze.who') auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') redirector = RedirectorPlugin('/login.html') redirector.classifications = {IChallenger: ['browser']} # only for browser identifiers = [ ('auth_tkt', auth_tkt), ('basicauth', basicauth), ] authenticators = [('htpasswd', htpasswd)] challengers = [('redirector', redirector), ('basicauth', basicauth)] mdproviders = [] from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider log_stream = None import os if os.environ.get('WHO_LOG'): log_stream = sys.stdout middleware = PluggableAuthenticationMiddleware(app, identifiers, authenticators, challengers, mdproviders, default_request_classifier, default_challenge_decider, log_stream=log_stream, log_level=logging.DEBUG) return middleware
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_test_middleware(app, global_conf): """ Functionally equivalent to [plugin:form] use = repoze.who.plugins.form.FormPlugin rememberer_name = cookie login_form_qs=__do_login [plugin:cookie] use = repoze.who.plugins.cookie:InsecureCookiePlugin cookie_name = oatmeal [plugin:basicauth] use = repoze.who.plugins.basicauth.BasicAuthPlugin realm = repoze.who [plugin:htpasswd] use = repoze.who.plugins.htpasswd.HTPasswdPlugin filename = <...> check_fn = repoze.who.plugins.htpasswd:crypt_check [general] request_classifier = repoze.who.classifiers:default_request_classifier challenge_decider = repoze.who.classifiers:default_challenge_decider [identifiers] plugins = form:browser cookie basicauth [authenticators] plugins = htpasswd [challengers] plugins = form:browser basicauth """ # be able to test without a config file from repoze.who.plugins.basicauth import BasicAuthPlugin from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin from repoze.who.plugins.cookie import InsecureCookiePlugin from repoze.who.plugins.form import FormPlugin from repoze.who.plugins.htpasswd import HTPasswdPlugin io = StringIO() salt = 'aa' for name, password in [ ('admin', 'admin'), ('chris', 'chris') ]: io.write('%s:%s\n' % (name, password)) io.seek(0) def cleartext_check(password, hashed): return password == hashed #pragma NO COVERAGE htpasswd = HTPasswdPlugin(io, cleartext_check) basicauth = BasicAuthPlugin('repoze.who') auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') cookie = InsecureCookiePlugin('oatmeal') form = FormPlugin('__do_login', rememberer_name='auth_tkt') form.classifications = { IIdentifier:['browser'], IChallenger:['browser'] } # only for browser identifiers = [('form', form),('auth_tkt',auth_tkt),('basicauth',basicauth)] authenticators = [('htpasswd', htpasswd)] challengers = [('form',form), ('basicauth',basicauth)] mdproviders = [] from repoze.who.classifiers import default_request_classifier from repoze.who.classifiers import default_challenge_decider log_stream = None import os if os.environ.get('WHO_LOG'): log_stream = sys.stdout middleware = PluggableAuthenticationMiddleware( app, identifiers, authenticators, challengers, mdproviders, default_request_classifier, default_challenge_decider, log_stream = log_stream, log_level = logging.DEBUG ) return middleware
# Configure the repoze.who middleware: ## fake .htpasswd authentication source io = StringIO() for name, password in [('admin', 'admin'), ('user', 'user')]: io.write('%s:%s\n' % (name, password)) io.seek(0) def cleartext_check(password, hashed): return password == hashed htpasswd = HTPasswdPlugin(io, cleartext_check) ## other plugins basicauth = BasicAuthPlugin('repoze.who') auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt', digest_algo="sha512") redirector = RedirectorPlugin(login_url='/login.html') redirector.classifications = {IChallenger: ['browser']} # only for browser ## group / order plugins by function identifiers = [('auth_tkt', auth_tkt), ('basicauth', basicauth)] authenticators = [('auth_tkt', auth_tkt), ('htpasswd', htpasswd)] challengers = [('redirector', redirector), ('basicauth', basicauth)] mdproviders = [] ## set up who logging, if desired log_stream = None if os.environ.get('WHO_LOG'): log_stream = sys.stdout # Wrap the middleware around the application.
from tg.configuration import AppConfig from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin from repoze.who.plugins.basicauth import BasicAuthPlugin import os authtkt = AuthTktCookiePlugin('authtkt', 'authtkt') basicauth = BasicAuthPlugin("something") import pythondispatchms from pythondispatchms import model, lib base_config = AppConfig() base_config.renderers = [] # True to prevent dispatcher from striping extensions # For example /socket.io would be served by "socket_io" # method instead of "socket". base_config.disable_request_extensions = False # Set None to disable escaping punctuation characters to "_" # when dispatching methods. # Set to a function to provide custom escaping. base_config.dispatch_path_translator = True base_config.prefer_toscawidgets2 = True base_config.package = pythondispatchms # Enable json in expose base_config.renderers.append('json')
# Configure the repoze.who middleware: ## fake .htpasswd authentication source io = StringIO() for name, password in [('admin', 'admin'), ('user', 'user')]: io.write('%s:%s\n' % (name, password)) io.seek(0) def cleartext_check(password, hashed): return password == hashed htpasswd = HTPasswdPlugin(io, cleartext_check) ## other plugins basicauth = BasicAuthPlugin('repoze.who') auth_tkt = AuthTktCookiePlugin('secret', 'auth_tkt') redirector = RedirectorPlugin(login_url='/login.html') redirector.classifications = {IChallenger: ['browser']} # only for browser ## group / order plugins by function identifiers = [('auth_tkt', auth_tkt), ('basicauth', basicauth)] authenticators = [('auth_tkt', auth_tkt), ('htpasswd', htpasswd)] challengers = [('redirector', redirector), ('basicauth', basicauth)] mdproviders = [] ## set up who logging, if desired log_stream = None if os.environ.get('WHO_LOG'): log_stream = sys.stdout # Wrap the middleware around the application.
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_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, **who_args): """ Sets :mod:`repoze.who` up with the provided authenticators and options to create FriendlyFormPlugin/FastFormPlugin. It returns a middleware that provides identification, authentication and authorization in a way that is compatible with repoze.who and repoze.what. """ if 'charset' in who_args: #pragma: no cover log.warn('charset argument in authentication setup is ignored') who_args.pop('charset') # 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 tg.configuration.auth.fastform import FastFormPlugin form = FastFormPlugin(login_url, login_handler, post_login_url, logout_handler, post_logout_url, rememberer_name='cookie', login_counter_name=login_counter_name) 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'] = turbogears_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)
def add_auth(app, site_name, cookie_name, cookie_secret, login_url, login_handler_url, authenticators, mdproviders, groups, permissions): """ Add authentication and authorization middleware to the ``app``. :param app: The WSGI application. :param site_name: the site name used in basic auth box. :param cookie_name: basic auth name and cookie name. :param cookie_secret: unique secret string used to protect sessions. :param login_url: the url for the login page :param login_handler_url: the url for the login handler :param authenticators: list of authenticator plugins :param mdproviders: list of mdprovider plugins :param groups: list of groups plugins :param permissions: list of permissions plugins :return: The same WSGI application, with authentication and authorization middleware. """ get_log().info("add_auth: intialising Repoze") if not authenticators: raise ValueError("No authenticators provided") if not mdproviders: raise ValueError("No mdproviders provided") if not groups: raise ValueError("No groups provided") if not permissions: raise ValueError("No permissions provided") # If we ever change default behavior for challengers and identifiers, # move these to the above function logout_handler = None form = RedirectingFormPlugin( login_url, login_handler_url, logout_handler, rememberer_name='cookie', ) cookie = AuthTktCookiePlugin(cookie_secret, cookie_name) #identifiers = [('main_identifier', form), ('basicauth', basicauth),\ # ('cookie', cookie)] #identifiers = [('basicauth', basicauth), ('cookie', cookie)] identifiers = [('form', form), ('cookie', cookie)] #challengers = [('form', form), ('basicauth', basicauth)] #challengers = [('basicauth', basicauth)] challengers = [('form', form)] #get_log().info(dict(groups)) #get_log().info( dict(permissions)) #get_log().info( identifiers) #get_log().info( authenticators) #get_log().info( challengers ) #get_log().info( mdproviders) app_with_auth = setup_auth( app=app, # # why these are dicts where all the other are lists... group_adapters=dict(groups), permission_adapters=dict(permissions), identifiers=identifiers, authenticators=authenticators, challengers=challengers, mdproviders=mdproviders, log_level=logging.DEBUG ) get_log().info("add_auth: user/group/permission setup OK.") return app_with_auth