From 0f8da52196ec5b66cbaea4ab9cee4c1b5d6ee231 Mon Sep 17 00:00:00 2001 From: andyfase Date: Tue, 27 Jul 2021 10:49:19 -0700 Subject: [PATCH] Add support for admin_user_global_sign_out to cognitoidp (#4092) * Add support for admin_user_global_sign_out to cognitoidp --- moto/cognitoidp/models.py | 16 ++++++++ moto/cognitoidp/responses.py | 8 ++++ tests/test_cognitoidp/test_cognitoidp.py | 47 ++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/moto/cognitoidp/models.py b/moto/cognitoidp/models.py index a5d17b710..860da9563 100644 --- a/moto/cognitoidp/models.py +++ b/moto/cognitoidp/models.py @@ -900,6 +900,19 @@ class CognitoIdpBackend(BaseBackend): user = user_pool.users[username] user.update_attributes(attributes) + def admin_user_global_sign_out(self, user_pool_id, username): + user_pool = self.user_pools.get(user_pool_id) + if not user_pool: + raise ResourceNotFoundError(user_pool_id) + + if username not in user_pool.users: + raise UserNotFoundError(username) + + for token, token_tuple in list(user_pool.refresh_tokens.items()): + _, username = token_tuple + if username == username: + user_pool.refresh_tokens[token] = None + def create_resource_server(self, user_pool_id, identifier, name, scopes): user_pool = self.user_pools.get(user_pool_id) if not user_pool: @@ -997,6 +1010,9 @@ class CognitoIdpBackend(BaseBackend): if not refresh_token: raise ResourceNotFoundError(refresh_token) + if user_pool.refresh_tokens[refresh_token] is None: + raise NotAuthorizedError("Refresh Token has been revoked") + client_id, username = user_pool.refresh_tokens[refresh_token] if not username: raise ResourceNotFoundError(username) diff --git a/moto/cognitoidp/responses.py b/moto/cognitoidp/responses.py index b1bc96982..dd7b8a6fc 100644 --- a/moto/cognitoidp/responses.py +++ b/moto/cognitoidp/responses.py @@ -422,6 +422,14 @@ class CognitoIdpResponse(BaseResponse): ) return "" + def admin_user_global_sign_out(self): + user_pool_id = self._get_param("UserPoolId") + username = self._get_param("Username") + cognitoidp_backends[self.region].admin_user_global_sign_out( + user_pool_id, username + ) + return "" + # Resource Server def create_resource_server(self): user_pool_id = self._get_param("UserPoolId") diff --git a/tests/test_cognitoidp/test_cognitoidp.py b/tests/test_cognitoidp/test_cognitoidp.py index d0a2e4c5b..45da376d8 100644 --- a/tests/test_cognitoidp/test_cognitoidp.py +++ b/tests/test_cognitoidp/test_cognitoidp.py @@ -1661,6 +1661,53 @@ def test_confirm_forgot_password(): ) +@mock_cognitoidp +def test_admin_user_global_sign_out(): + conn = boto3.client("cognito-idp", "us-west-2") + result = user_authentication_flow(conn) + + conn.admin_user_global_sign_out( + UserPoolId=result["user_pool_id"], Username=result["username"], + ) + + with pytest.raises(ClientError) as ex: + conn.initiate_auth( + ClientId=result["client_id"], + AuthFlow="REFRESH_TOKEN", + AuthParameters={ + "REFRESH_TOKEN": result["refresh_token"], + "SECRET_HASH": result["secret_hash"], + }, + ) + err = ex.value.response["Error"] + err["Code"].should.equal("NotAuthorizedException") + err["Message"].should.equal("Refresh Token has been revoked") + + +@mock_cognitoidp +def test_admin_user_global_sign_out_unknown_userpool(): + conn = boto3.client("cognito-idp", "us-west-2") + result = user_authentication_flow(conn) + with pytest.raises(ClientError) as ex: + conn.admin_user_global_sign_out( + UserPoolId="n/a", Username=result["username"], + ) + err = ex.value.response["Error"] + err["Code"].should.equal("ResourceNotFoundException") + + +@mock_cognitoidp +def test_admin_user_global_sign_out_unknown_user(): + conn = boto3.client("cognito-idp", "us-west-2") + result = user_authentication_flow(conn) + with pytest.raises(ClientError) as ex: + conn.admin_user_global_sign_out( + UserPoolId=result["user_pool_id"], Username="n/a", + ) + err = ex.value.response["Error"] + err["Code"].should.equal("UserNotFoundException") + + @mock_cognitoidp def test_admin_update_user_attributes(): conn = boto3.client("cognito-idp", "us-west-2")