Skip to content

Commit c29d9f9

Browse files
authored
Stop impersonation call (#565)
related to descope/etc#9294 + tests
1 parent f073bf6 commit c29d9f9

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

descope/management/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class MgmtV1:
8080
# jwt
8181
update_jwt_path = "/v1/mgmt/jwt/update"
8282
impersonate_path = "/v1/mgmt/impersonate"
83+
stop_impersonation_path = "/v1/mgmt/stop/impersonation"
8384
mgmt_sign_in_path = "/v1/mgmt/auth/signin"
8485
mgmt_sign_up_path = "/v1/mgmt/auth/signup"
8586
mgmt_sign_up_or_in_path = "/v1/mgmt/auth/signup-in"

descope/management/jwt.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def impersonate(
5959
validate_consent (bool): Indicate whether to allow impersonation in any case or only if a consent to this operation was granted.
6060
customClaims dict: Custom claims to add to JWT
6161
tenant_id (str): tenant id to set on DCT claim.
62+
refresh_duration (int): duration in seconds for which the new JWT will be valid
6263
6364
Return value (str): A JWT of the impersonated user
6465
@@ -86,6 +87,43 @@ def impersonate(
8687
pswd=self._auth.management_key,
8788
)
8889
return response.json().get("jwt", "")
90+
91+
def stop_impersonation(
92+
self,
93+
jwt: str,
94+
custom_claims: Optional[dict] = None,
95+
tenant_id: Optional[str] = None,
96+
refresh_duration: Optional[int] = None,
97+
) -> str:
98+
"""
99+
Stop impersonation and return to the original user
100+
Args:
101+
jwt (str): The impersonation jwt to stop.
102+
customClaims dict: Custom claims to add to JWT
103+
tenant_id (str): tenant id to set on DCT claim.
104+
refresh_duration (int): duration in seconds for which the new JWT will be valid
105+
106+
Return value (str): A JWT of the actor
107+
108+
Raise:
109+
AuthException: raised if update failed
110+
"""
111+
if not jwt or jwt == "":
112+
raise AuthException(
113+
400, ERROR_TYPE_INVALID_ARGUMENT, "jwt cannot be empty"
114+
)
115+
116+
response = self._auth.do_post(
117+
MgmtV1.impersonate_path,
118+
{
119+
"jwt": jwt,
120+
"customClaims": custom_claims,
121+
"selectedTenant": tenant_id,
122+
"refreshDuration": refresh_duration,
123+
},
124+
pswd=self._auth.management_key,
125+
)
126+
return response.json().get("jwt", "")
89127

90128
def sign_in(
91129
self, login_id: str, login_options: Optional[MgmtLoginOptions] = None

tests/management/test_jwt.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,50 @@ def test_impersonate(self):
144144
timeout=DEFAULT_TIMEOUT_SECONDS,
145145
)
146146

147+
def test_stop_impersonation(self):
148+
client = DescopeClient(
149+
self.dummy_project_id,
150+
self.public_key_dict,
151+
False,
152+
self.dummy_management_key,
153+
)
154+
155+
# Test failed flows
156+
with patch("requests.post") as mock_post:
157+
mock_post.return_value.ok = False
158+
self.assertRaises(
159+
AuthException, client.mgmt.jwt.stop_impersonation, "",
160+
)
161+
162+
# Test success flow
163+
with patch("requests.post") as mock_post:
164+
network_resp = mock.Mock()
165+
network_resp.ok = True
166+
network_resp.json.return_value = json.loads("""{"jwt": "response"}""")
167+
mock_post.return_value = network_resp
168+
resp = client.mgmt.jwt.stop_impersonation("jwtstr")
169+
self.assertEqual(resp, "response")
170+
expected_uri = f"{common.DEFAULT_BASE_URL}{MgmtV1.impersonate_path}"
171+
mock_post.assert_called_with(
172+
expected_uri,
173+
headers={
174+
**common.default_headers,
175+
"Authorization": f"Bearer {self.dummy_project_id}:{self.dummy_management_key}",
176+
"x-descope-project-id": self.dummy_project_id,
177+
},
178+
json={
179+
"jwt": "jwtstr",
180+
"customClaims": None,
181+
"selectedTenant": None,
182+
"refreshDuration": None,
183+
},
184+
allow_redirects=False,
185+
verify=True,
186+
params=None,
187+
timeout=DEFAULT_TIMEOUT_SECONDS,
188+
)
189+
190+
147191
def test_sign_in(self):
148192
client = DescopeClient(
149193
self.dummy_project_id,

0 commit comments

Comments
 (0)