Changeset 14667


Ignore:
Timestamp:
5 Apr 2017, 13:06:02 (8 years ago)
Author:
uli
Message:

Add XMLRPC-aware auth credentials plugin.

This new plugin can be used to authenticate users in a site
(i.e. normally officers of a University instance) with
regular HTTP basic auth credentials (normally we expect a
web form, where credentials are sent as form-vars).

This plugin is registered in _new_ University instances
automatically, but it is _not_ registered with already
existing PAUs.

Location:
main/waeup.kofa/trunk/src/waeup/kofa
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/authentication.py

    r13394 r14667  
    2929from zope.pluggableauth.factories import Principal
    3030from zope.pluggableauth.plugins.session import SessionCredentialsPlugin
     31from zope.pluggableauth.plugins.httpplugins import (
     32        HTTPBasicAuthCredentialsPlugin)
    3133from zope.pluggableauth.interfaces import (
    3234        ICredentialsPlugin, IAuthenticatorPlugin,
     
    5052    Then looks for any external utilities that want to modify the PAU.
    5153    """
    52     pau.credentialsPlugins = ('No Challenge if Authenticated', 'credentials')
     54    pau.credentialsPlugins = (
     55            'No Challenge if Authenticated',
     56            'xmlrpc-credentials',
     57            'credentials')
    5358    pau.authenticatorPlugins = ('users',)
    5459
     
    7176class KofaSessionCredentialsPlugin(grok.GlobalUtility,
    7277                                    SessionCredentialsPlugin):
     78    """Session plugin that picks usernames/passwords from fields in webforms.
     79    """
    7380    grok.provides(ICredentialsPlugin)
    7481    grok.name('credentials')
     
    7784    loginfield = 'form.login'
    7885    passwordfield = 'form.password'
     86
     87
     88class KofaXMLRPCCredentialsPlugin(
     89        grok.GlobalUtility, HTTPBasicAuthCredentialsPlugin):
     90    """Plugin that picks useranams/passwords from basic-auth headers.
     91
     92    As XMLRPC requests send/post their authentication credentials in HTTP
     93    basic-auth headers, we need a plugin that can handle this.
     94
     95    This plugin, however, does no challenging. If a user does not provide
     96    basic-auth infos, we will not ask for some. This is correct as we plan to
     97    communicate with machines.
     98
     99    This plugin is planned to be used in "PluggableAuthenitications" registered
     100    with `University` instances.
     101    """
     102    grok.provides(ICredentialsPlugin)
     103    grok.name('xmlrpc-credentials')
     104
     105    def challenge(self, request):
     106        """XMLRPC is for machines. No need to challenge.
     107        """
     108        return False
     109
     110    def logout(self, request):
     111        """Basic auth does not provide any logout possibility.
     112        """
     113        return False
     114
    79115
    80116class KofaPrincipalInfo(object):
  • main/waeup.kofa/trunk/src/waeup/kofa/tests/test_authentication.py

    r10055 r14667  
    2121import unittest
    2222from cStringIO import StringIO
    23 from zope.component import getGlobalSiteManager
     23from zope.component import getGlobalSiteManager, queryUtility
    2424from zope.component.hooks import setSite, clearSite
    2525from zope.interface.verify import verifyClass, verifyObject
    2626from zope.password.testing import setUpPasswordManagers
    27 from zope.pluggableauth.interfaces import IAuthenticatorPlugin
     27from zope.pluggableauth import PluggableAuthentication
     28from zope.pluggableauth.interfaces import (
     29    IAuthenticatorPlugin, ICredentialsPlugin)
     30from zope.publisher.browser import TestRequest
    2831from zope.securitypolicy.interfaces import IPrincipalRoleManager
    2932from waeup.kofa.testing import FunctionalTestCase, FunctionalLayer
    3033from waeup.kofa.authentication import (
    3134    UserAuthenticatorPlugin, Account, KofaPrincipalInfo, FailedLoginInfo,
    32     get_principal_role_manager, UsersPlugin,)
     35    get_principal_role_manager, UsersPlugin, KofaXMLRPCCredentialsPlugin,
     36    setup_authentication)
    3337from waeup.kofa.interfaces import (
    34     IUserAccount, IFailedLoginInfo, IKofaPrincipalInfo, IKofaPluggable)
     38    IAuthPluginUtility, IUserAccount, IFailedLoginInfo, IKofaPrincipalInfo,
     39    IKofaPluggable)
     40
    3541
    3642class FakeSite(grok.Site, grok.Container):
     
    3945    #    return getGlobalSiteManager()
    4046    pass
     47
     48
     49class FakeAuthPlugin(object):
     50    def register(self, pau):
     51        pau.credentialsPlugins += ('foo', )
     52
     53
     54class Test_setup_authentication(FunctionalTestCase):
     55    # Tests for the `setup_authentication` function
     56
     57    layer = FunctionalLayer
     58
     59    def tearDown(self):
     60        # clean up registry.
     61        gsm = getGlobalSiteManager()
     62        for iface, name in ((IAuthPluginUtility, 'myauth'), ):
     63            to_delete = queryUtility(iface, name=name)
     64            if to_delete is not None:
     65                gsm.unregisterUtility(provided=iface, name=name)
     66        super(Test_setup_authentication, self).tearDown()
     67
     68    def test_plugins_are_registered(self):
     69        # We can populate a PAU with (hardcoded set of) plugins
     70        pau = PluggableAuthentication()
     71        setup_authentication(pau)
     72        for name in (
     73                'No Challenge if Authenticated',
     74                'xmlrpc-credentials',
     75                'credentials'):
     76            assert name in pau.credentialsPlugins
     77        for name in ('users', ):
     78            assert name in pau.authenticatorPlugins
     79
     80    def test_external_plugins_are_registered(self):
     81        # registered plugins are called as well
     82        gsm = getGlobalSiteManager()
     83        gsm.registerUtility(
     84            MyFakeAuthPlugin(), IAuthPluginUtility, name='myauth')
     85        pau = PluggableAuthentication()
     86        setup_authentication(pau)
     87        assert 'foo' in pau.credentialsPlugins
     88
     89
     90class KofaXMLRPCCredentialsPluginTests(FunctionalTestCase):
     91    # Test for XMLRPC credentials plugin
     92
     93    layer = FunctionalLayer
     94
     95    def test_ifaces(self):
     96        # we meet interface requirements
     97        plugin = KofaXMLRPCCredentialsPlugin()
     98        self.assertTrue(
     99            verifyClass(ICredentialsPlugin, KofaXMLRPCCredentialsPlugin))
     100
     101    def test_util_is_registered(self):
     102        # we can query this named utility
     103        util = queryUtility(ICredentialsPlugin, name='xmlrpc-credentials')
     104        assert util is not None
     105
     106    def test_can_extract_creds(self):
     107        # we can extract credentials from appropriate requests
     108        req = TestRequest(
     109            environ={'HTTP_AUTHORIZATION': u'Basic bWdyOm1ncnB3'})
     110        plugin = KofaXMLRPCCredentialsPlugin()
     111        assert plugin.extractCredentials(req) == {
     112            'login': 'mgr', 'password': 'mgrpw'}
     113
     114    def test_challenge_disabled(self):
     115        # we will not challenge people
     116        plugin = KofaXMLRPCCredentialsPlugin()
     117        assert plugin.challenge(TestRequest()) is False
     118
     119    def test_logout_disabled(self):
     120        # we do not support logging out. HTTP basic auth cannot do this.
     121        plugin = KofaXMLRPCCredentialsPlugin()
     122        assert plugin.logout(TestRequest()) is False
     123
    41124
    42125class UserAuthenticatorPluginTests(FunctionalTestCase):
Note: See TracChangeset for help on using the changeset viewer.