Authenticate via oauth

Add support to authenticate with keystone via oauth access tokens.

Change-Id: Ie0eb3290d71661852cc7774bcdb1eb56971987be
implements: bp add-oauth-support
This commit is contained in:
Steve Martinelli
2014-03-04 13:24:48 -06:00
parent 15bec1cde3
commit 855ec80476
2 changed files with 129 additions and 0 deletions

View File

@@ -14,13 +14,17 @@
import uuid import uuid
import httpretty import httpretty
import mock
import six import six
from testtools import matchers from testtools import matchers
from keystoneclient.openstack.common import jsonutils from keystoneclient.openstack.common import jsonutils
from keystoneclient.openstack.common import timeutils from keystoneclient.openstack.common import timeutils
from keystoneclient import session
from keystoneclient.tests.v3 import client_fixtures
from keystoneclient.tests.v3 import utils from keystoneclient.tests.v3 import utils
from keystoneclient.v3.contrib.oauth1 import access_tokens from keystoneclient.v3.contrib.oauth1 import access_tokens
from keystoneclient.v3.contrib.oauth1 import auth
from keystoneclient.v3.contrib.oauth1 import consumers from keystoneclient.v3.contrib.oauth1 import consumers
from keystoneclient.v3.contrib.oauth1 import request_tokens from keystoneclient.v3.contrib.oauth1 import request_tokens
@@ -227,3 +231,70 @@ class AccessTokenTests(TokenTests):
timestamp=expires_at) timestamp=expires_at)
self._validate_oauth_headers(req_headers['Authorization'], self._validate_oauth_headers(req_headers['Authorization'],
oauth_client) oauth_client)
class AuthenticateWithOAuthTests(TokenTests):
def setUp(self):
super(AuthenticateWithOAuthTests, self).setUp()
if oauth1 is None:
self.skipTest('optional package oauthlib is not installed')
@httpretty.activate
def test_oauth_authenticate_success(self):
consumer_key = uuid.uuid4().hex
consumer_secret = uuid.uuid4().hex
access_key = uuid.uuid4().hex
access_secret = uuid.uuid4().hex
# Just use an existing project scoped token and change
# the methods to oauth1, and add an OS-OAUTH1 section.
oauth_token = client_fixtures.project_scoped_token()
oauth_token['methods'] = ["oauth1"]
oauth_token['OS-OAUTH1'] = {"consumer_id": consumer_key,
"access_token_id": access_key}
self.stub_auth(json=oauth_token)
a = auth.OAuth(self.TEST_URL, consumer_key=consumer_key,
consumer_secret=consumer_secret,
access_key=access_key,
access_secret=access_secret)
s = session.Session(auth=a)
t = s.get_token()
self.assertEqual(t, self.TEST_TOKEN)
OAUTH_REQUEST_BODY = {
"auth": {
"identity": {
"methods": ["oauth1"],
"oauth1": {}
}
}
}
self.assertRequestBodyIs(json=OAUTH_REQUEST_BODY)
# Assert that the headers have the same oauthlib data
req_headers = httpretty.last_request().headers
oauth_client = oauth1.Client(consumer_key,
client_secret=consumer_secret,
resource_owner_key=access_key,
resource_owner_secret=access_secret,
signature_method=oauth1.SIGNATURE_HMAC)
self._validate_oauth_headers(req_headers['Authorization'],
oauth_client)
class TestOAuthLibModule(utils.TestCase):
def setUp(self):
super(TestOAuthLibModule, self).setUp()
def test_no_oauthlib_installed(self):
with mock.patch.object(auth, 'oauth1', None):
self.assertRaises(NotImplementedError,
auth.OAuth,
self.TEST_URL,
consumer_key=uuid.uuid4().hex,
consumer_secret=uuid.uuid4().hex,
access_key=uuid.uuid4().hex,
access_secret=uuid.uuid4().hex)

View File

@@ -0,0 +1,58 @@
# 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.
from keystoneclient.auth.identity import v3
try:
from oauthlib import oauth1
except ImportError:
oauth1 = None
class OAuthMethod(v3.AuthMethod):
_method_parameters = ['consumer_key', 'consumer_secret',
'access_key', 'access_secret']
def __init__(self, **kwargs):
"""Construct an OAuth based authentication method.
:param string consumer_key: Consumer key.
:param string consumer_secret: Consumer secret.
:param string access_key: Access token key.
:param string access_secret: Access token secret.
"""
super(OAuthMethod, self).__init__(**kwargs)
if oauth1 is None:
raise NotImplementedError('optional package oauthlib'
' is not installed')
def get_auth_data(self, session, auth, headers, **kwargs):
# Add the oauth specific content into the headers
oauth_client = oauth1.Client(self.consumer_key,
client_secret=self.consumer_secret,
resource_owner_key=self.access_key,
resource_owner_secret=self.access_secret,
signature_method=oauth1.SIGNATURE_HMAC)
o_url, o_headers, o_body = oauth_client.sign(auth.token_url,
http_method='POST')
headers.update(o_headers)
return 'oauth1', {}
class OAuth(v3._AuthConstructor):
_auth_method_class = OAuthMethod
def __init__(self, auth_url, **kwargs):
super(OAuth, self).__init__(auth_url, **kwargs)