diff --git a/docs/installation_guide.md b/docs/installation_guide.md index f85b2991f1..2b46335b9c 100644 --- a/docs/installation_guide.md +++ b/docs/installation_guide.md @@ -815,7 +815,7 @@ for more information about how to install and configure such a NGSI proxy. ### Integration with the IdM GE -Create a new Application using the IdM server that is going to be linked (for example: `https://account.lab.fiware.org`). See the [KeyRock's User and Programmers Guide] for more information about how to create such an Application. Redirect URI must be: `http(s)://${wirecloud_server}/complete/fiware/`. Take note of the *Client ID* and the *Client Secret* values (those values are available in the Application details page, inside the *OAuth2 Credentials* section) as they are going to be used later. +The first thing to take into account is that this version of WireCloud is compatible with KeyRock v6 and KeyRock v7. To enable this integration, the first step is creating a new Application using the IdM server that is going to be used (for example: `https://account.lab.fiware.org`). See the [KeyRock's User and Programmers Guide] for more information about how to create such an Application. Redirect URI must be: `http(s)://${wirecloud_server}/complete/fiware/`. Take note of the *Client ID* and the *Client Secret* values (those values are available in the Application details page, inside the *OAuth2 Credentials* section) as they are going to be used later. On the WireCloud instance: diff --git a/src/wirecloud/fiware/social_auth_backend.py b/src/wirecloud/fiware/social_auth_backend.py index cfc9975f61..c7505e8068 100644 --- a/src/wirecloud/fiware/social_auth_backend.py +++ b/src/wirecloud/fiware/social_auth_backend.py @@ -32,6 +32,8 @@ field, check OAuthBackend class for details on how to extend it. """ +from __future__ import unicode_literals + import base64 import time from six.moves.urllib.parse import urljoin @@ -61,7 +63,9 @@ def create_organizations(strategy, backend, user, response, *args, **kwargs): social = None if social is None: - org_name = Organization.objects.search_available_name(organization['displayName']) + # KeyRock v6 uses displayName instead of name + organization_name = organization["name"] if "name" in organization else organization['displayName'] + org_name = Organization.objects.search_available_name(organization_name) org = Organization.objects.create_organization(org_name) social = UserSocialAuth.objects.create(user=org, uid=organization['id']) @@ -123,7 +127,7 @@ def get_user_details(self, response): 'first_name': first_name, 'last_name': last_name, 'is_superuser': superuser, - 'is_staff': superuser + 'is_staff': superuser, } def request_user_info(self, access_token): @@ -133,17 +137,6 @@ def request_user_info(self, access_token): def user_data(self, access_token, *args, **kwargs): data = self.request_user_info(access_token) - # Newer versions of the FIWARE IdM provides and id field with the - # username of the user. Older versions use actorId as identifier, but - # also provides a nickName field. We use nickName because it is also - # unique and provides a better way for migrating to newer versions - # of KeyRock. Store the appropiated field in username to simplify - # the rest of the code - data['username'] = data['nickName'] if 'nickName' in data else data['id'] - - # Something similar happens with Organizations, previous versions of the - # IdM used to provide an actorId, unify this behaviour... - for organization in data['organizations']: - organization["id"] = organization['actorId'] if 'actorId' in organization else organization['id'] + data['username'] = data.get('username') if "username" in data else data.get('id') return data diff --git a/src/wirecloud/fiware/tests/social_backend.py b/src/wirecloud/fiware/tests/social_backend.py index c88fdd99be..425514c276 100644 --- a/src/wirecloud/fiware/tests/social_backend.py +++ b/src/wirecloud/fiware/tests/social_backend.py @@ -35,6 +35,20 @@ class BasicClass(object): def __init__(self): pass + def extra_data(self, user, uid, response, details=None, *args, **kwargs): + return { + "access_token": "access_token", + "refresh_token": "refresh_token", + "expires_in": 3600 + } + + def refresh_token(self, token, *args, **kwargs): + return { + "access_token": "new_access_token", + "refresh_token": "new_refresh_token", + "expires_in": 3600 + } + @classmethod def get_key_and_secret(cls): return ('client', 'secret') @@ -46,25 +60,24 @@ class TestSocialAuthBackend(WirecloudTestCase, TestCase): populate = False use_search_indexes = False + # KeyRock v6 OLD_RESPONSE = { - "schemas": ["urn:scim:schemas:core:2.0:User"], - "id": 1, - "actorId": 1, - "nickName": "demo", + "id": "demo", + "username": "demo", "displayName": "Demo user", "email": "demo@fiware.org", - "roles": [{"id": 1, "name": "Manager"}, {"id": 7, "name": "Ticket manager"}], + "roles": [{"id": "1", "name": "Manager"}, {"id": "7", "name": "Ticket manager"}], "organizations": [{ - "id": 1, - "actorId": 2, + "id": "00000000000000000000000000000001", "displayName": "Universidad Politecnica de Madrid", "roles": [{"id": 14, "name": "Admin"}] }] } - NEW_RESPONSE = { + OLD_RESPONSE_NO_LAST_NAME = { "id": "demo", - "displayName": "Demo user", + "username": "demo", + "displayName": "Demo", "email": "demo@fiware.org", "roles": [{"id": "1", "name": "Manager"}, {"id": "7", "name": "Ticket manager"}], "organizations": [{ @@ -74,21 +87,26 @@ class TestSocialAuthBackend(WirecloudTestCase, TestCase): }] } - RESPONSE_NO_LAST_NAME = { - "id": "demo", + # KeyRock v7 + NEW_RESPONSE = { + "id": "8b0127d8-38f7-4428-b22d-31bd80bba510", + "displayName": "", "username": "demo", - "displayName": "Demo", "email": "demo@fiware.org", - "roles": [{"id": "1", "name": "Manager"}, {"id": "7", "name": "Ticket manager"}], + "roles": [{"id": "4a923351-b767-4fef-bc92-4a4fa996e88e", "name": "Manager"}, {"id": "4a92as51-b54d-4fef-bc92-4a4fa996e88e", "name": "Ticket manager"}], "organizations": [{ - "id": "00000000000000000000000000000001", - "displayName": "Universidad Politecnica de Madrid", - "roles": [{"id": 14, "name": "Admin"}] + "id": "04ac28b2-54c7-46a7-a606-c62fdc4f1513", + "name": "Mi organization", + "description":"dafsdf", + "website": None, + "roles":[{"id": "4a923351-b767-4fef-bc92-4a4fa996e88e", "name":"one_role"}] }] } USER_DATA = {"username": "demo", "email": "demo@fiware.org", "fullname": "Demo user", "first_name": "Demo", "last_name": "user", "is_superuser": False, "is_staff": False} + NEW_USER_DATA = {"username": "demo", "email": "demo@fiware.org", "fullname": "", "first_name": "", "last_name": "", "is_superuser": False, "is_staff": False} USER_DATA_ADMIN = {"username": "demo", "email": "demo@fiware.org", "fullname": "Demo user", "first_name": "Demo", "last_name": "user", "is_superuser": True, "is_staff": True} + NEW_USER_DATA_ADMIN = {"username": "demo", "email": "demo@fiware.org", "fullname": "", "first_name": "", "last_name": "", "is_superuser": True, "is_staff": True} USER_DATA_NO_LAST_NAME = {"username": "demo", "email": "demo@fiware.org", "fullname": "Demo", "first_name": "Demo", "last_name": "", "is_superuser": False, "is_staff": False} def setUp(self): @@ -129,7 +147,7 @@ def test_get_user_data_old_version(self): self.assertIn('username', data) self.assertEqual(data['username'], 'demo') self.assertIn('id', data['organizations'][0]) - self.assertEqual(data['organizations'][0]['id'], 2) + self.assertEqual(data['organizations'][0]['id'], "00000000000000000000000000000001") def test_get_user_data_new_version(self): @@ -139,7 +157,7 @@ def test_get_user_data_new_version(self): self.assertIn('username', data) self.assertEqual(data['username'], 'demo') self.assertIn('id', data['organizations'][0]) - self.assertEqual(data['organizations'][0]['id'], "00000000000000000000000000000001") + self.assertEqual(data['organizations'][0]['id'], "04ac28b2-54c7-46a7-a606-c62fdc4f1513") def test_get_user_data_invalid_response(self): @@ -154,6 +172,20 @@ def test_auth_headers(self): self.assertIn('Basic ', headers['Authorization']) self.assertEqual(headers['Authorization'], 'Basic Y2xpZW50OnNlY3JldA==') + @patch("wirecloud.fiware.social_auth_backend.time.time") + def test_extra_data(self, time_mock): + + time_mock.return_value = 10000 + + data = self.instance.extra_data("user", "uid", "response") + + self.assertEqual(data, { + "access_token": "access_token", + "refresh_token": "refresh_token", + "expires_in": 3600, + "expires_on": 13600 + }) + def test_get_user_details_old_version(self): response = deepcopy(self.OLD_RESPONSE) @@ -165,18 +197,25 @@ def test_get_user_details_old_version(self): def test_get_user_details_old_version_admin(self): response = deepcopy(self.OLD_RESPONSE) - response['roles'][0]['name'] = 'admin' + response['roles'][0]['name'] = 'Admin' data = self.instance.get_user_details(response) self.assertEqual(data, self.USER_DATA_ADMIN) + def test_get_user_details_old_version_no_last_name(self): + + response = deepcopy(self.OLD_RESPONSE_NO_LAST_NAME) + data = self.instance.get_user_details(response) + + self.assertEqual(data, self.USER_DATA_NO_LAST_NAME) + def test_get_user_details_new_version(self): response = deepcopy(self.NEW_RESPONSE) response['username'] = 'demo' data = self.instance.get_user_details(response) - self.assertEqual(data, self.USER_DATA) + self.assertEqual(data, self.NEW_USER_DATA) def test_get_user_details_new_version_admin(self): @@ -184,14 +223,22 @@ def test_get_user_details_new_version_admin(self): response['roles'][0]['name'] = 'Admin' data = self.instance.get_user_details(response) - self.assertEqual(data, self.USER_DATA_ADMIN) + self.assertEqual(data, self.NEW_USER_DATA_ADMIN) - def test_get_user_details_no_last_name(self): + @patch("wirecloud.fiware.social_auth_backend.time.time") + def test_refresh_token_normalizes_token_expiration_time(self, time_mock): - response = deepcopy(self.RESPONSE_NO_LAST_NAME) - data = self.instance.get_user_details(response) + time_mock.return_value = 10000 - self.assertEqual(data, self.USER_DATA_NO_LAST_NAME) + data = self.instance.refresh_token("old_access_token") + + self.assertEqual(data, { + "access_token": "new_access_token", + "refresh_token": "new_refresh_token", + "expires_in": 3600, + "expires_on": 13600, + "openstack_token": None + }) def test_request_user_info(self):