diff --git a/keystone/tests/test_keystoneclient.py b/keystone/tests/test_keystoneclient.py index 1769a747d2..62e1d9d1a9 100644 --- a/keystone/tests/test_keystoneclient.py +++ b/keystone/tests/test_keystoneclient.py @@ -383,25 +383,64 @@ class ClientDrivenTestCase(tests.TestCase): password=uuid.uuid4().hex) def test_change_password_invalidates_token(self): - client = self.get_client(admin=True) + admin_client = self.get_client(admin=True) username = uuid.uuid4().hex - passwd = uuid.uuid4().hex - user = client.users.create(name=username, password=passwd, - email=uuid.uuid4().hex) + password = uuid.uuid4().hex + user = admin_client.users.create(name=username, password=password, + email=uuid.uuid4().hex) - token_id = client.tokens.authenticate(username=username, - password=passwd).id + # auth as user should work before a password change + client = self._client(username=username, password=password) - # authenticate with a token should work before a password change - client.tokens.authenticate(token=token_id) + # auth as user with a token should work before a password change + self._client(token=client.auth_token) - client.users.update_password(user=user.id, password=uuid.uuid4().hex) + # administrative password reset + admin_client.users.update_password( + user=user.id, + password=uuid.uuid4().hex) - # authenticate with a token should not work after a password change + # auth as user with original password should not work after change self.assertRaises(client_exceptions.Unauthorized, - client.tokens.authenticate, - token=token_id) + self._client, + username=username, + password=password) + + # authenticate with an old token should not work after change + self.assertRaises(client_exceptions.Unauthorized, + self._client, + token=client.auth_token) + + def test_user_change_own_password_invalidates_token(self): + from keystoneclient import exceptions as client_exceptions + + # bootstrap a user as admin + client = self.get_client(admin=True) + username = uuid.uuid4().hex + password = uuid.uuid4().hex + client.users.create(name=username, password=password, + email=uuid.uuid4().hex) + + # auth as user should work before a password change + client = self._client(username=username, password=password) + + # auth as user with a token should work before a password change + self._client(token=client.auth_token) + + # change the user's own password + client.users.update_own_password(password, uuid.uuid4().hex) + + # auth as user with original password should not work after change + self.assertRaises(client_exceptions.Unauthorized, + self._client, + username=username, + password=password) + + # auth as user with an old token should not work after change + self.assertRaises(client_exceptions.Unauthorized, + self._client, + token=client.auth_token) def test_disable_tenant_invalidates_token(self): admin_client = self.get_client(admin=True) diff --git a/keystone/tests/test_v3.py b/keystone/tests/test_v3.py index 5d85cef176..027163e81a 100644 --- a/keystone/tests/test_v3.py +++ b/keystone/tests/test_v3.py @@ -326,12 +326,15 @@ class RestfulTestCase(tests.SQLDriverOverrides, rest.RestfulTestCase): def get_requested_token(self, auth): """Request the specific token we want.""" - r = self.admin_request( - method='POST', - path='/v3/auth/tokens', - body=auth) + r = self.v3_authenticate_token(auth) return r.headers.get('X-Subject-Token') + def v3_authenticate_token(self, auth, expected_status=201): + return self.admin_request(method='POST', + path='/v3/auth/tokens', + body=auth, + expected_status=expected_status) + def v3_request(self, path, **kwargs): # Check if the caller has passed in auth details for # use in requesting the token diff --git a/keystone/tests/test_v3_identity.py b/keystone/tests/test_v3_identity.py index 000c50c160..ea222f305a 100644 --- a/keystone/tests/test_v3_identity.py +++ b/keystone/tests/test_v3_identity.py @@ -593,6 +593,41 @@ class IdentityTestCase(test_v3.RestfulTestCase): body={'user': user}) self.assertValidUserResponse(r, user) + def test_admin_password_reset(self): + # bootstrap a user as admin + user_ref = self.new_user_ref(domain_id=self.domain['id']) + password = user_ref['password'] + user_ref = self.identity_api.create_user(user_ref['id'], user_ref) + + # auth as user should work before a password change + old_password_auth = self.build_authentication_request( + user_id=user_ref['id'], + password=password) + r = self.v3_authenticate_token(old_password_auth, expected_status=201) + old_token = r.headers.get('X-Subject-Token') + + # auth as user with a token should work before a password change + old_token_auth = self.build_authentication_request(token=old_token) + self.v3_authenticate_token(old_token_auth, expected_status=201) + + # administrative password reset + new_password = uuid.uuid4().hex + self.patch('/users/%s' % user_ref['id'], + body={'user': {'password': new_password}}, + expected_status=200) + + # auth as user with original password should not work after change + self.v3_authenticate_token(old_password_auth, expected_status=401) + + # auth as user with an old token should not work after change + self.v3_authenticate_token(old_token_auth, expected_status=404) + + # new password should work + new_password_auth = self.build_authentication_request( + user_id=user_ref['id'], + password=new_password) + self.v3_authenticate_token(new_password_auth, expected_status=201) + def test_update_user_domain_id(self): """Call ``PATCH /users/{user_id}`` with domain_id.""" user = self.new_user_ref(domain_id=self.domain['id']) @@ -1917,8 +1952,11 @@ class UserSelfServiceChangingPasswordsTestCase(test_v3.RestfulTestCase): def test_changing_password(self): # original password works - self.get_request_token(self.user_ref['password'], - expected_status=201) + token_id = self.get_request_token(self.user_ref['password'], + expected_status=201) + # original token works + old_token_auth = self.build_authentication_request(token=token_id) + self.v3_authenticate_token(old_token_auth, expected_status=201) # change password new_password = uuid.uuid4().hex @@ -1929,6 +1967,9 @@ class UserSelfServiceChangingPasswordsTestCase(test_v3.RestfulTestCase): # old password fails self.get_request_token(self.user_ref['password'], expected_status=401) + # old token fails + self.v3_authenticate_token(old_token_auth, expected_status=404) + # new password works self.get_request_token(new_password, expected_status=201)