Skip to content

Commit

Permalink
Merge pull request #21 from aarranz/fix/oauth2-authorization-header
Browse files Browse the repository at this point in the history
Handle OAuth2 Bearer tokens correctly
  • Loading branch information
aarranz committed Jul 7, 2018
2 parents 2f832e2 + dbeef5a commit 3749d7d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 14 deletions.
6 changes: 6 additions & 0 deletions ckanext/oauth2/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ def _refresh_and_save_token(user_name):
apikey = toolkit.request.headers.get(self.authorization_header, '')
user_name = None

if self.authorization_header == "authorization":
if apikey.startswith('Bearer '):
apikey = apikey[7:].strip()
else:
apikey = ''

# This API Key is not the one of CKAN, it's the one provided by the OAuth2 Service
if apikey:
try:
Expand Down
54 changes: 40 additions & 14 deletions ckanext/oauth2/tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
from mock import MagicMock, patch
from parameterized import parameterized

AUTHORIZATION_HEADER = 'custom_header'
HOST = 'data.lab.fiware.org'
CUSTOM_AUTHORIZATION_HEADER = 'x-auth-token'
OAUTH2_AUTHORIZATION_HEADER = 'authorization'
HOST = 'ckan.example.org'


class PluginTest(unittest.TestCase):
Expand All @@ -35,7 +36,7 @@ def setUp(self):

self._toolkit = plugin.toolkit
plugin.toolkit = MagicMock()
plugin.toolkit.config = {'ckan.oauth2.authorization_header': AUTHORIZATION_HEADER}
plugin.toolkit.config = {'ckan.oauth2.authorization_header': OAUTH2_AUTHORIZATION_HEADER}

self._oauth2 = plugin.oauth2
plugin.oauth2 = MagicMock()
Expand Down Expand Up @@ -110,17 +111,39 @@ def test_auth_functions(self):
self.assertEquals(False, function_result['success'])

@parameterized.expand([
({}, None, None, None),
({}, None, 'test', 'test'),
({AUTHORIZATION_HEADER: 'api_key'}, 'test', None, 'test'),
({AUTHORIZATION_HEADER: 'api_key'}, 'test', 'test2', 'test'),
({AUTHORIZATION_HEADER: 'api_key'}, ValueError('Invalid Key'), 'test2', 'test2'),
({AUTHORIZATION_HEADER: 'api_key'}, None, 'test2', 'test2'),
({'invalid_header': 'api_key'}, 'test', None, None),
({'invalid_header': 'api_key'}, 'test', 'test2', 'test2'),
({}, None, None, None, False),
({}, None, None, None, True),
({}, None, 'test', 'test', False),
({}, None, 'test', 'test', True),
({'invalid_header': 'api_key'}, None, None, None, False),
({'invalid_header': 'api_key'}, None, 'test2', 'test2', False),
({'invalid_header': 'api_key'}, None, None, None, True),
({'invalid_header': 'api_key'}, None, 'test2', 'test2', True),
({OAUTH2_AUTHORIZATION_HEADER: 'Bearer api_key'}, 'test', None, 'test', True),
({OAUTH2_AUTHORIZATION_HEADER: 'Bearer api_key'}, 'test', 'test2', 'test', True),
({OAUTH2_AUTHORIZATION_HEADER: 'Bearer api_key'}, ValueError('Invalid Key'), 'test2', 'test2', True),
({OAUTH2_AUTHORIZATION_HEADER: 'Bearer api_key'}, ValueError('Invalid Key'), None, None, True),
({OAUTH2_AUTHORIZATION_HEADER: 'Bearer api_key'}, None, 'test2', 'test2', True),
({OAUTH2_AUTHORIZATION_HEADER: 'Otherr api_key'}, None, None, None, True),
({OAUTH2_AUTHORIZATION_HEADER: 'api_key'}, None, 'test2', 'test2', True),
({OAUTH2_AUTHORIZATION_HEADER: 'api_key'}, None, None, None, True),
({CUSTOM_AUTHORIZATION_HEADER: 'api_key'}, 'test', None, 'test', False),
({CUSTOM_AUTHORIZATION_HEADER: 'api_key'}, 'test', 'test2', 'test', False),
({CUSTOM_AUTHORIZATION_HEADER: 'api_key'}, ValueError('Invalid Key'), 'test2', 'test2', False),
({CUSTOM_AUTHORIZATION_HEADER: 'api_key'}, ValueError('Invalid Key'), None, None, False),
({CUSTOM_AUTHORIZATION_HEADER: 'api_key'}, None, 'test2', 'test2', False),
])
@patch("ckanext.oauth2.plugin.g")
def test_identify(self, headers, authenticate_result, identity, expected_user, g_mock):
def test_identify(self, headers, authenticate_result, identity, expected_user, oauth2, g_mock):

if not oauth2:
plugin.toolkit.config = {'ckan.oauth2.authorization_header': CUSTOM_AUTHORIZATION_HEADER}
self._plugin.update_config(plugin.toolkit.config)

self._set_identity(identity)

Expand Down Expand Up @@ -159,8 +182,11 @@ def authenticate_side_effect(identity):
self._plugin.identify()

# Check that the function "authenticate" (called when the API Key is included) has not been called
if headers and AUTHORIZATION_HEADER in headers:
self._plugin.oauth2helper.identify.assert_called_once_with({'access_token': headers[AUTHORIZATION_HEADER]})
if oauth2 and OAUTH2_AUTHORIZATION_HEADER in headers and headers[OAUTH2_AUTHORIZATION_HEADER].startswith('Bearer '):
token = headers[OAUTH2_AUTHORIZATION_HEADER].replace('Bearer ', '')
self._plugin.oauth2helper.identify.assert_called_once_with({'access_token': token})
elif not oauth2 and CUSTOM_AUTHORIZATION_HEADER in headers:
self._plugin.oauth2helper.identify.assert_called_once_with({'access_token': headers[CUSTOM_AUTHORIZATION_HEADER]})
else:
self.assertEquals(0, self._plugin.oauth2helper.identify.call_count)

Expand Down

0 comments on commit 3749d7d

Please sign in to comment.