diff --git a/doc/source/overview_auth.rst b/doc/source/overview_auth.rst
index ab637fc798..a07b1a872c 100644
--- a/doc/source/overview_auth.rst
+++ b/doc/source/overview_auth.rst
@@ -42,6 +42,91 @@ such as the X-Container-Sync-Key for a container GET or HEAD.
 The user starts a session by sending a ReST request to the auth system to
 receive the auth token and a URL to the Swift system.
 
+-------------
+Keystone Auth
+-------------
+
+Swift is able to authenticate against OpenStack keystone via the
+:mod:`swift.common.middleware.keystoneauth` middleware.
+
+In order to use the ``keystoneauth`` middleware the ``authtoken``
+middleware from keystone will need to be configured.
+
+The ``authtoken`` middleware performs the authentication token
+validation and retrieves actual user authentication information. It
+can be found in the Keystone distribution.
+
+The ``keystoneauth`` middleware performs authorization and mapping the
+``keystone`` roles to Swift's ACLs.
+
+Configuring Swift to use Keystone
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Configuring Swift to use Keystone is relatively straight
+forward.  The first step is to ensure that you have the auth_token
+middleware installed, distributed with keystone it can either be
+dropped in your python path or installed via the keystone package.
+
+You need at first make sure you have a service endpoint of type
+``object-store`` in keystone pointing to your Swift proxy. For example
+having this in your ``/etc/keystone/default_catalog.templates`` ::
+
+  catalog.RegionOne.object_store.name = Swift Service
+  catalog.RegionOne.object_store.publicURL = http://swiftproxy:8080/v1/AUTH_$(tenant_id)s
+  catalog.RegionOne.object_store.adminURL = http://swiftproxy:8080/
+  catalog.RegionOne.object_store.internalURL = http://swiftproxy:8080/v1/AUTH_$(tenant_id)s
+
+On your Swift Proxy server you will want to adjust your main pipeline
+and add auth_token and keystoneauth in your
+``/etc/swift/proxy-server.conf`` like this ::
+
+  [pipeline:main]
+  pipeline = [....] authtoken keystoneauth proxy-logging proxy-server
+
+add the configuration for the authtoken middleware::
+
+  [filter:authtoken]
+  paste.filter_factory = keystone.middleware.auth_token:filter_factory
+  auth_host = keystonehost
+  auth_port = 35357
+  auth_protocol = http
+  auth_uri = http://keystonehost:5000/
+  admin_tenant_name = service
+  admin_user = swift
+  admin_password = password
+
+The actual values for these variables will need to be set depending on
+your situation.  For more information, please refer to the Keystone
+documentation on the ``auth_token`` middleware, but in short:
+
+* Those variables beginning with ``auth_`` point to the Keystone
+  Admin service.  This information is used by the middleware to actually
+  query Keystone about the validity of the
+  authentication tokens.
+* The admin auth credentials (``admin_user``, ``admin_tenant_name``,
+  ``admin_password``) will be used to retrieve an admin token. That
+  token will be used to authorize user tokens behind the scenes.
+
+.. note::
+
+    If support is required for unvalidated users (as with anonymous
+    access) or for tempurl/formpost middleware, authtoken will need
+    to be configured with delay_auth_decision set to 1.
+
+and you can finally add the keystoneauth configuration::
+
+  [filter:keystoneauth]
+  use = egg:swift#keystoneauth
+  operator_roles = admin, swiftoperator
+
+By default the only users able to give ACL or to Create other
+containers are the ones who has the Keystone role specified in the
+``operator_roles`` setting.
+
+This user who have one of those role will be able to give ACLs to
+other users on containers, see the documentation on ACL here
+:mod:`swift.common.middleware.acl`.
+
 --------------
 Extending Auth
 --------------
diff --git a/etc/proxy-server.conf-sample b/etc/proxy-server.conf-sample
index bc56ade7ff..901ab8dbb3 100644
--- a/etc/proxy-server.conf-sample
+++ b/etc/proxy-server.conf-sample
@@ -118,6 +118,32 @@ user_test_tester = testing .admin
 user_test2_tester2 = testing2 .admin
 user_test_tester3 = testing3
 
+# To enable Keystone authentication you need to have the auth token
+# middleware first to be configured. Here is an example below, please
+# refer to the keystone's documentation for details about the
+# different settings.
+#
+# You'll need to have as well the keystoneauth middleware enabled
+# and have it in your main pipeline so instead of having tempauth in
+# there you can change it to: authtoken keystone
+#
+# [filter:authtoken]
+# paste.filter_factory = keystone.middleware.auth_token:filter_factory
+# auth_host = keystonehost
+# auth_port = 35357
+# auth_protocol = http
+# auth_uri = http://keystonehost:5000/
+# admin_tenant_name = service
+# admin_user = swift
+# admin_password = password
+# delay_auth_decision = 1
+#
+# [filter:keystoneauth]
+# use = egg:swift#keystoneauth
+# Operator roles is the role which user would be allowed to manage a
+# tenant and be able to create container or give ACL to others.
+# operator_roles = admin, swiftoperator
+
 [filter:healthcheck]
 use = egg:swift#healthcheck
 # You can override the default log routing for this filter here:
diff --git a/setup.py b/setup.py
index 42b57d3521..185d11feed 100644
--- a/setup.py
+++ b/setup.py
@@ -88,6 +88,7 @@ setup(
             'domain_remap=swift.common.middleware.domain_remap:filter_factory',
             'staticweb=swift.common.middleware.staticweb:filter_factory',
             'tempauth=swift.common.middleware.tempauth:filter_factory',
+            'keystoneauth=swift.common.middleware.keystoneauth:filter_factory',
             'recon=swift.common.middleware.recon:filter_factory',
             'tempurl=swift.common.middleware.tempurl:filter_factory',
             'formpost=swift.common.middleware.formpost:filter_factory',
diff --git a/swift/common/middleware/keystoneauth.py b/swift/common/middleware/keystoneauth.py
new file mode 100644
index 0000000000..72f5fe6d7b
--- /dev/null
+++ b/swift/common/middleware/keystoneauth.py
@@ -0,0 +1,289 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import webob
+
+from swift.common import utils as swift_utils
+from swift.common.middleware import acl as swift_acl
+
+
+class KeystoneAuth(object):
+    """Swift middleware to Keystone authorization system.
+
+    In Swift's proxy-server.conf add this middleware to your pipeline::
+
+        [pipeline:main]
+        pipeline = catch_errors cache authtoken keystoneauth proxy-server
+
+    Make sure you have the authtoken middleware before the
+    keystoneauth middleware.
+
+    The authtoken middleware will take care of validating the user and
+    keystoneauth will authorize access.
+
+    The authtoken middleware is shipped directly with keystone it
+    does not have any other dependences than itself so you can either
+    install it by copying the file directly in your python path or by
+    installing keystone.
+
+    If support is required for unvalidated users (as with anonymous
+    access) or for tempurl/formpost middleware, authtoken will need
+    to be configured with delay_auth_decision set to 1.  See the
+    Keystone documentation for more detail on how to configure the
+    authtoken middleware.
+
+    In proxy-server.conf you will need to have the setting account
+    auto creation to true::
+
+        [app:proxy-server] account_autocreate = true
+
+    And add a swift authorization filter section, such as::
+
+        [filter:keystoneauth]
+        use = egg:swift#keystoneauth
+        operator_roles = admin, swiftoperator
+
+    This maps tenants to account in Swift.
+
+    The user whose able to give ACL / create Containers permissions
+    will be the one that are inside the operator_roles
+    setting which by default includes the admin and the swiftoperator
+    roles.
+
+    The option is_admin if set to true will allow the
+    username that has the same name as the account name to be the owner.
+
+    Example: If we have the account called hellocorp with a user
+    hellocorp that user will be admin on that account and can give ACL
+    to all other users for hellocorp.
+
+    If you need to have a different reseller_prefix to be able to
+    mix different auth servers you can configure the option
+    reseller_prefix in your keystoneauth entry like this :
+
+        reseller_prefix = NEWAUTH_
+
+    Make sure you have a underscore at the end of your new
+    reseller_prefix option.
+
+    :param app: The next WSGI app in the pipeline
+    :param conf: The dict of configuration values
+    """
+    def __init__(self, app, conf):
+        self.app = app
+        self.conf = conf
+        self.logger = swift_utils.get_logger(conf, log_route='keystoneauth')
+        self.reseller_prefix = conf.get('reseller_prefix', 'AUTH_').strip()
+        self.operator_roles = conf.get('operator_roles',
+                                       'admin, swiftoperator')
+        self.reseller_admin_role = conf.get('reseller_admin_role',
+                                            'ResellerAdmin')
+        config_is_admin = conf.get('is_admin', "false").lower()
+        self.is_admin = config_is_admin in swift_utils.TRUE_VALUES
+        cfg_synchosts = conf.get('allowed_sync_hosts', '127.0.0.1')
+        self.allowed_sync_hosts = [h.strip() for h in cfg_synchosts.split(',')
+                                   if h.strip()]
+        config_overrides = conf.get('allow_overrides', 't').lower()
+        self.allow_overrides = config_overrides in swift_utils.TRUE_VALUES
+
+    def __call__(self, environ, start_response):
+        identity = self._keystone_identity(environ)
+
+        # Check if one of the middleware like tempurl or formpost have
+        # set the swift.authorize_override environ and want to control the
+        # authentication
+        if (self.allow_overrides and
+                environ.get('swift.authorize_override', False)):
+            msg = 'Authorizing from an overriding middleware (i.e: tempurl)'
+            self.logger.debug(msg)
+            return self.app(environ, start_response)
+
+        if identity:
+            self.logger.debug('Using identity: %r' % (identity))
+            environ['keystone.identity'] = identity
+            environ['REMOTE_USER'] = identity.get('tenant')
+            environ['swift.authorize'] = self.authorize
+        else:
+            self.logger.debug('Authorizing as anonymous')
+            environ['swift.authorize'] = self.authorize_anonymous
+
+        environ['swift.clean_acl'] = swift_acl.clean_acl
+
+        return self.app(environ, start_response)
+
+    def _keystone_identity(self, environ):
+        """Extract the identity from the Keystone auth component."""
+        if environ.get('HTTP_X_IDENTITY_STATUS') != 'Confirmed':
+            return
+        roles = []
+        if 'HTTP_X_ROLES' in environ:
+            roles = environ['HTTP_X_ROLES'].split(',')
+        identity = {'user': environ.get('HTTP_X_USER_NAME'),
+                    'tenant': (environ.get('HTTP_X_TENANT_ID'),
+                               environ.get('HTTP_X_TENANT_NAME')),
+                    'roles': roles}
+        return identity
+
+    def _get_account_for_tenant(self, tenant_id):
+        return '%s%s' % (self.reseller_prefix, tenant_id)
+
+    def _reseller_check(self, account, tenant_id):
+        """Check reseller prefix."""
+        return account == self._get_account_for_tenant(tenant_id)
+
+    def authorize(self, req):
+        env = req.environ
+        env_identity = env.get('keystone.identity', {})
+        tenant_id, tenant_name = env_identity.get('tenant')
+
+        try:
+            part = swift_utils.split_path(req.path, 1, 4, True)
+            version, account, container, obj = part
+        except ValueError:
+            return webob.exc.HTTPNotFound(request=req)
+
+        user_roles = env_identity.get('roles', [])
+
+        # Give unconditional access to a user with the reseller_admin
+        # role.
+        if self.reseller_admin_role in user_roles:
+            msg = 'User %s has reseller admin authorizing'
+            self.logger.debug(msg % tenant_id)
+            req.environ['swift_owner'] = True
+            return
+
+        # Check if a user tries to access an account that does not match their
+        # token
+        if not self._reseller_check(account, tenant_id):
+            log_msg = 'tenant mismatch: %s != %s' % (account, tenant_id)
+            self.logger.debug(log_msg)
+            return self.denied_response(req)
+
+        # Check the roles the user is belonging to. If the user is
+        # part of the role defined in the config variable
+        # operator_roles (like admin) then it will be
+        # promoted as an admin of the account/tenant.
+        for role in self.operator_roles.split(','):
+            role = role.strip()
+            if role in user_roles:
+                log_msg = 'allow user with role %s as account admin' % (role)
+                self.logger.debug(log_msg)
+                req.environ['swift_owner'] = True
+                return
+
+        # If user is of the same name of the tenant then make owner of it.
+        user = env_identity.get('user', '')
+        if self.is_admin and user == tenant_name:
+            req.environ['swift_owner'] = True
+            return
+
+        referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None))
+
+        authorized = self._authorize_unconfirmed_identity(req, obj, referrers,
+                                                          roles)
+        if authorized:
+            return
+        elif authorized is not None:
+            return self.denied_response(req)
+
+        # Allow ACL at individual user level (tenant:user format)
+        # For backward compatibility, check for ACL in tenant_id:user format
+        if ('%s:%s' % (tenant_name, user) in roles
+                or '%s:%s' % (tenant_id, user) in roles):
+            log_msg = 'user %s:%s or %s:%s allowed in ACL authorizing'
+            self.logger.debug(log_msg % (tenant_name, user, tenant_id, user))
+            return
+
+        # Check if we have the role in the userroles and allow it
+        for user_role in user_roles:
+            if user_role in roles:
+                log_msg = 'user %s:%s allowed in ACL: %s authorizing'
+                self.logger.debug(log_msg % (tenant_name, user, user_role))
+                return
+
+        return self.denied_response(req)
+
+    def authorize_anonymous(self, req):
+        """
+        Authorize an anonymous request.
+
+        :returns: None if authorization is granted, an error page otherwise.
+        """
+        try:
+            part = swift_utils.split_path(req.path, 1, 4, True)
+            version, account, container, obj = part
+        except ValueError:
+            return webob.exc.HTTPNotFound(request=req)
+
+        is_authoritative_authz = (account and
+                                  account.startswith(self.reseller_prefix))
+        if not is_authoritative_authz:
+            return self.denied_response(req)
+
+        referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None))
+        authorized = self._authorize_unconfirmed_identity(req, obj, referrers,
+                                                          roles)
+        if not authorized:
+            return self.denied_response(req)
+
+    def _authorize_unconfirmed_identity(self, req, obj, referrers, roles):
+        """"
+        Perform authorization for access that does not require a
+        confirmed identity.
+
+        :returns: A boolean if authorization is granted or denied.  None if
+                  a determination could not be made.
+        """
+        # Allow container sync.
+        if (req.environ.get('swift_sync_key')
+            and req.environ['swift_sync_key'] ==
+                req.headers.get('x-container-sync-key', None)
+            and 'x-timestamp' in req.headers
+            and (req.remote_addr in self.allowed_sync_hosts
+                 or swift_utils.get_remote_client(req)
+                 in self.allowed_sync_hosts)):
+            log_msg = 'allowing proxy %s for container-sync' % req.remote_addr
+            self.logger.debug(log_msg)
+            return True
+
+        # Check if referrer is allowed.
+        if swift_acl.referrer_allowed(req.referer, referrers):
+            if obj or '.rlistings' in roles:
+                log_msg = 'authorizing %s via referer ACL' % req.referrer
+                self.logger.debug(log_msg)
+                return True
+            return False
+
+    def denied_response(self, req):
+        """Deny WSGI Response.
+
+        Returns a standard WSGI response callable with the status of 403 or 401
+        depending on whether the REMOTE_USER is set or not.
+        """
+        if req.remote_user:
+            return webob.exc.HTTPForbidden(request=req)
+        else:
+            return webob.exc.HTTPUnauthorized(request=req)
+
+
+def filter_factory(global_conf, **local_conf):
+    """Returns a WSGI filter app for use with paste.deploy."""
+    conf = global_conf.copy()
+    conf.update(local_conf)
+
+    def auth_filter(app):
+        return KeystoneAuth(app, conf)
+    return auth_filter
diff --git a/test/unit/common/middleware/test_keystoneauth.py b/test/unit/common/middleware/test_keystoneauth.py
new file mode 100644
index 0000000000..c9c3b99508
--- /dev/null
+++ b/test/unit/common/middleware/test_keystoneauth.py
@@ -0,0 +1,230 @@
+# Copyright (c) 2012 OpenStack, LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import webob
+
+from swift.common.middleware import keystoneauth
+
+
+class FakeApp(object):
+    def __init__(self, status_headers_body_iter=None):
+        self.calls = 0
+        self.status_headers_body_iter = status_headers_body_iter
+        if not self.status_headers_body_iter:
+            self.status_headers_body_iter = iter([('404 Not Found', {}, '')])
+
+    def __call__(self, env, start_response):
+        self.calls += 1
+        self.request = webob.Request.blank('', environ=env)
+        if 'swift.authorize' in env:
+            resp = env['swift.authorize'](self.request)
+            if resp:
+                return resp(env, start_response)
+        status, headers, body = self.status_headers_body_iter.next()
+        return webob.Response(status=status, headers=headers,
+                              body=body)(env, start_response)
+
+
+class SwiftAuth(unittest.TestCase):
+    def setUp(self):
+        self.test_auth = keystoneauth.filter_factory({})(FakeApp())
+
+    def _make_request(self, path=None, headers=None, **kwargs):
+        if not path:
+            path = '/v1/%s/c/o' % self.test_auth._get_account_for_tenant('foo')
+        return webob.Request.blank(path, headers=headers, **kwargs)
+
+    def _get_identity_headers(self, status='Confirmed', tenant_id='1',
+                          tenant_name='acct', user='usr', role=''):
+        return dict(X_IDENTITY_STATUS=status,
+                    X_TENANT_ID=tenant_id,
+                    X_TENANT_NAME=tenant_name,
+                    X_ROLES=role,
+                    X_USER_NAME=user)
+
+    def _get_successful_middleware(self):
+        response_iter = iter([('200 OK', {}, '')])
+        return keystoneauth.filter_factory({})(FakeApp(response_iter))
+
+    def test_confirmed_identity_is_authorized(self):
+        role = self.test_auth.reseller_admin_role
+        headers = self._get_identity_headers(role=role)
+        req = self._make_request('/v1/AUTH_acct/c', headers)
+        resp = req.get_response(self._get_successful_middleware())
+        self.assertEqual(resp.status_int, 200)
+
+    def test_confirmed_identity_is_not_authorized(self):
+        headers = self._get_identity_headers()
+        req = self._make_request('/v1/AUTH_acct/c', headers)
+        resp = req.get_response(self.test_auth)
+        self.assertEqual(resp.status_int, 403)
+
+    def test_anonymous_is_authorized_for_permitted_referrer(self):
+        req = self._make_request(headers={'X_IDENTITY_STATUS': 'Invalid'})
+        req.acl = '.r:*'
+        resp = req.get_response(self._get_successful_middleware())
+        self.assertEqual(resp.status_int, 200)
+
+    def test_anonymous_is_not_authorized_for_unknown_reseller_prefix(self):
+        req = self._make_request(path='/v1/BLAH_foo/c/o',
+                                 headers={'X_IDENTITY_STATUS': 'Invalid'})
+        resp = req.get_response(self.test_auth)
+        self.assertEqual(resp.status_int, 401)
+
+    def test_blank_reseller_prefix(self):
+        conf = {'reseller_prefix': ''}
+        test_auth = keystoneauth.filter_factory(conf)(FakeApp())
+        account = tenant_id = 'foo'
+        self.assertTrue(test_auth._reseller_check(account, tenant_id))
+
+    def test_override_asked_for_but_not_allowed(self):
+        conf = {'allow_overrides': 'false'}
+        self.test_auth = keystoneauth.filter_factory(conf)(FakeApp())
+        req = self._make_request('/v1/AUTH_account',
+                                 environ={'swift.authorize_override': True})
+        resp = req.get_response(self.test_auth)
+        self.assertEquals(resp.status_int, 401)
+
+    def test_override_asked_for_and_allowed(self):
+        conf = {'allow_overrides': 'true'}
+        self.test_auth = keystoneauth.filter_factory(conf)(FakeApp())
+        req = self._make_request('/v1/AUTH_account',
+                                 environ={'swift.authorize_override': True})
+        resp = req.get_response(self.test_auth)
+        self.assertEquals(resp.status_int, 404)
+
+    def test_override_default_allowed(self):
+        req = self._make_request('/v1/AUTH_account',
+                                 environ={'swift.authorize_override': True})
+        resp = req.get_response(self.test_auth)
+        self.assertEquals(resp.status_int, 404)
+
+
+class TestAuthorize(unittest.TestCase):
+    def setUp(self):
+        self.test_auth = keystoneauth.filter_factory({})(FakeApp())
+
+    def _make_request(self, path, **kwargs):
+        return webob.Request.blank(path, **kwargs)
+
+    def _get_account(self, identity=None):
+        if not identity:
+            identity = self._get_identity()
+        return self.test_auth._get_account_for_tenant(identity['tenant'][0])
+
+    def _get_identity(self, tenant_id='tenant_id',
+                      tenant_name='tenant_name', user='user', roles=None):
+        if not roles:
+            roles = []
+        return dict(tenant=(tenant_id, tenant_name), user=user, roles=roles)
+
+    def _check_authenticate(self, account=None, identity=None, headers=None,
+                            exception=None, acl=None, env=None, path=None):
+        if not identity:
+            identity = self._get_identity()
+        if not account:
+            account = self._get_account(identity)
+        if not path:
+            path = '/v1/%s/c' % account
+        default_env = {'keystone.identity': identity,
+                       'REMOTE_USER': identity['tenant']}
+        if env:
+            default_env.update(env)
+        req = self._make_request(path, headers=headers, environ=default_env)
+        req.acl = acl
+        result = self.test_auth.authorize(req)
+        if exception:
+            self.assertTrue(isinstance(result, exception))
+        else:
+            self.assertTrue(result is None)
+        return req
+
+    def test_authorize_fails_for_unauthorized_user(self):
+        self._check_authenticate(exception=webob.exc.HTTPForbidden)
+
+    def test_authorize_fails_for_invalid_reseller_prefix(self):
+        self._check_authenticate(account='BLAN_a',
+                                 exception=webob.exc.HTTPForbidden)
+
+    def test_authorize_succeeds_for_reseller_admin(self):
+        roles = [self.test_auth.reseller_admin_role]
+        identity = self._get_identity(roles=roles)
+        req = self._check_authenticate(identity=identity)
+        self.assertTrue(req.environ.get('swift_owner'))
+
+    def test_authorize_succeeds_as_owner_for_operator_role(self):
+        roles = self.test_auth.operator_roles.split(',')[0]
+        identity = self._get_identity(roles=roles)
+        req = self._check_authenticate(identity=identity)
+        self.assertTrue(req.environ.get('swift_owner'))
+
+    def _check_authorize_for_tenant_owner_match(self, exception=None):
+        identity = self._get_identity()
+        identity['user'] = identity['tenant'][1]
+        req = self._check_authenticate(identity=identity, exception=exception)
+        expected = bool(exception is None)
+        self.assertEqual(bool(req.environ.get('swift_owner')), expected)
+
+    def test_authorize_succeeds_as_owner_for_tenant_owner_match(self):
+        self.test_auth.is_admin = True
+        self._check_authorize_for_tenant_owner_match()
+
+    def test_authorize_fails_as_owner_for_tenant_owner_match(self):
+        self.test_auth.is_admin = False
+        self._check_authorize_for_tenant_owner_match(
+            exception=webob.exc.HTTPForbidden)
+
+    def test_authorize_succeeds_for_container_sync(self):
+        env = {'swift_sync_key': 'foo', 'REMOTE_ADDR': '127.0.0.1'}
+        headers = {'x-container-sync-key': 'foo', 'x-timestamp': None}
+        self._check_authenticate(env=env, headers=headers)
+
+    def test_authorize_fails_for_invalid_referrer(self):
+        env = {'HTTP_REFERER': 'http://invalid.com/index.html'}
+        self._check_authenticate(acl='.r:example.com', env=env,
+                                 exception=webob.exc.HTTPForbidden)
+
+    def test_authorize_fails_for_referrer_without_rlistings(self):
+        env = {'HTTP_REFERER': 'http://example.com/index.html'}
+        self._check_authenticate(acl='.r:example.com', env=env,
+                                 exception=webob.exc.HTTPForbidden)
+
+    def test_authorize_succeeds_for_referrer_with_rlistings(self):
+        env = {'HTTP_REFERER': 'http://example.com/index.html'}
+        self._check_authenticate(acl='.r:example.com,.rlistings', env=env)
+
+    def test_authorize_succeeds_for_referrer_with_obj(self):
+        path = '/v1/%s/c/o' % self._get_account()
+        env = {'HTTP_REFERER': 'http://example.com/index.html'}
+        self._check_authenticate(acl='.r:example.com', env=env, path=path)
+
+    def test_authorize_succeeds_for_user_role_in_roles(self):
+        acl = 'allowme'
+        identity = self._get_identity(roles=[acl])
+        self._check_authenticate(identity=identity, acl=acl)
+
+    def test_authorize_succeeds_for_tenant_name_user_in_roles(self):
+        identity = self._get_identity()
+        acl = '%s:%s' % (identity['tenant'][1], identity['user'])
+        self._check_authenticate(identity=identity, acl=acl)
+
+    def test_authorize_succeeds_for_tenant_id_user_in_roles(self):
+        identity = self._get_identity()
+        acl = '%s:%s' % (identity['tenant'][0], identity['user'])
+        self._check_authenticate(identity=identity, acl=acl)
+
+if __name__ == '__main__':
+    unittest.main()