diff --git a/bin/swift b/bin/swift
index b958f321..7cfbf161 100755
--- a/bin/swift
+++ b/bin/swift
@@ -38,9 +38,9 @@ def get_conn(options):
     return Connection(options.auth,
                       options.user,
                       options.key,
-                      snet=options.snet,
-                      tenant_name=options.os_tenant_name,
-                      auth_version=options.auth_version)
+                      auth_version=options.auth_version,
+                      os_options=options.os_options,
+                      snet=options.snet)
 
 
 def mkdirs(path):
@@ -991,13 +991,6 @@ def parse_args(parser, args, enforce_requires=True):
         # Use 2.0 auth if none of the old args are present
         options.auth_version = '2.0'
 
-    if options.auth_version in ('2.0', '2') and not \
-            options.os_tenant_name and options.user and \
-            ':' in options.user:
-        (options.os_tenant_name,
-         options.os_username) = options.user.split(':')
-        options.user = options.os_username
-
     # Use new-style args if old ones not present
     if not options.auth and options.os_auth_url:
         options.auth = options.os_auth_url
@@ -1006,6 +999,15 @@ def parse_args(parser, args, enforce_requires=True):
     if not options.key and options.os_password:
         options.key = options.os_password
 
+    # Specific OpenStack options
+    options.os_options = {
+        'tenant_id': options.os_tenant_id,
+        'tenant_name': options.os_tenant_name,
+        'service_type': options.os_service_type,
+        'auth_token': options.os_auth_token,
+        'object_storage_url': options.os_storage_url,
+    }
+
     # Handle trailing '/' in URL
     if options.auth and not options.auth.endswith('/'):
         options.auth += '/'
@@ -1017,8 +1019,8 @@ Auth version 1.0 requires ST_AUTH, ST_USER, and ST_KEY environment variables
 to be set or overridden with -A, -U, or -K.
 
 Auth version 2.0 requires OS_AUTH_URL, OS_USERNAME, OS_PASSWORD, and
-OS_TENANT_NAME to be set or overridden with --os_auth_url, --os_username,
---os_password, or --os_tenant_name.'''.strip('\n'))
+OS_TENANT_NAME OS_TENANT_ID to be set or overridden with --os-auth_url,
+--os_username, --os_password, --os_tenant_name or os_tenant_id.'''.strip('\n'))
     return options, args
 
 
@@ -1051,26 +1053,43 @@ Example:
                       default=environ.get('ST_AUTH_VERSION', '1.0'),
                       type=str,
                       help='Specify a version for authentication'\
-                          '(default: 1.0)')
+                           '(default: 1.0)')
     parser.add_option('-U', '--user', dest='user',
                       default=environ.get('ST_USER'),
                       help='User name for obtaining an auth token')
     parser.add_option('-K', '--key', dest='key',
                       default=environ.get('ST_KEY'),
                       help='Key for obtaining an auth token')
-    parser.add_option('--os_auth_url', dest='os_auth_url',
-                      default=environ.get('OS_AUTH_URL'),
-                      help='Openstack auth URL. Defaults to env[OS_AUTH_URL].')
     parser.add_option('--os_username', dest='os_username',
                       default=environ.get('OS_USERNAME'),
                       help='Openstack username. Defaults to env[OS_USERNAME].')
+    parser.add_option('--os_password', dest='os_password',
+                      default=environ.get('OS_PASSWORD'),
+                      help='Openstack password. Defaults to env[OS_PASSWORD].')
+    parser.add_option('--os_tenant_id',
+                      default=environ.get('OS_TENANT_ID'),
+                      help='OpenStack tenant ID.' \
+                           'Defaults to env[OS_TENANT_ID]')
     parser.add_option('--os_tenant_name', dest='os_tenant_name',
                       default=environ.get('OS_TENANT_NAME'),
                       help='Openstack tenant name.' \
                            'Defaults to env[OS_TENANT_NAME].')
-    parser.add_option('--os_password', dest='os_password',
-                      default=environ.get('OS_PASSWORD'),
-                      help='Openstack password. Defaults to env[OS_PASSWORD].')
+    parser.add_option('--os_auth_url', dest='os_auth_url',
+                      default=environ.get('OS_AUTH_URL'),
+                      help='Openstack auth URL. Defaults to env[OS_AUTH_URL].')
+    parser.add_option('--os_auth_token', dest='os_auth_token',
+                      default=environ.get('OS_AUTH_TOKEN'),
+                      help='Openstack token. Defaults to env[OS_AUTH_TOKEN]')
+    parser.add_option('--os_storage_url',
+                      dest='os_storage_url',
+                      default=environ.get('OS_STORAGE_URL'),
+                      help='Openstack storage URL.' \
+                           'Defaults to env[OS_STORAGE_URL]')
+    parser.add_option('--os_service_type',
+                      dest='os_service_type',
+                      default=environ.get('OS_SERVICE_TYPE'),
+                      help='Openstack Service type.' \
+                           'Defaults to env[OS_SERVICE_TYPE]')
     parser.disable_interspersed_args()
     (options, args) = parse_args(parser, argv[1:], enforce_requires=False)
     parser.enable_interspersed_args()
diff --git a/swiftclient/client.py b/swiftclient/client.py
index 79e6594f..8d7fd03e 100644
--- a/swiftclient/client.py
+++ b/swiftclient/client.py
@@ -20,10 +20,9 @@ Cloud Files client library used internally
 import socket
 import os
 import logging
-import httplib
 
 from urllib import quote as _quote
-from urlparse import urlparse, urlunparse, urljoin
+from urlparse import urlparse, urlunparse
 
 try:
     from eventlet.green.httplib import HTTPException, HTTPSConnection
@@ -202,7 +201,7 @@ def json_request(method, url, **kwargs):
     return resp, body
 
 
-def _get_auth_v1_0(url, user, key, snet):
+def get_auth_1_0(url, user, key, snet):
     parsed, conn = http_connection(url)
     method = 'GET'
     conn.request(method, parsed.path, '',
@@ -230,36 +229,26 @@ def _get_auth_v1_0(url, user, key, snet):
                                resp.getheader('x-auth-token'))
 
 
-def _get_auth_v2_0(url, user, tenant_name, key, snet):
-    body = {'auth':
-            {'passwordCredentials': {'password': key, 'username': user},
-             'tenantName': tenant_name}}
-    token_url = urljoin(url, "tokens")
-    resp, body = json_request("POST", token_url, body=body)
-    token_id = None
-    try:
-        url = None
-        catalogs = body['access']['serviceCatalog']
-        for service in catalogs:
-            if service['type'] == 'object-store':
-                url = service['endpoints'][0]['publicURL']
-        token_id = body['access']['token']['id']
-        if not url:
-            raise ClientException("There is no object-store endpoint "
-                                  "on this auth server.")
-    except(KeyError, IndexError):
-        raise ClientException("Error while getting answers from auth server")
+def get_keystoneclient_2_0(auth_url, user, key, os_options):
+    """
+    Authenticate against a auth 2.0 server.
 
-    if snet:
-        parsed = list(urlparse(url))
-        # Second item in the list is the netloc
-        parsed[1] = 'snet-' + parsed[1]
-        url = urlunparse(parsed)
-
-    return url, token_id
+    We are using the keystoneclient library for our 2.0 authentication.
+    """
+    from keystoneclient.v2_0 import client as ksclient
+    _ksclient = ksclient.Client(username=user,
+                                password=key,
+                                tenant_name=os_options.get('tenant_name'),
+                                tenant_id=os_options.get('tenant_id'),
+                                auth_url=auth_url)
+    service_type = os_options.get('service_type') or 'object-store'
+    endpoint = _ksclient.service_catalog.url_for(
+        service_type=service_type,
+        endpoint_type='publicURL')
+    return (endpoint, _ksclient.auth_token)
 
 
-def get_auth(url, user, key, snet=False, tenant_name=None, auth_version="1.0"):
+def get_auth(auth_url, user, key, **kwargs):
     """
     Get authentication/authorization credentials.
 
@@ -268,28 +257,45 @@ def get_auth(url, user, key, snet=False, tenant_name=None, auth_version="1.0"):
     of the host name for the returned storage URL. With Rackspace Cloud Files,
     use of this network path causes no bandwidth charges but requires the
     client to be running on Rackspace's ServiceNet network.
-
-    :param url: authentication/authorization URL
-    :param user: user to authenticate as
-    :param key: key or password for authorization
-    :param snet: use SERVICENET internal network (see above), default is False
-    :param auth_version: OpenStack auth version, default is 1.0
-    :param tenant_name: The tenant/account name, required when connecting
-                        to a auth 2.0 system.
-    :returns: tuple of (storage URL, auth token)
-    :raises: ClientException: HTTP GET request to auth URL failed
     """
-    if auth_version in ["1.0", "1"]:
-        return _get_auth_v1_0(url, user, key, snet)
-    elif auth_version in ["2.0", "2"]:
-        if not tenant_name and ':' in user:
-            (tenant_name, user) = user.split(':')
-        if not tenant_name:
+    auth_version = kwargs.get('auth_version', '1')
+
+    if auth_version in ['1.0', '1', 1]:
+        return get_auth_1_0(auth_url,
+                            user,
+                            key,
+                            kwargs.get('snet'))
+
+    if auth_version in ['2.0', '2', 2]:
+
+        # We are allowing to specify a token/storage-url to re-use
+        # without having to re-authenticate.
+        if (kwargs['os_options'].get('object_storage_url') and
+                kwargs['os_options'].get('auth_token')):
+            return(kwargs['os_options'].get('object_storage_url'),
+                   kwargs['os_options'].get('auth_token'))
+
+        # We are handling a special use case here when we were
+        # allowing specifying the account/tenant_name with the -U
+        # argument
+        if not kwargs.get('tenant_name') and ':' in user:
+            (kwargs['os_options']['tenant_name'],
+             user) = user.split(':')
+
+        # We are allowing to have an tenant_name argument in get_auth
+        # directly without having os_options
+        if kwargs.get('tenant_name'):
+            kwargs['os_options']['tenant_name'] = kwargs['tenant_name']
+
+        if (not 'tenant_name' in kwargs['os_options']):
             raise ClientException('No tenant specified')
-        return _get_auth_v2_0(url, user, tenant_name, key, snet)
-    else:
-        raise ClientException('Unknown auth_version %s specified.'
-                              % auth_version)
+
+        (auth_url, token) = get_keystoneclient_2_0(auth_url, user,
+                                                   key, kwargs['os_options'])
+        return (auth_url, token)
+
+    raise ClientException('Unknown auth_version %s specified.'
+                          % auth_version)
 
 
 def get_account(url, token, marker=None, limit=None, prefix=None,
@@ -898,8 +904,7 @@ class Connection(object):
 
     def __init__(self, authurl, user, key, retries=5, preauthurl=None,
                  preauthtoken=None, snet=False, starting_backoff=1,
-                 tenant_name=None,
-                 auth_version="1"):
+                 tenant_name=None, os_options={}, auth_version="1"):
         """
         :param authurl: authentication URL
         :param user: user name to authenticate as
@@ -912,6 +917,9 @@ class Connection(object):
         :param auth_version: OpenStack auth version, default is 1.0
         :param tenant_name: The tenant/account name, required when connecting
                             to a auth 2.0 system.
+        :param os_options: The OpenStack options which can have tenant_id,
+                           auth_token, service_type, tenant_name,
+                           object_storage_url
         """
         self.authurl = authurl
         self.user = user
@@ -924,13 +932,17 @@ class Connection(object):
         self.snet = snet
         self.starting_backoff = starting_backoff
         self.auth_version = auth_version
-        self.tenant_name = tenant_name
+        if tenant_name:
+            os_options['tenant_name'] = tenant_name
+        self.os_options = os_options
 
     def get_auth(self):
-        return get_auth(self.authurl, self.user,
-                        self.key, snet=self.snet,
-                        tenant_name=self.tenant_name,
-                        auth_version=self.auth_version)
+        return get_auth(self.authurl,
+                        self.user,
+                        self.key,
+                        snet=self.snet,
+                        auth_version=self.auth_version,
+                        os_options=self.os_options)
 
     def http_connection(self):
         return http_connection(self.url)
diff --git a/tests/test_swiftclient.py b/tests/test_swiftclient.py
index b165dee3..29233e04 100644
--- a/tests/test_swiftclient.py
+++ b/tests/test_swiftclient.py
@@ -19,7 +19,7 @@ import unittest
 from urlparse import urlparse
 
 # TODO: mock http connection class with more control over headers
-from utils import fake_http_connect
+from utils import fake_http_connect, fake_get_keystoneclient_2_0
 
 from swiftclient import client as c
 
@@ -175,42 +175,33 @@ class TestGetAuth(MockHttpTest):
         self.assertEquals(token, None)
 
     def test_auth_v2(self):
-        def read(*args, **kwargs):
-            acct_url = 'http://127.0.01/AUTH_FOO'
-            body = {'access': {'serviceCatalog':
-                                   [{u'endpoints': [{'publicURL': acct_url}],
-                                     'type': 'object-store'}],
-                               'token': {'id': 'XXXXXXX'}}}
-            return c.json_dumps(body)
-        c.http_connection = self.fake_http_connection(200, return_read=read)
+        c.get_keystoneclient_2_0 = fake_get_keystoneclient_2_0
         url, token = c.get_auth('http://www.test.com', 'asdf', 'asdf',
-                                tenant_name='asdf', auth_version="2.0")
+                                os_options={'tenant_name': 'asdf'},
+                                auth_version="2.0")
         self.assertTrue(url.startswith("http"))
         self.assertTrue(token)
 
     def test_auth_v2_no_tenant_name(self):
-        def read(*args, **kwargs):
-            acct_url = 'http://127.0.01/AUTH_FOO'
-            body = {'access': {'serviceCatalog':
-                                   [{u'endpoints': [{'publicURL': acct_url}],
-                                     'type': 'object-store'}],
-                               'token': {'id': 'XXXXXXX'}}}
-            return c.json_dumps(body)
-        c.http_connection = self.fake_http_connection(200, return_read=read)
+        c.get_keystoneclient_2_0 = fake_get_keystoneclient_2_0
         self.assertRaises(c.ClientException, c.get_auth,
                           'http://www.tests.com', 'asdf', 'asdf',
+                          os_options={},
                           auth_version='2.0')
 
     def test_auth_v2_with_tenant_user_in_user(self):
-        def read(*args, **kwargs):
-            acct_url = 'http://127.0.01/AUTH_FOO'
-            body = {'access': {'serviceCatalog':
-                                   [{u'endpoints': [{'publicURL': acct_url}],
-                                     'type': 'object-store'}],
-                               'token': {'id': 'XXXXXXX'}}}
-            return c.json_dumps(body)
-        c.http_connection = self.fake_http_connection(200, return_read=read)
+        c.get_keystoneclient_2_0 = fake_get_keystoneclient_2_0
         url, token = c.get_auth('http://www.test.com', 'foo:bar', 'asdf',
+                                os_options={},
+                                auth_version="2.0")
+        self.assertTrue(url.startswith("http"))
+        self.assertTrue(token)
+
+    def test_auth_v2_tenant_name_no_os_options(self):
+        c.get_keystoneclient_2_0 = fake_get_keystoneclient_2_0
+        url, token = c.get_auth('http://www.test.com', 'asdf', 'asdf',
+                                tenant_name='asdf',
+                                os_options={},
                                 auth_version="2.0")
         self.assertTrue(url.startswith("http"))
         self.assertTrue(token)
diff --git a/tests/utils.py b/tests/utils.py
index 6a53cbc0..95f63359 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -17,6 +17,14 @@ from httplib import HTTPException
 from eventlet import Timeout, sleep
 
 
+def fake_get_keystoneclient_2_0(auth_url,
+                                username,
+                                tenant_name,
+                                password,
+                                service_type='object-store'):
+    return ("http://url/", "token")
+
+
 def fake_http_connect(*code_iter, **kwargs):
 
     class FakeConn(object):
diff --git a/tools/pip-requires b/tools/pip-requires
index 322630ee..cda31213 100644
--- a/tools/pip-requires
+++ b/tools/pip-requires
@@ -1 +1,2 @@
 simplejson
+python-keystoneclient