diff --git a/tests/test_user_management.py b/tests/test_user_management.py index f80868ca..4a0eb6cb 100644 --- a/tests/test_user_management.py +++ b/tests/test_user_management.py @@ -362,6 +362,14 @@ def test_get_logout_url(self): assert expected == result + def test_get_logout_url_with_return_to(self): + expected = "https://api.workos.test/user_management/sessions/logout?session_id=session_123&return_to=https%3A%2F%2Fexample.com%2Fsigned-out" + result = self.user_management.get_logout_url( + "session_123", return_to="https://example.com/signed-out" + ) + + assert expected == result + @pytest.mark.sync_and_async(UserManagement, AsyncUserManagement) class TestUserManagement(UserManagementFixtures): diff --git a/workos/session.py b/workos/session.py index fea062ca..c4ab1c35 100644 --- a/workos/session.py +++ b/workos/session.py @@ -159,7 +159,7 @@ def refresh( authenticated=False, reason=str(e) ) - def get_logout_url(self) -> str: + def get_logout_url(self, return_to: Optional[str] = None) -> str: auth_response = self.authenticate() if isinstance(auth_response, AuthenticateWithSessionCookieErrorResponse): @@ -168,7 +168,8 @@ def get_logout_url(self) -> str: ) result = self.user_management.get_logout_url( - session_id=auth_response.session_id + session_id=auth_response.session_id, + return_to=return_to, ) return str(result) diff --git a/workos/user_management.py b/workos/user_management.py index 269ea346..c684eb4e 100644 --- a/workos/user_management.py +++ b/workos/user_management.py @@ -1,4 +1,5 @@ from typing import Optional, Protocol, Sequence, Type, cast +from urllib.parse import urlencode from workos._client_configuration import ClientConfiguration from workos.session import Session from workos.types.list_resource import ( @@ -588,19 +589,25 @@ def get_jwks_url(self) -> str: return f"{self._client_configuration.base_url}sso/jwks/{self._client_configuration.client_id}" - def get_logout_url(self, session_id: str) -> str: + def get_logout_url(self, session_id: str, return_to: Optional[str] = None) -> str: """Get the URL for ending the session and redirecting the user This method is purposefully designed as synchronous as it does not make any HTTP requests. Args: session_id (str): The ID of the user's session + return_to (str): The URL to redirect the user to after the session is ended. (Optional) Returns: (str): URL to redirect the user to to end the session. """ - return f"{self._client_configuration.base_url}user_management/sessions/logout?session_id={session_id}" + params = {"session_id": session_id} + + if return_to: + params["return_to"] = return_to + + return f"{self._client_configuration.base_url}user_management/sessions/logout?{urlencode(params)}" def get_password_reset(self, password_reset_id: str) -> SyncOrAsync[PasswordReset]: """Get the details of a password reset object.