diff --git a/keystone/contrib/oauth1/controllers.py b/keystone/contrib/oauth1/controllers.py index 4759bdee0d..837e5fd25f 100644 --- a/keystone/contrib/oauth1/controllers.py +++ b/keystone/contrib/oauth1/controllers.py @@ -24,13 +24,25 @@ from keystone.contrib.oauth1 import validator from keystone import exception from keystone.i18n import _ +from keystone.models import token_model +from keystone import notifications from keystone.openstack.common import jsonutils CONF = config.CONF -@dependency.requires('oauth_api', 'token_api') +@notifications.internal(notifications.INVALIDATE_USER_OAUTH_CONSUMER_TOKENS, + resource_id_arg_index=0) +def _emit_user_oauth_consumer_token_invalidate(payload): + # This is a special case notification that expect the payload to be a dict + # containing the user_id and the consumer_id. This is so that the token + # provider can invalidate any tokens in the token persistence if + # token persistence is enabled + pass + + +@dependency.requires('oauth_api', 'token_provider_api') class ConsumerCrudV3(controller.V3Controller): collection_name = 'consumers' member_name = 'consumer' @@ -70,9 +82,13 @@ def get_consumer(self, context, consumer_id): @controller.protected() def delete_consumer(self, context, consumer_id): - user_token_ref = self.token_api.get_token(context['token_id']) - user_id = user_token_ref['user'].get('id') - self.token_api.delete_tokens(user_id, consumer_id=consumer_id) + user_token_ref = token_model.KeystoneToken( + token_id=context['token_id'], + token_data=self.token_provider_api.validate_token( + context['token_id'])) + payload = {'user_id': user_token_ref.user_id, + 'consumer_id': consumer_id} + _emit_user_oauth_consumer_token_invalidate(payload) self.oauth_api.delete_consumer(consumer_id) def _validate_consumer_ref(self, consumer): @@ -81,7 +97,7 @@ def _validate_consumer_ref(self, consumer): raise exception.ValidationError(message=msg) -@dependency.requires('oauth_api', 'token_api') +@dependency.requires('oauth_api') class AccessTokenCrudV3(controller.V3Controller): collection_name = 'access_tokens' member_name = 'access_token' @@ -120,7 +136,8 @@ def list_access_tokens(self, context, user_id): def delete_access_token(self, context, user_id, access_token_id): access_token = self.oauth_api.get_access_token(access_token_id) consumer_id = access_token['consumer_id'] - self.token_api.delete_tokens(user_id, consumer_id=consumer_id) + payload = {'user_id': user_id, 'consumer_id': consumer_id} + _emit_user_oauth_consumer_token_invalidate(payload) return self.oauth_api.delete_access_token( user_id, access_token_id) @@ -187,7 +204,7 @@ def _format_role_entity(self, role_id): return formatted_entity -@dependency.requires('assignment_api', 'oauth_api', 'token_api') +@dependency.requires('assignment_api', 'oauth_api', 'token_provider_api') class OAuthControllerV3(controller.V3Controller): collection_name = 'not_used' member_name = 'not_used' @@ -351,8 +368,11 @@ def authorize_request_token(self, context, request_token_id, roles): authed_roles.add(role['id']) # verify the authorizing user has the roles - user_token = self.token_api.get_token(context['token_id']) - user_id = user_token['user'].get('id') + user_token = token_model.KeystoneToken( + token_id=context['token_id'], + token_data=self.token_provider_api.validate_token( + context['token_id'])) + user_id = user_token.user_id project_id = req_token['requested_project_id'] user_roles = self.assignment_api.get_roles_for_user_and_project( user_id, project_id) diff --git a/keystone/notifications.py b/keystone/notifications.py index 3527458575..86391c2ce3 100644 --- a/keystone/notifications.py +++ b/keystone/notifications.py @@ -79,6 +79,7 @@ def getcallargs(f, *positional, **named): # internally for handling token persistence token deletions INVALIDATE_USER_TOKEN_PERSISTENCE = 'invalidate_user_tokens' INVALIDATE_USER_PROJECT_TOKEN_PERSISTENCE = 'invalidate_user_project_tokens' +INVALIDATE_USER_OAUTH_CONSUMER_TOKENS = 'invalidate_user_consumer_tokens' class ManagerNotificationWrapper(object): diff --git a/keystone/token/provider.py b/keystone/token/provider.py index d4a76f93d3..db5ae4e8e6 100644 --- a/keystone/token/provider.py +++ b/keystone/token/provider.py @@ -166,7 +166,9 @@ def __init__(self): notifications.INVALIDATE_USER_TOKEN_PERSISTENCE: [ self._delete_user_tokens_callback], notifications.INVALIDATE_USER_PROJECT_TOKEN_PERSISTENCE: [ - self._delete_user_project_tokens_callback]} + self._delete_user_project_tokens_callback], + notifications.INVALIDATE_USER_OAUTH_CONSUMER_TOKENS: [ + self._delete_user_oauth_consumer_tokens_callback]} } @property @@ -511,6 +513,15 @@ def _delete_project_tokens_callback(self, service, resource_type, self.assignment_api.list_user_ids_for_project(project_id), project_id=project_id) + def _delete_user_oauth_consumer_tokens_callback(self, service, + resource_type, operation, + payload): + if CONF.token.revoke_by_id: + user_id = payload['resource_info']['user_id'] + consumer_id = payload['resource_info']['consumer_id'] + self.persistence.delete_tokens(user_id=user_id, + consumer_id=consumer_id) + @six.add_metaclass(abc.ABCMeta) class Provider(object):