Example #1
0
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
Example #2
0
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
Example #3
0
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')
Example #4
0
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
Example #6
0
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
Example #8
0
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
Example #9
0
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
Example #10
0
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)
Example #11
0
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
Example #12
0
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
Example #13
0
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)