kiarina-lib-google-auth 1.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. kiarina_lib_google_auth-1.4.0/.gitignore +34 -0
  2. kiarina_lib_google_auth-1.4.0/.vscode/settings.json +8 -0
  3. kiarina_lib_google_auth-1.4.0/CHANGELOG.md +64 -0
  4. kiarina_lib_google_auth-1.4.0/PKG-INFO +502 -0
  5. kiarina_lib_google_auth-1.4.0/README.md +475 -0
  6. kiarina_lib_google_auth-1.4.0/pyproject.toml +43 -0
  7. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/__init__.py +58 -0
  8. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_helpers/__init__.py +0 -0
  9. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_helpers/get_credentials.py +63 -0
  10. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_helpers/get_self_signed_jwt.py +23 -0
  11. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_types/__init__.py +0 -0
  12. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_types/credentials.py +13 -0
  13. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_types/credentials_cache.py +21 -0
  14. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_utils/__init__.py +0 -0
  15. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_utils/get_default_credentials.py +35 -0
  16. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_utils/get_service_account_credentials.py +27 -0
  17. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/_utils/get_user_account_credentials.py +81 -0
  18. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/py.typed +0 -0
  19. kiarina_lib_google_auth-1.4.0/src/kiarina/lib/google/auth/settings.py +116 -0
  20. kiarina_lib_google_auth-1.4.0/tests/__init__.py +0 -0
  21. kiarina_lib_google_auth-1.4.0/tests/conftest.py +0 -0
  22. kiarina_lib_google_auth-1.4.0/tests/test_get_credentials.py +83 -0
  23. kiarina_lib_google_auth-1.4.0/tests/test_get_default_credentials.py +36 -0
  24. kiarina_lib_google_auth-1.4.0/tests/test_get_self_signed_jwt.py +22 -0
  25. kiarina_lib_google_auth-1.4.0/tests/test_get_service_account_credentials.py +38 -0
  26. kiarina_lib_google_auth-1.4.0/tests/test_get_user_account_credentials.py +125 -0
@@ -0,0 +1,34 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.so
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .ruff_cache/
9
+ .mypy_cache/
10
+ .pytest_cache/
11
+ .coverage
12
+ coverage.xml
13
+ htmlcov/
14
+
15
+ # uv
16
+ .uv_cache/
17
+
18
+ # Virtual environments & config
19
+ .venv/
20
+ .env
21
+
22
+ # OS
23
+ .DS_Store
24
+
25
+ # Project specific
26
+ *.log
27
+ tmp/
28
+
29
+ # Test data
30
+ tests/data/large/
31
+
32
+ # mise tasks (always include)
33
+ !mise-tasks/
34
+ !mise-tasks/**
@@ -0,0 +1,8 @@
1
+ {
2
+ "python.testing.pytestArgs": [
3
+ "tests"
4
+ ],
5
+ "python.testing.unittestEnabled": false,
6
+ "python.testing.pytestEnabled": true,
7
+ "python.envFile": "${workspaceFolder}/.env"
8
+ }
@@ -0,0 +1,64 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [1.4.0] - 2025-10-09
11
+
12
+ ### Added
13
+ - Initial release of kiarina-lib-google-auth
14
+ - Google Cloud authentication library with configuration management using pydantic-settings-manager
15
+ - Multiple authentication methods:
16
+ - Default credentials (Application Default Credentials)
17
+ - Service account authentication (from file or JSON data)
18
+ - User account authentication (OAuth2 authorized user credentials)
19
+ - Service account impersonation with configurable scopes
20
+ - Credentials caching support with `CredentialsCache` protocol
21
+ - Self-signed JWT generation for service accounts
22
+ - Type safety with full type hints and Pydantic validation
23
+ - Environment variable configuration support with `KIARINA_LIB_GOOGLE_AUTH_` prefix
24
+ - Runtime configuration overrides
25
+ - Multiple named configurations support via pydantic-settings-manager
26
+ - Automatic credential refresh for user accounts
27
+ - Stable cache key generation for user account credentials
28
+ - Default scopes for GCP, Google Drive, and Google Sheets
29
+
30
+ ### Features
31
+ - **`get_credentials()`**: Main function to obtain credentials based on configuration
32
+ - **`get_self_signed_jwt()`**: Generate self-signed JWTs for service account authentication
33
+ - **`get_default_credentials()`**: Utility to get default Google credentials (ADC)
34
+ - **`get_service_account_credentials()`**: Utility to get service account credentials
35
+ - **`get_user_account_credentials()`**: Utility to get user account credentials with caching
36
+ - **`GoogleAuthSettings`**: Pydantic settings model with comprehensive configuration options
37
+ - **`CredentialsCache`**: Protocol for implementing custom credentials caching strategies
38
+ - **`Credentials`**: Type alias for all supported credential types
39
+
40
+ ### Security
41
+ - **Enhanced credential protection**: Changed `service_account_data`, `client_secret_data`, and `authorized_user_data` fields to use `SecretStr`
42
+ - Credentials are now masked in string representations and logs (displayed as `**********`)
43
+ - Prevents accidental exposure of sensitive data in debug output
44
+ - Access secret values explicitly via `.get_secret_value()` method
45
+ - Minimal breaking change: only affects direct field access (use `get_*_data()` methods instead)
46
+
47
+ ### Configuration Options
48
+ - `type`: Authentication type (default, service_account, user_account)
49
+ - `service_account_file`: Path to service account key file
50
+ - `service_account_data`: Service account key data as JSON string
51
+ - `service_account_email`: Service account email address
52
+ - `authorized_user_file`: Path to authorized user credentials file
53
+ - `authorized_user_data`: Authorized user credentials as JSON string
54
+ - `user_account_email`: User account email address
55
+ - `client_secret_file`: Path to OAuth2 client secret file
56
+ - `client_secret_data`: OAuth2 client secret as JSON string
57
+ - `impersonate_service_account`: Target service account for impersonation
58
+ - `scopes`: List of OAuth2 scopes
59
+ - `project_id`: GCP project ID
60
+
61
+ ### Dependencies
62
+ - google-api-python-client>=2.184.0
63
+ - pydantic-settings>=2.10.1
64
+ - pydantic-settings-manager>=2.1.0
@@ -0,0 +1,502 @@
1
+ Metadata-Version: 2.4
2
+ Name: kiarina-lib-google-auth
3
+ Version: 1.4.0
4
+ Summary: Google Cloud client library for kiarina namespace
5
+ Project-URL: Homepage, https://github.com/kiarina/kiarina-python
6
+ Project-URL: Repository, https://github.com/kiarina/kiarina-python
7
+ Project-URL: Issues, https://github.com/kiarina/kiarina-python/issues
8
+ Project-URL: Changelog, https://github.com/kiarina/kiarina-python/blob/main/packages/kiarina-lib-google-auth/CHANGELOG.md
9
+ Project-URL: Documentation, https://github.com/kiarina/kiarina-python/tree/main/packages/kiarina-lib-google-auth#readme
10
+ Author-email: kiarina <kiarinadawa@gmail.com>
11
+ Maintainer-email: kiarina <kiarinadawa@gmail.com>
12
+ License-Expression: MIT
13
+ Keywords: client,cloud,gcp,google,google-cloud,pydantic,settings
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.12
23
+ Requires-Dist: google-api-python-client>=2.184.0
24
+ Requires-Dist: pydantic-settings-manager>=2.1.0
25
+ Requires-Dist: pydantic-settings>=2.10.1
26
+ Description-Content-Type: text/markdown
27
+
28
+ # kiarina-lib-google-auth
29
+
30
+ A Python client library for Google Cloud authentication with configuration management and support for multiple credential types.
31
+
32
+ ## Features
33
+
34
+ - **Multiple Authentication Methods**: Support for default credentials, service accounts, and user accounts
35
+ - **Service Account Impersonation**: Impersonate service accounts for delegated access
36
+ - **Configuration Management**: Use `pydantic-settings-manager` for flexible configuration
37
+ - **Credentials Caching**: Cache and refresh user account credentials automatically
38
+ - **Self-Signed JWT**: Generate self-signed JWTs for service accounts
39
+ - **Type Safety**: Full type hints and Pydantic validation
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ pip install kiarina-lib-google-auth
45
+ ```
46
+
47
+ ## Quick Start
48
+
49
+ ### Basic Usage with Default Credentials
50
+
51
+ ```python
52
+ from kiarina.lib.google.auth import get_credentials
53
+
54
+ # Get default credentials (ADC, service account, or compute engine)
55
+ credentials = get_credentials()
56
+ ```
57
+
58
+ ### Service Account Authentication
59
+
60
+ ```python
61
+ from kiarina.lib.google.auth import get_credentials, GoogleAuthSettings
62
+
63
+ # From service account key file
64
+ credentials = get_credentials(
65
+ settings=GoogleAuthSettings(
66
+ type="service_account",
67
+ service_account_file="~/path/to/service-account-key.json"
68
+ )
69
+ )
70
+
71
+ # From service account key data (JSON string)
72
+ import json
73
+ credentials = get_credentials(
74
+ settings=GoogleAuthSettings(
75
+ type="service_account",
76
+ service_account_data=json.dumps({
77
+ "type": "service_account",
78
+ "project_id": "your-project",
79
+ "private_key_id": "...",
80
+ "private_key": "...",
81
+ "client_email": "...",
82
+ # ... other fields
83
+ })
84
+ )
85
+ )
86
+ ```
87
+
88
+ ### User Account Authentication
89
+
90
+ ```python
91
+ from kiarina.lib.google.auth import get_credentials, GoogleAuthSettings
92
+
93
+ # From authorized user file (OAuth2 credentials)
94
+ credentials = get_credentials(
95
+ settings=GoogleAuthSettings(
96
+ type="user_account",
97
+ authorized_user_file="~/path/to/authorized-user.json",
98
+ scopes=["https://www.googleapis.com/auth/drive"]
99
+ )
100
+ )
101
+
102
+ # From authorized user data (JSON string)
103
+ credentials = get_credentials(
104
+ settings=GoogleAuthSettings(
105
+ type="user_account",
106
+ authorized_user_data=json.dumps({
107
+ "type": "authorized_user",
108
+ "client_id": "...",
109
+ "client_secret": "...",
110
+ "refresh_token": "..."
111
+ }),
112
+ scopes=["https://www.googleapis.com/auth/drive"]
113
+ )
114
+ )
115
+ ```
116
+
117
+ ### Service Account Impersonation
118
+
119
+ ```python
120
+ from kiarina.lib.google.auth import get_credentials, GoogleAuthSettings
121
+
122
+ # Impersonate a service account using source credentials
123
+ credentials = get_credentials(
124
+ settings=GoogleAuthSettings(
125
+ type="service_account",
126
+ service_account_file="~/path/to/source-sa-key.json",
127
+ impersonate_service_account="target-sa@project.iam.gserviceaccount.com",
128
+ scopes=["https://www.googleapis.com/auth/cloud-platform"]
129
+ )
130
+ )
131
+
132
+ # Note: Source principal requires roles/iam.serviceAccountTokenCreator role
133
+ ```
134
+
135
+ ### Credentials Caching
136
+
137
+ ```python
138
+ from kiarina.lib.google.auth import get_credentials, GoogleAuthSettings, CredentialsCache
139
+
140
+ # Implement a cache (e.g., in-memory, Redis, file-based)
141
+ class InMemoryCache(CredentialsCache):
142
+ def __init__(self):
143
+ self._cache: str | None = None
144
+
145
+ def get(self) -> str | None:
146
+ return self._cache
147
+
148
+ def set(self, value: str) -> None:
149
+ self._cache = value
150
+
151
+ cache = InMemoryCache()
152
+
153
+ # Use cache for user account credentials
154
+ credentials = get_credentials(
155
+ settings=GoogleAuthSettings(
156
+ type="user_account",
157
+ authorized_user_file="~/path/to/authorized-user.json",
158
+ scopes=["https://www.googleapis.com/auth/drive"]
159
+ ),
160
+ cache=cache
161
+ )
162
+ ```
163
+
164
+ ### Self-Signed JWT
165
+
166
+ ```python
167
+ from kiarina.lib.google.auth import get_self_signed_jwt, GoogleAuthSettings
168
+
169
+ # Generate a self-signed JWT for service account
170
+ jwt_token = get_self_signed_jwt(
171
+ settings=GoogleAuthSettings(
172
+ type="service_account",
173
+ service_account_file="~/path/to/service-account-key.json"
174
+ ),
175
+ audience="https://your-service.example.com/"
176
+ )
177
+ ```
178
+
179
+ ## Configuration
180
+
181
+ This library uses [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) for flexible configuration management.
182
+
183
+ ### Environment Variables
184
+
185
+ Configure authentication using environment variables:
186
+
187
+ ```bash
188
+ # Authentication type
189
+ export KIARINA_LIB_GOOGLE_AUTH_TYPE="service_account"
190
+
191
+ # Service account configuration
192
+ export KIARINA_LIB_GOOGLE_AUTH_SERVICE_ACCOUNT_FILE="~/path/to/sa-key.json"
193
+ export KIARINA_LIB_GOOGLE_AUTH_SERVICE_ACCOUNT_EMAIL="sa@project.iam.gserviceaccount.com"
194
+
195
+ # User account configuration
196
+ export KIARINA_LIB_GOOGLE_AUTH_AUTHORIZED_USER_FILE="~/path/to/authorized-user.json"
197
+ export KIARINA_LIB_GOOGLE_AUTH_USER_ACCOUNT_EMAIL="user@example.com"
198
+
199
+ # Impersonation
200
+ export KIARINA_LIB_GOOGLE_AUTH_IMPERSONATE_SERVICE_ACCOUNT="target-sa@project.iam.gserviceaccount.com"
201
+
202
+ # Scopes (comma-separated)
203
+ export KIARINA_LIB_GOOGLE_AUTH_SCOPES="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/drive"
204
+
205
+ # Project ID
206
+ export KIARINA_LIB_GOOGLE_AUTH_PROJECT_ID="your-project-id"
207
+ ```
208
+
209
+ ### Programmatic Configuration
210
+
211
+ ```python
212
+ from kiarina.lib.google.auth import settings_manager, get_credentials
213
+
214
+ # Configure multiple environments
215
+ settings_manager.user_config = {
216
+ "development": {
217
+ "type": "user_account",
218
+ "authorized_user_file": "~/.config/gcloud/application_default_credentials.json",
219
+ "scopes": ["https://www.googleapis.com/auth/cloud-platform"]
220
+ },
221
+ "production": {
222
+ "type": "service_account",
223
+ "service_account_file": "/secrets/prod-sa-key.json",
224
+ "scopes": ["https://www.googleapis.com/auth/cloud-platform"]
225
+ }
226
+ }
227
+
228
+ # Switch to production configuration
229
+ settings_manager.active_key = "production"
230
+ credentials = get_credentials()
231
+ ```
232
+
233
+ ## API Reference
234
+
235
+ ### Main Functions
236
+
237
+ #### `get_credentials(config_key=None, *, settings=None, scopes=None, cache=None)`
238
+
239
+ Get Google Cloud credentials based on configuration.
240
+
241
+ **Parameters:**
242
+ - `config_key` (str | None): Configuration key for multi-config setup
243
+ - `settings` (GoogleAuthSettings | None): Settings object (overrides config_key)
244
+ - `scopes` (list[str] | None): OAuth2 scopes (overrides settings.scopes)
245
+ - `cache` (CredentialsCache | None): Credentials cache for user accounts
246
+
247
+ **Returns:**
248
+ - `Credentials`: Google Cloud credentials object
249
+
250
+ **Supported credential types:**
251
+ - `google.auth.compute_engine.credentials.Credentials` (Compute Engine)
252
+ - `google.oauth2.service_account.Credentials` (Service Account)
253
+ - `google.oauth2.credentials.Credentials` (User Account)
254
+ - `google.auth.impersonated_credentials.Credentials` (Impersonated)
255
+
256
+ #### `get_self_signed_jwt(config_key=None, *, settings=None, audience)`
257
+
258
+ Generate a self-signed JWT for service account authentication.
259
+
260
+ **Parameters:**
261
+ - `config_key` (str | None): Configuration key for multi-config setup
262
+ - `settings` (GoogleAuthSettings | None): Settings object (overrides config_key)
263
+ - `audience` (str): JWT audience (target service URL)
264
+
265
+ **Returns:**
266
+ - `str`: Self-signed JWT token
267
+
268
+ ### Utility Functions
269
+
270
+ #### `get_default_credentials()`
271
+
272
+ Get default Google credentials using Application Default Credentials (ADC).
273
+
274
+ **Returns:**
275
+ - `Credentials`: Default credentials (ADC, service account, or compute engine)
276
+
277
+ #### `get_service_account_credentials(*, service_account_file=None, service_account_data=None)`
278
+
279
+ Get service account credentials from file or data.
280
+
281
+ **Parameters:**
282
+ - `service_account_file` (str | PathLike | None): Path to service account key file
283
+ - `service_account_data` (dict | None): Service account key data
284
+
285
+ **Returns:**
286
+ - `google.oauth2.service_account.Credentials`: Service account credentials
287
+
288
+ #### `get_user_account_credentials(*, authorized_user_file=None, authorized_user_data=None, scopes, cache=None)`
289
+
290
+ Get user account credentials from file or data.
291
+
292
+ **Parameters:**
293
+ - `authorized_user_file` (str | PathLike | None): Path to authorized user file
294
+ - `authorized_user_data` (dict | None): Authorized user data
295
+ - `scopes` (list[str]): OAuth2 scopes
296
+ - `cache` (CredentialsCache | None): Credentials cache
297
+
298
+ **Returns:**
299
+ - `google.oauth2.credentials.Credentials`: User account credentials
300
+
301
+ ### Configuration Classes
302
+
303
+ #### `GoogleAuthSettings`
304
+
305
+ Pydantic settings model for Google Cloud authentication.
306
+
307
+ **Fields:**
308
+ - `type` (Literal["default", "service_account", "user_account"]): Authentication type (default: "default")
309
+ - `service_account_email` (str | None): Service account email
310
+ - `service_account_file` (str | None): Path to service account key file
311
+ - `service_account_data` (str | None): Service account key data (JSON string)
312
+ - `user_account_email` (str | None): User account email
313
+ - `client_secret_file` (str | None): Path to client secret file
314
+ - `client_secret_data` (str | None): Client secret data (JSON string)
315
+ - `authorized_user_file` (str | None): Path to authorized user file
316
+ - `authorized_user_data` (str | None): Authorized user data (JSON string)
317
+ - `impersonate_service_account` (str | None): Target service account email for impersonation
318
+ - `scopes` (list[str]): OAuth2 scopes (default: cloud-platform, drive, spreadsheets)
319
+ - `project_id` (str | None): GCP project ID
320
+
321
+ **Methods:**
322
+ - `get_service_account_data()`: Parse service_account_data JSON string
323
+ - `get_client_secret_data()`: Parse client_secret_data JSON string
324
+ - `get_authorized_user_data()`: Parse authorized_user_data JSON string
325
+
326
+ #### `CredentialsCache` (Protocol)
327
+
328
+ Protocol for implementing credentials cache.
329
+
330
+ **Methods:**
331
+ - `get() -> str | None`: Retrieve cached credentials (JSON string)
332
+ - `set(value: str) -> None`: Store credentials in cache (JSON string)
333
+
334
+ ## Authentication Types
335
+
336
+ ### 1. Default Credentials
337
+
338
+ Uses Application Default Credentials (ADC) in the following priority:
339
+
340
+ 1. `GOOGLE_APPLICATION_CREDENTIALS` environment variable (service account key file)
341
+ 2. `gcloud auth application-default login` credentials (user account)
342
+ 3. Compute Engine metadata server (compute engine credentials)
343
+
344
+ ```python
345
+ credentials = get_credentials(
346
+ settings=GoogleAuthSettings(type="default")
347
+ )
348
+ ```
349
+
350
+ ### 2. Service Account
351
+
352
+ Authenticates using a service account key file or data.
353
+
354
+ ```python
355
+ # From file
356
+ credentials = get_credentials(
357
+ settings=GoogleAuthSettings(
358
+ type="service_account",
359
+ service_account_file="~/sa-key.json"
360
+ )
361
+ )
362
+
363
+ # From data
364
+ credentials = get_credentials(
365
+ settings=GoogleAuthSettings(
366
+ type="service_account",
367
+ service_account_data='{"type": "service_account", ...}'
368
+ )
369
+ )
370
+ ```
371
+
372
+ ### 3. User Account
373
+
374
+ Authenticates using OAuth2 user credentials (authorized user file).
375
+
376
+ ```python
377
+ credentials = get_credentials(
378
+ settings=GoogleAuthSettings(
379
+ type="user_account",
380
+ authorized_user_file="~/.config/gcloud/application_default_credentials.json",
381
+ scopes=["https://www.googleapis.com/auth/drive"]
382
+ )
383
+ )
384
+ ```
385
+
386
+ **Note:** User account credentials support automatic refresh and caching.
387
+
388
+ ### 4. Service Account Impersonation
389
+
390
+ Impersonate a target service account using source credentials.
391
+
392
+ ```python
393
+ credentials = get_credentials(
394
+ settings=GoogleAuthSettings(
395
+ type="service_account",
396
+ service_account_file="~/source-sa-key.json",
397
+ impersonate_service_account="target-sa@project.iam.gserviceaccount.com",
398
+ scopes=["https://www.googleapis.com/auth/cloud-platform"]
399
+ )
400
+ )
401
+ ```
402
+
403
+ **Required IAM Role:** The source principal must have the `roles/iam.serviceAccountTokenCreator` role on the target service account.
404
+
405
+ ## Default Scopes
406
+
407
+ The library includes the following default scopes:
408
+
409
+ - `https://www.googleapis.com/auth/cloud-platform` - All GCP resources
410
+ - `https://www.googleapis.com/auth/drive` - Google Drive resources
411
+ - `https://www.googleapis.com/auth/spreadsheets` - Google Sheets resources
412
+
413
+ You can override these by specifying custom scopes in the configuration or function call.
414
+
415
+ ## Error Handling
416
+
417
+ ```python
418
+ from kiarina.lib.google.auth import get_credentials, GoogleAuthSettings
419
+
420
+ try:
421
+ credentials = get_credentials(
422
+ settings=GoogleAuthSettings(
423
+ type="service_account",
424
+ service_account_file="~/sa-key.json"
425
+ )
426
+ )
427
+ except ValueError as e:
428
+ print(f"Configuration error: {e}")
429
+ except FileNotFoundError as e:
430
+ print(f"Key file not found: {e}")
431
+ except Exception as e:
432
+ print(f"Authentication failed: {e}")
433
+ ```
434
+
435
+ ## Development
436
+
437
+ ### Prerequisites
438
+
439
+ - Python 3.12+
440
+
441
+ ### Setup
442
+
443
+ ```bash
444
+ # Clone the repository
445
+ git clone https://github.com/kiarina/kiarina-python.git
446
+ cd kiarina-python
447
+
448
+ # Setup development environment
449
+ mise run setup
450
+ ```
451
+
452
+ ### Running Tests
453
+
454
+ ```bash
455
+ # Run format, lint, type checks and tests
456
+ mise run package kiarina-lib-google-auth
457
+
458
+ # Coverage report
459
+ mise run package:test kiarina-lib-google-auth --coverage
460
+ ```
461
+
462
+ ### Test Configuration
463
+
464
+ Some tests require actual GCP credentials. Set the following environment variables:
465
+
466
+ ```bash
467
+ # Service account key file
468
+ export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_FILE="~/path/to/sa-key.json"
469
+
470
+ # Service account key data (JSON string)
471
+ export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_SA_KEY_DATA='{"type": "service_account", ...}'
472
+
473
+ # Authorized user file
474
+ export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_FILE="~/.config/gcloud/application_default_credentials.json"
475
+
476
+ # Authorized user data (JSON string)
477
+ export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_AUTHORIZED_USER_DATA='{"type": "authorized_user", ...}'
478
+
479
+ # Target service account for impersonation tests
480
+ export KIARINA_LIB_GOOGLE_AUTH_TEST_GCP_IMPERSONATE_SA="target-sa@project.iam.gserviceaccount.com"
481
+ ```
482
+
483
+ Tests will be skipped (xfail) if these environment variables are not set.
484
+
485
+ ## Dependencies
486
+
487
+ - [google-api-python-client](https://github.com/googleapis/google-api-python-client) - Google API client library
488
+ - [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) - Settings management
489
+ - [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Advanced settings management
490
+
491
+ ## License
492
+
493
+ This project is licensed under the MIT License - see the [LICENSE](../../LICENSE) file for details.
494
+
495
+ ## Contributing
496
+
497
+ This is a personal project, but contributions are welcome! Please feel free to submit issues or pull requests.
498
+
499
+ ## Related Projects
500
+
501
+ - [kiarina-python](https://github.com/kiarina/kiarina-python) - The main monorepo containing this package
502
+ - [pydantic-settings-manager](https://github.com/kiarina/pydantic-settings-manager) - Configuration management library used by this package