summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Huin <mhu@enovance.com>2013-12-02 10:43:10 +0100
committerDolph Mathews <dolph.mathews@gmail.com>2014-01-16 13:31:04 -0600
commitbed88a2e724f5f23a1c839b7872b1bc56f059df5 (patch)
treee689cdd8e1dc18bc0cbe4f90dd81c6053c1cda9d
parente54a6a353c63edd389400e6f8181d165f8fe29ea (diff)
downloadkeystone-bed88a2e724f5f23a1c839b7872b1bc56f059df5.tar.gz
Replacing python-oauth2 by oauthlib
This patch replaces the old, unmaintained python-oauth2 library by the better suited oauthlib in keystone oAuth modules. The library switch comes with two notable changes in terms of use: * the client must set the callback uri to 'oob' (out-of-band) explicitly when requesting a Request Token * the requested_project_id header is not included in the signature anymore, in compliance with the oAuth1 spec. Closes-Bug: 1240382 Change-Id: Ie553830cc80075aa818e719604e6bc4c754d2ae3
-rw-r--r--keystone/auth/plugins/oauth1.py34
-rw-r--r--keystone/contrib/oauth1/backends/sql.py20
-rw-r--r--keystone/contrib/oauth1/controllers.py60
-rw-r--r--keystone/contrib/oauth1/core.py49
-rw-r--r--keystone/contrib/oauth1/validator.py184
-rw-r--r--keystone/tests/test_v3_oauth1.py125
-rw-r--r--requirements.txt2
7 files changed, 325 insertions, 149 deletions
diff --git a/keystone/auth/plugins/oauth1.py b/keystone/auth/plugins/oauth1.py
index 5ccc33527..91863453c 100644
--- a/keystone/auth/plugins/oauth1.py
+++ b/keystone/auth/plugins/oauth1.py
@@ -18,6 +18,7 @@ from keystone import auth
from keystone.common import dependency
from keystone.contrib import oauth1
from keystone.contrib.oauth1 import core as oauth
+from keystone.contrib.oauth1 import validator
from keystone import exception
from keystone.openstack.common import log
from keystone.openstack.common import timeutils
@@ -36,7 +37,6 @@ class OAuth(auth.AuthMethodHandler):
"""Turn a signed request with an access key into a keystone token."""
headers = context['headers']
oauth_headers = oauth.get_oauth_headers(headers)
- consumer_id = oauth_headers.get('oauth_consumer_key')
access_token_id = oauth_headers.get('oauth_token')
if not access_token_id:
@@ -44,7 +44,6 @@ class OAuth(auth.AuthMethodHandler):
attribute='oauth_token', target='request')
acc_token = self.oauth_api.get_access_token(access_token_id)
- consumer = self.oauth_api.get_consumer_with_secret(consumer_id)
expires_at = acc_token['expires_at']
if expires_at:
@@ -54,27 +53,20 @@ class OAuth(auth.AuthMethodHandler):
if now > expires:
raise exception.Unauthorized(_('Access token is expired'))
- consumer_obj = oauth1.Consumer(key=consumer['id'],
- secret=consumer['secret'])
- acc_token_obj = oauth1.Token(key=acc_token['id'],
- secret=acc_token['access_secret'])
-
url = oauth.rebuild_url(context['path'])
- oauth_request = oauth1.Request.from_request(
+ access_verifier = oauth.ResourceEndpoint(
+ request_validator=validator.OAuthValidator(),
+ token_generator=oauth.token_generator)
+ result, request = access_verifier.validate_protected_resource_request(
+ url,
http_method='POST',
- http_url=url,
- headers=context['headers'],
- query_string=context['query_string'])
- oauth_server = oauth1.Server()
- oauth_server.add_signature_method(oauth1.SignatureMethod_HMAC_SHA1())
- params = oauth_server.verify_request(oauth_request,
- consumer_obj,
- token=acc_token_obj)
-
- if params:
- msg = _('There should not be any non-oauth parameters')
- raise exception.Unauthorized(message=msg)
-
+ body=context['query_string'],
+ headers=headers,
+ realms=None
+ )
+ if not result:
+ msg = _('Could not validate the access token')
+ raise exception.Unauthorized(msg)
auth_context['user_id'] = acc_token['authorizing_user_id']
auth_context['access_token_id'] = access_token_id
auth_context['project_id'] = acc_token['project_id']
diff --git a/keystone/contrib/oauth1/backends/sql.py b/keystone/contrib/oauth1/backends/sql.py
index e840e4e1e..cde5c087f 100644
--- a/keystone/contrib/oauth1/backends/sql.py
+++ b/keystone/contrib/oauth1/backends/sql.py
@@ -162,7 +162,12 @@ class OAuth1(sql.Base):
consumer_ref.extra = new_consumer.extra
return core.filter_consumer(consumer_ref.to_dict())
- def create_request_token(self, consumer_id, project_id, token_duration):
+ def create_request_token(self, consumer_id, project_id, token_duration,
+ request_token_id=None, request_token_secret=None):
+ if request_token_id is None:
+ request_token_id = uuid.uuid4().hex
+ if request_token_secret is None:
+ request_token_secret = uuid.uuid4().hex
expiry_date = None
if token_duration:
now = timeutils.utcnow()
@@ -170,9 +175,8 @@ class OAuth1(sql.Base):
expiry_date = timeutils.isotime(future, subsecond=True)
ref = {}
- request_token_id = uuid.uuid4().hex
ref['id'] = request_token_id
- ref['request_secret'] = uuid.uuid4().hex
+ ref['request_secret'] = request_token_secret
ref['verifier'] = None
ref['authorizing_user_id'] = None
ref['requested_project_id'] = project_id
@@ -214,7 +218,12 @@ class OAuth1(sql.Base):
return token_ref.to_dict()
- def create_access_token(self, request_token_id, token_duration):
+ def create_access_token(self, request_token_id, token_duration,
+ access_token_id=None, access_token_secret=None):
+ if access_token_id is None:
+ access_token_id = uuid.uuid4().hex
+ if access_token_secret is None:
+ access_token_secret = uuid.uuid4().hex
session = self.get_session()
with session.begin():
req_token_ref = self._get_request_token(session, request_token_id)
@@ -228,9 +237,8 @@ class OAuth1(sql.Base):
# add Access Token
ref = {}
- access_token_id = uuid.uuid4().hex
ref['id'] = access_token_id
- ref['access_secret'] = uuid.uuid4().hex
+ ref['access_secret'] = access_token_secret
ref['authorizing_user_id'] = token_dict['authorizing_user_id']
ref['project_id'] = token_dict['requested_project_id']
ref['role_ids'] = token_dict['role_ids']
diff --git a/keystone/contrib/oauth1/controllers.py b/keystone/contrib/oauth1/controllers.py
index c3bd21db4..85cfec8b3 100644
--- a/keystone/contrib/oauth1/controllers.py
+++ b/keystone/contrib/oauth1/controllers.py
@@ -21,6 +21,7 @@ from keystone.common import dependency
from keystone.common import wsgi
from keystone import config
from keystone.contrib.oauth1 import core as oauth1
+from keystone.contrib.oauth1 import validator
from keystone import exception
from keystone.openstack.common import jsonutils
from keystone.openstack.common import timeutils
@@ -176,26 +177,21 @@ class OAuthControllerV3(controller.V3Controller):
raise exception.ValidationError(
attribute='requested_project_id', target='request')
- consumer_ref = self.oauth_api.get_consumer_with_secret(consumer_id)
- consumer = oauth1.Consumer(key=consumer_ref['id'],
- secret=consumer_ref['secret'])
-
url = oauth1.rebuild_url(context['path'])
- oauth_request = oauth1.Request.from_request(
+
+ req_headers = {'Requested-Project-Id': requested_project_id}
+ req_headers.update(headers)
+ request_verifier = oauth1.RequestTokenEndpoint(
+ request_validator=validator.OAuthValidator(),
+ token_generator=oauth1.token_generator)
+ h, b, s = request_verifier.create_request_token_response(
+ url,
http_method='POST',
- http_url=url,
- headers=context['headers'],
- query_string=context['query_string'],
- parameters={'requested_project_id': requested_project_id})
- oauth_server = oauth1.Server()
- oauth_server.add_signature_method(oauth1.SignatureMethod_HMAC_SHA1())
- params = oauth_server.verify_request(oauth_request,
- consumer,
- token=None)
-
- project_params = params['requested_project_id']
- if project_params != requested_project_id:
- msg = _('Non-oauth parameter - project, do not match')
+ body=context['query_string'],
+ headers=req_headers)
+
+ if (not b) or int(s) > 399:
+ msg = _('Invalid signature')
raise exception.Unauthorized(message=msg)
request_token_duration = CONF.oauth1.request_token_duration
@@ -235,7 +231,6 @@ class OAuthControllerV3(controller.V3Controller):
raise exception.ValidationError(
attribute='oauth_verifier', target='request')
- consumer = self.oauth_api.get_consumer_with_secret(consumer_id)
req_token = self.oauth_api.get_request_token(
request_token_id)
@@ -247,25 +242,18 @@ class OAuthControllerV3(controller.V3Controller):
if now > expires:
raise exception.Unauthorized(_('Request token is expired'))
- consumer_obj = oauth1.Consumer(key=consumer['id'],
- secret=consumer['secret'])
- req_token_obj = oauth1.Token(key=req_token['id'],
- secret=req_token['request_secret'])
- req_token_obj.set_verifier(oauth_verifier)
-
url = oauth1.rebuild_url(context['path'])
- oauth_request = oauth1.Request.from_request(
+
+ access_verifier = oauth1.AccessTokenEndpoint(
+ request_validator=validator.OAuthValidator(),
+ token_generator=oauth1.token_generator)
+ h, b, s = access_verifier.create_access_token_response(
+ url,
http_method='POST',
- http_url=url,
- headers=context['headers'],
- query_string=context['query_string'])
- oauth_server = oauth1.Server()
- oauth_server.add_signature_method(oauth1.SignatureMethod_HMAC_SHA1())
- params = oauth_server.verify_request(oauth_request,
- consumer_obj,
- token=req_token_obj)
-
- if params:
+ body=context['query_string'],
+ headers=headers)
+ params = oauth1.extract_non_oauth_params(b)
+ if len(params) != 0:
msg = _('There should not be any non-oauth parameters')
raise exception.Unauthorized(message=msg)
diff --git a/keystone/contrib/oauth1/core.py b/keystone/contrib/oauth1/core.py
index 857a4ad84..d88a82812 100644
--- a/keystone/contrib/oauth1/core.py
+++ b/keystone/contrib/oauth1/core.py
@@ -20,8 +20,10 @@ from __future__ import absolute_import
import abc
-import oauth2 as oauth
+import oauthlib.common
+from oauthlib import oauth1
import six
+import uuid
from keystone.common import dependency
from keystone.common import extension
@@ -30,19 +32,33 @@ from keystone import config
from keystone import exception
-Consumer = oauth.Consumer
-Request = oauth.Request
-Server = oauth.Server
-SignatureMethod = oauth.SignatureMethod
-SignatureMethod_HMAC_SHA1 = oauth.SignatureMethod_HMAC_SHA1
-SignatureMethod_PLAINTEXT = oauth.SignatureMethod_PLAINTEXT
-Token = oauth.Token
-Client = oauth.Client
+RequestValidator = oauth1.RequestValidator
+Client = oauth1.Client
+AccessTokenEndpoint = oauth1.AccessTokenEndpoint
+ResourceEndpoint = oauth1.ResourceEndpoint
+AuthorizationEndpoint = oauth1.AuthorizationEndpoint
+SIG_HMAC = oauth1.SIGNATURE_HMAC
+RequestTokenEndpoint = oauth1.RequestTokenEndpoint
+oRequest = oauthlib.common.Request
+
+
+class Token(object):
+ def __init__(self, key, secret):
+ self.key = key
+ self.secret = secret
+ self.verifier = None
+
+ def set_verifier(self, verifier):
+ self.verifier = verifier
CONF = config.CONF
+def token_generator(*args, **kwargs):
+ return uuid.uuid4().hex
+
+
EXTENSION_DATA = {
'name': 'OpenStack OAUTH1 API',
'namespace': 'http://docs.openstack.org/identity/api/ext/'
@@ -116,13 +132,14 @@ def get_oauth_headers(headers):
# to split the rest of the headers.
auth_header = headers['Authorization']
- # Check that the authorization header is OAuth.
- if auth_header[:6] == 'OAuth ':
- auth_header = auth_header[6:]
- # Get the parameters from the header.
- header_params = oauth.Request._split_header(auth_header)
- parameters.update(header_params)
- return parameters
+ params = oauth1.rfc5849.utils.parse_authorization_header(auth_header)
+ parameters.update(dict(params))
+ return parameters
+
+
+def extract_non_oauth_params(query_string):
+ params = oauthlib.common.extract_params(query_string)
+ return dict([(k, v) for k, v in params if not k.startswith('oauth_')])
@dependency.provider('oauth_api')
diff --git a/keystone/contrib/oauth1/validator.py b/keystone/contrib/oauth1/validator.py
new file mode 100644
index 000000000..37a5ef018
--- /dev/null
+++ b/keystone/contrib/oauth1/validator.py
@@ -0,0 +1,184 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2014 OpenStack Foundation
+#
+# 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.
+
+"""oAuthlib request validator."""
+
+from keystone.common import dependency
+from keystone.contrib.oauth1 import core as oauth1
+from keystone import exception
+from keystone.openstack.common import log
+
+
+METHOD_NAME = 'oauth_validator'
+LOG = log.getLogger(__name__)
+
+
+@dependency.requires('oauth_api')
+class OAuthValidator(oauth1.RequestValidator):
+
+ def __init__(self):
+ self.oauth_api = oauth1.Manager()
+
+ #TODO(mhu) set as option probably ?
+ @property
+ def enforce_ssl(self):
+ return False
+
+ @property
+ def safe_characters(self):
+ #oauth tokens are generated from a uuid hex value
+ return set("abcdef0123456789")
+
+ def _check_token(self, token):
+ # generic token verification when they're obtained from a uuid hex
+ return (set(token) <= self.safe_characters and
+ len(token) == 32)
+
+ def check_client_key(self, client_key):
+ return self._check_token(client_key)
+
+ def check_request_token(self, request_token):
+ return self._check_token(request_token)
+
+ def check_access_token(self, access_token):
+ return self._check_token(access_token)
+
+ def check_nonce(self, nonce):
+ # Assuming length is not a concern
+ return set(nonce) <= self.safe_characters
+
+ def check_verifier(self, verifier):
+ try:
+ return 1000 <= int(verifier) <= 9999
+ except ValueError:
+ return False
+
+ def get_client_secret(self, client_key, request):
+ client = self.oauth_api.get_consumer_with_secret(client_key)
+ return client['secret']
+
+ def get_request_token_secret(self, client_key, token, request):
+ token_ref = self.oauth_api.get_request_token(token)
+ return token_ref['request_secret']
+
+ def get_access_token_secret(self, client_key, token, request):
+ access_token = self.oauth_api.get_access_token(token)
+ return access_token['access_secret']
+
+ def get_default_realms(self, client_key, request):
+ # realms weren't implemented with the previous library
+ return []
+
+ def get_realms(self, token, request):
+ return []
+
+ def get_redirect_uri(self, token, request):
+ # OOB (out of band) is supposed to be the default value to use
+ return 'oob'
+
+ def get_rsa_key(self, client_key, request):
+ # HMAC signing is used, so return a dummy value
+ return ''
+
+ def invalidate_request_token(self, client_key, request_token, request):
+ # this method is invoked when an access token is generated out of a
+ # request token, to make sure that request token cannot be consumed
+ # anymore. This is done in the backend, so we do nothing here.
+ pass
+
+ def validate_client_key(self, client_key, request):
+ try:
+ return self.oauth_api.get_consumer(client_key) is not None
+ except exception.NotFound:
+ return False
+
+ def validate_request_token(self, client_key, token, request):
+ try:
+ return self.oauth_api.get_request_token(token) is not None
+ except exception.NotFound:
+ return False
+
+ def validate_access_token(self, client_key, token, request):
+ try:
+ return self.oauth_api.get_access_token(token) is not None
+ except exception.NotFound:
+ return False
+
+ def validate_timestamp_and_nonce(self,
+ client_key,
+ timestamp,
+ nonce,
+ request,
+ request_token=None,
+ access_token=None):
+ return True
+
+ def validate_redirect_uri(self, client_key, redirect_uri, request):
+ # we expect OOB, we don't really care
+ return True
+
+ def validate_requested_realms(self, client_key, realms, request):
+ # realms are not used
+ return True
+
+ def validate_realms(self,
+ client_key,
+ token,
+ request,
+ uri=None,
+ realms=None):
+ return True
+
+ def validate_verifier(self, client_key, token, verifier, request):
+ try:
+ req_token = self.oauth_api.get_request_token(token)
+ return req_token['verifier'] == verifier
+ except exception.NotFound:
+ return False
+
+ def verify_request_token(self, token, request):
+ # there aren't strong expectations on the request token format
+ return isinstance(token, basestring)
+
+ def verify_realms(self, token, realms, request):
+ return True
+
+ # The following save_XXX methods are called to create tokens. I chose to
+ # keep the original logic, but the comments below show how that could be
+ # implemented. The real implementation logic is in the backend.
+ def save_access_token(self, token, request):
+ pass
+# token_duration = CONF.oauth1.request_token_duration
+# request_token_id = request.client_key
+# self.oauth_api.create_access_token(request_token_id,
+# token_duration,
+# token["oauth_token"],
+# token["oauth_token_secret"])
+
+ def save_request_token(self, token, request):
+ pass
+# project_id = request.headers.get('Requested-Project-Id')
+# token_duration = CONF.oauth1.request_token_duration
+# self.oauth_api.create_request_token(request.client_key,
+# project_id,
+# token_duration,
+# token["oauth_token"],
+# token["oauth_token_secret"])
+
+ def save_verifier(self, token, verifier, request):
+ # keep the old logic for this, as it is done in two steps and requires
+ # information that the request validator has no access to
+ pass
diff --git a/keystone/tests/test_v3_oauth1.py b/keystone/tests/test_v3_oauth1.py
index 3aecdb3d5..a5ca5d135 100644
--- a/keystone/tests/test_v3_oauth1.py
+++ b/keystone/tests/test_v3_oauth1.py
@@ -60,50 +60,43 @@ class OAuth1Tests(test_v3.RestfulTestCase):
body={'consumer': ref})
return resp.result.get('consumer')
- def _oauth_request(self, consumer, token=None, **kw):
- return oauth1.Request.from_consumer_and_token(consumer=consumer,
- token=token,
- **kw)
-
def _create_request_token(self, consumer, project_id):
- params = {'requested_project_id': project_id}
- headers = {'Content-Type': 'application/json'}
- url = '/OS-OAUTH1/request_token'
- oreq = self._oauth_request(
- consumer=consumer,
- http_url=self.base_url + url,
- http_method='POST',
- parameters=params)
- hmac = oauth1.SignatureMethod_HMAC_SHA1()
- oreq.sign_request(hmac, consumer, None)
- headers.update(oreq.to_header())
- headers.update(params)
- return url, headers
+ endpoint = '/OS-OAUTH1/request_token'
+ client = oauth1.Client(consumer['key'],
+ client_secret=consumer['secret'],
+ signature_method=oauth1.SIG_HMAC,
+ callback_uri="oob")
+ headers = {'requested_project_id': project_id}
+ url, headers, body = client.sign(self.base_url + endpoint,
+ http_method='POST',
+ headers=headers)
+ return endpoint, headers
def _create_access_token(self, consumer, token):
- headers = {'Content-Type': 'application/json'}
- url = '/OS-OAUTH1/access_token'
- oreq = self._oauth_request(
- consumer=consumer, token=token,
- http_method='POST',
- http_url=self.base_url + url)
- hmac = oauth1.SignatureMethod_HMAC_SHA1()
- oreq.sign_request(hmac, consumer, token)
- headers.update(oreq.to_header())
- return url, headers
+ endpoint = '/OS-OAUTH1/access_token'
+ client = oauth1.Client(consumer['key'],
+ client_secret=consumer['secret'],
+ resource_owner_key=token.key,
+ resource_owner_secret=token.secret,
+ signature_method=oauth1.SIG_HMAC,
+ verifier=token.verifier)
+ url, headers, body = client.sign(self.base_url + endpoint,
+ http_method='POST')
+ headers.update({'Content-Type': 'application/json'})
+ return endpoint, headers
def _get_oauth_token(self, consumer, token):
- headers = {'Content-Type': 'application/json'}
- body = {'auth': {'identity': {'methods': ['oauth1'], 'oauth1': {}}}}
- url = '/auth/tokens'
- oreq = self._oauth_request(
- consumer=consumer, token=token,
- http_method='POST',
- http_url=self.base_url + url)
- hmac = oauth1.SignatureMethod_HMAC_SHA1()
- oreq.sign_request(hmac, consumer, token)
- headers.update(oreq.to_header())
- return url, headers, body
+ client = oauth1.Client(consumer['key'],
+ client_secret=consumer['secret'],
+ resource_owner_key=token.key,
+ resource_owner_secret=token.secret,
+ signature_method=oauth1.SIG_HMAC)
+ endpoint = '/auth/tokens'
+ url, headers, body = client.sign(self.base_url + endpoint,
+ http_method='POST')
+ headers.update({'Content-Type': 'application/json'})
+ ref = {'auth': {'identity': {'oauth1': {}, 'methods': ['oauth1']}}}
+ return endpoint, headers, ref
def _authorize_request_token(self, request_id):
return '/OS-OAUTH1/authorize/%s' % (request_id)
@@ -214,8 +207,8 @@ class OAuthFlowTests(OAuth1Tests):
consumer = self._create_single_consumer()
consumer_id = consumer.get('id')
consumer_secret = consumer.get('secret')
- self.consumer = oauth1.Consumer(consumer_id, consumer_secret)
- self.assertIsNotNone(self.consumer.key)
+ self.consumer = {'key': consumer_id, 'secret': consumer_secret}
+ self.assertIsNotNone(self.consumer['secret'])
url, headers = self._create_request_token(self.consumer,
self.project_id)
@@ -270,7 +263,7 @@ class AccessTokenCRUDTests(OAuthFlowTests):
'key': self.access_token.key})
entity = resp.result.get('access_token')
self.assertEqual(entity['id'], self.access_token.key)
- self.assertEqual(entity['consumer_id'], self.consumer.key)
+ self.assertEqual(entity['consumer_id'], self.consumer['key'])
def test_get_access_token_dne(self):
self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens/%(key)s'
@@ -339,7 +332,7 @@ class AuthTokenTests(OAuthFlowTests):
oauth_section = r.result['token']['OS-OAUTH1']
self.assertEqual(oauth_section['access_token_id'],
self.access_token.key)
- self.assertEqual(oauth_section['consumer_id'], self.consumer.key)
+ self.assertEqual(oauth_section['consumer_id'], self.consumer['key'])
# verify the roles section
roles_list = r.result['token']['roles']
@@ -371,7 +364,7 @@ class AuthTokenTests(OAuthFlowTests):
self.test_oauth_flow()
# Delete consumer
- consumer_id = self.consumer.key
+ consumer_id = self.consumer['key']
resp = self.delete('/OS-OAUTH1/consumers/%(consumer_id)s'
% {'consumer_id': consumer_id})
self.assertResponseStatus(resp, 204)
@@ -443,7 +436,7 @@ class AuthTokenTests(OAuthFlowTests):
self.test_oauth_flow()
self.token_api.get_token(self.keystone_token_id)
self.token_api.delete_tokens(self.user_id,
- consumer_id=self.consumer.key)
+ consumer_id=self.consumer['key'])
self.assertRaises(exception.TokenNotFound, self.token_api.get_token,
self.keystone_token_id)
@@ -453,20 +446,18 @@ class MaliciousOAuth1Tests(OAuth1Tests):
def test_bad_consumer_secret(self):
consumer = self._create_single_consumer()
consumer_id = consumer.get('id')
- consumer = oauth1.Consumer(consumer_id, "bad_secret")
- url, headers = self._create_request_token(consumer,
- self.project_id)
- self.post(url, headers=headers, expected_status=500)
+ consumer = {'key': consumer_id, 'secret': uuid.uuid4().hex}
+ url, headers = self._create_request_token(consumer, self.project_id)
+ self.post(url, headers=headers, expected_status=401)
def test_bad_request_token_key(self):
consumer = self._create_single_consumer()
consumer_id = consumer.get('id')
consumer_secret = consumer.get('secret')
- consumer = oauth1.Consumer(consumer_id, consumer_secret)
- url, headers = self._create_request_token(consumer,
- self.project_id)
+ consumer = {'key': consumer_id, 'secret': consumer_secret}
+ url, headers = self._create_request_token(consumer, self.project_id)
self.post(url, headers=headers)
- url = self._authorize_request_token("bad_key")
+ url = self._authorize_request_token(uuid.uuid4().hex)
body = {'roles': [{'id': self.role_id}]}
self.put(url, body=body, expected_status=404)
@@ -474,10 +465,9 @@ class MaliciousOAuth1Tests(OAuth1Tests):
consumer = self._create_single_consumer()
consumer_id = consumer.get('id')
consumer_secret = consumer.get('secret')
- consumer = oauth1.Consumer(consumer_id, consumer_secret)
+ consumer = {'key': consumer_id, 'secret': consumer_secret}
- url, headers = self._create_request_token(consumer,
- self.project_id)
+ url, headers = self._create_request_token(consumer, self.project_id)
content = self.post(url, headers=headers)
credentials = urlparse.parse_qs(content.result)
request_key = credentials.get('oauth_token')[0]
@@ -490,26 +480,23 @@ class MaliciousOAuth1Tests(OAuth1Tests):
verifier = resp.result['token']['oauth_verifier']
self.assertIsNotNone(verifier)
- request_token.set_verifier("bad verifier")
- url, headers = self._create_access_token(consumer,
- request_token)
+ request_token.set_verifier(uuid.uuid4().hex)
+ url, headers = self._create_access_token(consumer, request_token)
self.post(url, headers=headers, expected_status=401)
def test_bad_authorizing_roles(self):
consumer = self._create_single_consumer()
consumer_id = consumer.get('id')
consumer_secret = consumer.get('secret')
- consumer = oauth1.Consumer(consumer_id, consumer_secret)
+ consumer = {'key': consumer_id, 'secret': consumer_secret}
- url, headers = self._create_request_token(consumer,
- self.project_id)
+ url, headers = self._create_request_token(consumer, self.project_id)
content = self.post(url, headers=headers)
credentials = urlparse.parse_qs(content.result)
request_key = credentials.get('oauth_token')[0]
- self.assignment_api.remove_role_from_user_and_project(self.user_id,
- self.project_id,
- self.role_id)
+ self.assignment_api.remove_role_from_user_and_project(
+ self.user_id, self.project_id, self.role_id)
url = self._authorize_request_token(request_key)
body = {'roles': [{'id': self.role_id}]}
self.admin_request(path=url, method='PUT',
@@ -521,8 +508,8 @@ class MaliciousOAuth1Tests(OAuth1Tests):
consumer = self._create_single_consumer()
consumer_id = consumer.get('id')
consumer_secret = consumer.get('secret')
- self.consumer = oauth1.Consumer(consumer_id, consumer_secret)
- self.assertIsNotNone(self.consumer.key)
+ self.consumer = {'key': consumer_id, 'secret': consumer_secret}
+ self.assertIsNotNone(self.consumer['key'])
url, headers = self._create_request_token(self.consumer,
self.project_id)
@@ -542,8 +529,8 @@ class MaliciousOAuth1Tests(OAuth1Tests):
consumer = self._create_single_consumer()
consumer_id = consumer.get('id')
consumer_secret = consumer.get('secret')
- self.consumer = oauth1.Consumer(consumer_id, consumer_secret)
- self.assertIsNotNone(self.consumer.key)
+ self.consumer = {'key': consumer_id, 'secret': consumer_secret}
+ self.assertIsNotNone(self.consumer['key'])
url, headers = self._create_request_token(self.consumer,
self.project_id)
diff --git a/requirements.txt b/requirements.txt
index e7c7a35ab..472a949ab 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -17,7 +17,7 @@ iso8601>=0.1.8
python-keystoneclient>=0.4.1
oslo.config>=1.2.0
Babel>=1.3
-oauth2
+oauthlib
dogpile.cache>=0.5.0
# KDS exclusive dependencies