From 885f48fa9ab4da06fe8ba550ac2815e40b0b7128 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Sat, 19 Apr 2025 12:23:42 +0300 Subject: [PATCH 1/3] Cleaned up the public API and updated the code examples --- README.md | 22 +++------------------- zitadel_client/zitadel.py | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 156fc5e6..cbad328c 100644 --- a/README.md +++ b/README.md @@ -69,13 +69,8 @@ JSON file. This process creates a secure token. ```python import zitadel_client as zitadel -from zitadel_client.auth.web_token_authenticator import WebTokenAuthenticator -base_url = "https://example.zitadel.com" -key_file = "/path/to/jwt-key.json" - -authenticator = WebTokenAuthenticator.from_json(base_url, key_file) -zitadel = zitadel.Zitadel(authenticator) +zitadel = zitadel.Zitadel.with_private_key("https://example.us1.zitadel.cloud", "path/to/jwt-key.json") try: response = zitadel.users.add_human_user({ @@ -108,14 +103,8 @@ which is then used to authenticate. ```python import zitadel_client as zitadel -from zitadel_client.auth.client_credentials_authenticator import ClientCredentialsAuthenticator - -base_url = "https://example.zitadel.com" -client_id = "your-client-id" -client_secret = "your-client-secret" -authenticator = ClientCredentialsAuthenticator.builder(base_url, client_id, client_secret).build() -zitadel = zitadel.Zitadel(authenticator) +zitadel = zitadel.Zitadel.with_client_credentials("https://example.us1.zitadel.cloud", "id", "secret") try: response = zitadel.users.add_human_user({ @@ -148,13 +137,8 @@ authenticate without exchanging credentials every time. ```python import zitadel_client as zitadel -from zitadel_client.auth.personal_access_token_authenticator import PersonalAccessTokenAuthenticator - -base_url = "https://example.zitadel.com" -valid_token = "your-valid-token" -authenticator = PersonalAccessTokenAuthenticator(base_url, valid_token) -zitadel = zitadel.Zitadel(authenticator) +zitadel = zitadel.Zitadel.with_access_token("https://example.us1.zitadel.cloud", "token") try: response = zitadel.users.add_human_user({ diff --git a/zitadel_client/zitadel.py b/zitadel_client/zitadel.py index 0e16eb59..5fdff1ef 100644 --- a/zitadel_client/zitadel.py +++ b/zitadel_client/zitadel.py @@ -10,6 +10,9 @@ from zitadel_client.api.user_service_api import UserServiceApi from zitadel_client.api_client import ApiClient from zitadel_client.auth.authenticator import Authenticator +from zitadel_client.auth.client_credentials_authenticator import ClientCredentialsAuthenticator +from zitadel_client.auth.personal_access_token_authenticator import PersonalAccessTokenAuthenticator +from zitadel_client.auth.web_token_authenticator import WebTokenAuthenticator from zitadel_client.configuration import Configuration @@ -93,3 +96,15 @@ def __exit__( traceback: The traceback of the exception, if an exception occurred. """ pass + + @staticmethod + def with_access_token(host: str, access_token: str) -> "Zitadel": + return Zitadel(PersonalAccessTokenAuthenticator(host, access_token)) + + @staticmethod + def with_client_credentials(host: str, client_id: str, client_secret: str) -> "Zitadel": + return Zitadel(ClientCredentialsAuthenticator.builder(host, client_id, client_secret).build()) + + @staticmethod + def with_private_key(host: str, key_file: str) -> "Zitadel": + return Zitadel(WebTokenAuthenticator.from_json(host, key_file)) From 818f6a7af1959f504d28562228f42bfb7d9b7b1e Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Sat, 19 Apr 2025 12:30:33 +0300 Subject: [PATCH 2/3] Updated the specificiation tests to use the public API --- ...sdk_test_using_client_credentials_authentication_spec.py | 6 +++--- ..._test_using_personal_access_token_authentication_spec.py | 6 +++--- spec/sdk_test_using_web_token_authentication_spec.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/sdk_test_using_client_credentials_authentication_spec.py b/spec/sdk_test_using_client_credentials_authentication_spec.py index 7f9f5329..0227989a 100644 --- a/spec/sdk_test_using_client_credentials_authentication_spec.py +++ b/spec/sdk_test_using_client_credentials_authentication_spec.py @@ -30,7 +30,7 @@ def base_url() -> str | None: @pytest.fixture def user_id(client_id: str, client_secret: str, base_url: str) -> str | None: """Fixture to create a user and return their ID.""" - with zitadel.Zitadel(ClientCredentialsAuthenticator.builder(base_url, client_id, client_secret).build()) as client: + with zitadel.Zitadel.with_client_credentials(base_url, client_id, client_secret) as client: try: response = client.users.add_human_user( body=zitadel.models.V2AddHumanUserRequest( @@ -48,7 +48,7 @@ def test_should_deactivate_and_reactivate_user_with_valid_token( user_id: str, client_id: str, client_secret: str, base_url: str ) -> None: """Test to (de)activate the user with a valid token.""" - with zitadel.Zitadel(ClientCredentialsAuthenticator.builder(base_url, client_id, client_secret).build()) as client: + with zitadel.Zitadel.with_client_credentials(base_url, client_id, client_secret) as client: try: deactivate_response = client.users.deactivate_user(user_id=user_id) assert deactivate_response is not None, "Deactivation response is None" @@ -61,7 +61,7 @@ def test_should_deactivate_and_reactivate_user_with_valid_token( def test_should_not_deactivate_or_reactivate_user_with_invalid_token(user_id: str, base_url: str) -> None: """Test to attempt (de)activating the user with an invalid token.""" - with zitadel.Zitadel(ClientCredentialsAuthenticator.builder(base_url, "id", "secret").build()) as client: + with zitadel.Zitadel.with_client_credentials(base_url, "id", "secret") as client: with pytest.raises(Exception, match="Failed to refresh token: invalid_client: client not found"): client.users.deactivate_user(user_id=user_id) diff --git a/spec/sdk_test_using_personal_access_token_authentication_spec.py b/spec/sdk_test_using_personal_access_token_authentication_spec.py index a7bf243b..7dedce97 100644 --- a/spec/sdk_test_using_personal_access_token_authentication_spec.py +++ b/spec/sdk_test_using_personal_access_token_authentication_spec.py @@ -31,7 +31,7 @@ def base_url() -> str | None: @pytest.fixture def user_id(valid_token: str, base_url: str) -> str | None: """Fixture to create a user and return their ID.""" - with zitadel.Zitadel(PersonalAccessTokenAuthenticator(base_url, valid_token)) as client: + with zitadel.Zitadel.with_access_token(base_url, valid_token) as client: try: response = client.users.add_human_user( body=zitadel.models.V2AddHumanUserRequest( @@ -47,7 +47,7 @@ def user_id(valid_token: str, base_url: str) -> str | None: def test_should_deactivate_and_reactivate_user_with_valid_token(user_id: str, valid_token: str, base_url: str) -> None: """Test to (de)activate the user with a valid token.""" - with zitadel.Zitadel(PersonalAccessTokenAuthenticator(base_url, valid_token)) as client: + with zitadel.Zitadel.with_access_token(base_url, valid_token) as client: try: deactivate_response = client.users.deactivate_user(user_id=user_id) assert deactivate_response is not None, "Deactivation response is None" @@ -60,7 +60,7 @@ def test_should_deactivate_and_reactivate_user_with_valid_token(user_id: str, va def test_should_not_deactivate_or_reactivate_user_with_invalid_token(user_id: str, invalid_token: str, base_url: str) -> None: """Test to attempt (de)activating the user with an invalid token.""" - with zitadel.Zitadel(PersonalAccessTokenAuthenticator(base_url, invalid_token)) as client: + with zitadel.Zitadel.with_access_token(base_url, invalid_token) as client: with pytest.raises(UnauthorizedException): client.users.deactivate_user(user_id=user_id) diff --git a/spec/sdk_test_using_web_token_authentication_spec.py b/spec/sdk_test_using_web_token_authentication_spec.py index c91b09f8..f655cbfa 100644 --- a/spec/sdk_test_using_web_token_authentication_spec.py +++ b/spec/sdk_test_using_web_token_authentication_spec.py @@ -27,7 +27,7 @@ def base_url() -> str | None: @pytest.fixture def user_id(key_file: str, base_url: str) -> str | None: """Fixture to create a user and return their ID.""" - with zitadel.Zitadel(WebTokenAuthenticator.from_json(base_url, key_file)) as client: + with zitadel.Zitadel.with_private_key(base_url, key_file) as client: try: response = client.users.add_human_user( body=zitadel.models.V2AddHumanUserRequest( @@ -43,7 +43,7 @@ def user_id(key_file: str, base_url: str) -> str | None: def test_should_deactivate_and_reactivate_user_with_valid_token(user_id: str, key_file: str, base_url: str) -> None: """Test to (de)activate the user with a valid token.""" - with zitadel.Zitadel(WebTokenAuthenticator.from_json(base_url, key_file)) as client: + with zitadel.Zitadel.with_private_key(base_url, key_file) as client: try: deactivate_response = client.users.deactivate_user(user_id=user_id) assert deactivate_response is not None, "Deactivation response is None" From ad1ccdd33a1023151e59d17c5a839c3ec617ad39 Mon Sep 17 00:00:00 2001 From: Mridang Agarwalla Date: Sat, 19 Apr 2025 13:20:43 +0300 Subject: [PATCH 3/3] Updated the README --- zitadel_client/zitadel.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/zitadel_client/zitadel.py b/zitadel_client/zitadel.py index 5fdff1ef..3763bc11 100644 --- a/zitadel_client/zitadel.py +++ b/zitadel_client/zitadel.py @@ -99,12 +99,37 @@ def __exit__( @staticmethod def with_access_token(host: str, access_token: str) -> "Zitadel": + """ + Initialize the SDK with a Personal Access Token (PAT). + + :param host: API URL (e.g., "https://api.zitadel.example.com"). + :param access_token: Personal Access Token for Bearer authentication. + :return: Configured Zitadel client instance. + :see: https://zitadel.com/docs/guides/integrate/service-users/personal-access-token + """ return Zitadel(PersonalAccessTokenAuthenticator(host, access_token)) @staticmethod def with_client_credentials(host: str, client_id: str, client_secret: str) -> "Zitadel": + """ + Initialize the SDK using OAuth2 Client Credentials flow. + + :param host: API URL. + :param client_id: OAuth2 client identifier. + :param client_secret: OAuth2 client secret. + :return: Configured Zitadel client instance with token auto-refresh. + :see: https://zitadel.com/docs/guides/integrate/service-users/client-credentials + """ return Zitadel(ClientCredentialsAuthenticator.builder(host, client_id, client_secret).build()) @staticmethod def with_private_key(host: str, key_file: str) -> "Zitadel": + """ + Initialize the SDK via Private Key JWT assertion. + + :param host: API URL. + :param key_file: Path to service account JSON or PEM key file. + :return: Configured Zitadel client instance using JWT assertion. + :see: https://zitadel.com/docs/guides/integrate/service-users/private-key-jwt + """ return Zitadel(WebTokenAuthenticator.from_json(host, key_file))