├── .coveragerc ├── .flake8 ├── .github ├── .OwlBot.lock.yaml ├── .OwlBot.yaml ├── CODEOWNERS ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── support_request.md ├── release-please.yml ├── release-trigger.yml └── sync-repo-settings.yaml ├── .gitignore ├── .kokoro ├── build-systests.sh ├── build.sh ├── common.cfg ├── continuous │ ├── common.cfg │ ├── continuous.cfg │ └── prerelease-deps.cfg ├── populate-secrets.sh ├── presubmit │ ├── common.cfg │ ├── prerelease-deps.cfg │ ├── presubmit.cfg │ └── system-3.7.cfg ├── samples-test-setup.sh ├── samples │ ├── lint │ │ ├── common.cfg │ │ ├── continuous.cfg │ │ ├── periodic.cfg │ │ └── presubmit.cfg │ ├── python3.10 │ │ ├── common.cfg │ │ ├── continuous.cfg │ │ ├── periodic-head.cfg │ │ ├── periodic.cfg │ │ └── presubmit.cfg │ ├── python3.11 │ │ ├── common.cfg │ │ ├── continuous.cfg │ │ ├── periodic-head.cfg │ │ ├── periodic.cfg │ │ └── presubmit.cfg │ ├── python3.12 │ │ ├── common.cfg │ │ ├── continuous.cfg │ │ ├── periodic-head.cfg │ │ ├── periodic.cfg │ │ └── presubmit.cfg │ ├── python3.13 │ │ ├── common.cfg │ │ ├── continuous.cfg │ │ ├── periodic-head.cfg │ │ ├── periodic.cfg │ │ └── presubmit.cfg │ ├── python3.7 │ │ ├── common.cfg │ │ ├── continuous.cfg │ │ ├── periodic-head.cfg │ │ ├── periodic.cfg │ │ └── presubmit.cfg │ ├── python3.8 │ │ ├── common.cfg │ │ ├── continuous.cfg │ │ ├── periodic-head.cfg │ │ ├── periodic.cfg │ │ └── presubmit.cfg │ └── python3.9 │ │ ├── common.cfg │ │ ├── continuous.cfg │ │ ├── periodic-head.cfg │ │ ├── periodic.cfg │ │ └── presubmit.cfg ├── test-samples-against-head.sh ├── test-samples-impl.sh ├── test-samples.sh ├── trampoline.sh └── trampoline_v2.sh ├── .readthedocs.yaml ├── .repo-metadata.json ├── .trampolinerc ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.rst ├── CONTRIBUTORS.md ├── LICENSE ├── MANIFEST.in ├── README.rst ├── SECURITY.md ├── docs ├── _static │ └── custom.css ├── conf.py ├── index.rst ├── oauth2client-deprecation.rst ├── reference │ ├── google.auth._credentials_async.rst │ ├── google.auth._jwt_async.rst │ ├── google.auth.app_engine.rst │ ├── google.auth.aws.rst │ ├── google.auth.compute_engine.credentials.rst │ ├── google.auth.compute_engine.rst │ ├── google.auth.credentials.rst │ ├── google.auth.crypt.base.rst │ ├── google.auth.crypt.es256.rst │ ├── google.auth.crypt.rsa.rst │ ├── google.auth.crypt.rst │ ├── google.auth.downscoped.rst │ ├── google.auth.environment_vars.rst │ ├── google.auth.exceptions.rst │ ├── google.auth.external_account.rst │ ├── google.auth.iam.rst │ ├── google.auth.identity_pool.rst │ ├── google.auth.impersonated_credentials.rst │ ├── google.auth.jwt.rst │ ├── google.auth.rst │ ├── google.auth.transport._aiohttp_requests.rst │ ├── google.auth.transport.grpc.rst │ ├── google.auth.transport.mtls.rst │ ├── google.auth.transport.requests.rst │ ├── google.auth.transport.rst │ ├── google.auth.transport.urllib3.rst │ ├── google.oauth2._credentials_async.rst │ ├── google.oauth2._service_account_async.rst │ ├── google.oauth2.credentials.rst │ ├── google.oauth2.id_token.rst │ ├── google.oauth2.rst │ ├── google.oauth2.service_account.rst │ ├── google.oauth2.sts.rst │ ├── google.oauth2.utils.rst │ ├── google.rst │ └── modules.rst ├── requirements-docs.txt └── user-guide.rst ├── google ├── auth │ ├── __init__.py │ ├── _cloud_sdk.py │ ├── _credentials_async.py │ ├── _credentials_base.py │ ├── _default.py │ ├── _default_async.py │ ├── _exponential_backoff.py │ ├── _helpers.py │ ├── _jwt_async.py │ ├── _oauth2client.py │ ├── _refresh_worker.py │ ├── _service_account_info.py │ ├── aio │ │ ├── __init__.py │ │ ├── _helpers.py │ │ ├── credentials.py │ │ └── transport │ │ │ ├── __init__.py │ │ │ ├── aiohttp.py │ │ │ └── sessions.py │ ├── api_key.py │ ├── app_engine.py │ ├── aws.py │ ├── compute_engine │ │ ├── __init__.py │ │ ├── _metadata.py │ │ └── credentials.py │ ├── credentials.py │ ├── crypt │ │ ├── __init__.py │ │ ├── _cryptography_rsa.py │ │ ├── _helpers.py │ │ ├── _python_rsa.py │ │ ├── base.py │ │ ├── es256.py │ │ └── rsa.py │ ├── downscoped.py │ ├── environment_vars.py │ ├── exceptions.py │ ├── external_account.py │ ├── external_account_authorized_user.py │ ├── iam.py │ ├── identity_pool.py │ ├── impersonated_credentials.py │ ├── jwt.py │ ├── metrics.py │ ├── pluggable.py │ ├── py.typed │ ├── transport │ │ ├── __init__.py │ │ ├── _aiohttp_requests.py │ │ ├── _custom_tls_signer.py │ │ ├── _http_client.py │ │ ├── _mtls_helper.py │ │ ├── _requests_base.py │ │ ├── grpc.py │ │ ├── mtls.py │ │ ├── requests.py │ │ └── urllib3.py │ └── version.py └── oauth2 │ ├── __init__.py │ ├── _client.py │ ├── _client_async.py │ ├── _credentials_async.py │ ├── _id_token_async.py │ ├── _reauth_async.py │ ├── _service_account_async.py │ ├── challenges.py │ ├── credentials.py │ ├── gdch_credentials.py │ ├── id_token.py │ ├── py.typed │ ├── reauth.py │ ├── service_account.py │ ├── sts.py │ ├── utils.py │ ├── webauthn_handler.py │ ├── webauthn_handler_factory.py │ └── webauthn_types.py ├── mypy.ini ├── noxfile.py ├── owlbot.py ├── renovate.json ├── samples └── cloud-client │ └── snippets │ ├── authenticate_explicit_with_adc.py │ ├── authenticate_implicit_with_adc.py │ ├── idtoken_from_impersonated_credentials.py │ ├── idtoken_from_metadata_server.py │ ├── idtoken_from_service_account.py │ ├── noxfile.py │ ├── noxfile_config.py │ ├── requirements.txt │ ├── snippets_test.py │ └── verify_google_idtoken.py ├── scripts ├── decrypt-secrets.sh ├── encrypt-secrets.sh ├── setup_external_accounts.sh └── travis.sh ├── setup.cfg ├── setup.py ├── system_tests ├── __init__.py ├── noxfile.py ├── secrets.tar.enc ├── system_tests_async │ ├── __init__.py │ ├── conftest.py │ ├── test_default.py │ ├── test_id_token.py │ └── test_service_account.py └── system_tests_sync │ ├── .gitignore │ ├── __init__.py │ ├── conftest.py │ ├── secrets.tar.enc │ ├── test_compute_engine.py │ ├── test_default.py │ ├── test_downscoping.py │ ├── test_external_accounts.py │ ├── test_grpc.py │ ├── test_id_token.py │ ├── test_impersonated_credentials.py │ ├── test_mtls_http.py │ ├── test_oauth2_credentials.py │ ├── test_requests.py │ ├── test_service_account.py │ └── test_urllib3.py ├── testing ├── constraints-3.10.txt ├── constraints-3.11.txt ├── constraints-3.12.txt ├── constraints-3.13.txt ├── constraints-3.7.txt ├── constraints-3.8.txt └── constraints-3.9.txt ├── tests ├── __init__.py ├── aio │ └── test__helpers.py ├── compute_engine │ ├── __init__.py │ ├── data │ │ ├── smbios_product_name │ │ └── smbios_product_name_non_google │ ├── test__metadata.py │ └── test_credentials.py ├── conftest.py ├── crypt │ ├── __init__.py │ ├── test__cryptography_rsa.py │ ├── test__python_rsa.py │ ├── test_crypt.py │ └── test_es256.py ├── data │ ├── authorized_user.json │ ├── authorized_user_cloud_sdk.json │ ├── authorized_user_cloud_sdk_with_quota_project_id.json │ ├── authorized_user_with_rapt_token.json │ ├── client_secrets.json │ ├── context_aware_metadata.json │ ├── enterprise_cert_invalid.json │ ├── enterprise_cert_valid.json │ ├── enterprise_cert_valid_provider.json │ ├── es256_privatekey.pem │ ├── es256_public_cert.pem │ ├── es256_publickey.pem │ ├── es256_service_account.json │ ├── external_account_authorized_user.json │ ├── external_account_authorized_user_non_gdu.json │ ├── external_subject_token.json │ ├── external_subject_token.txt │ ├── gdch_service_account.json │ ├── impersonated_service_account_authorized_user_source.json │ ├── impersonated_service_account_external_account_authorized_user_source.json │ ├── impersonated_service_account_service_account_source.json │ ├── impersonated_service_account_with_quota_project.json │ ├── old_oauth_credentials_py3.pickle │ ├── other_cert.pem │ ├── pem_from_pkcs12.pem │ ├── privatekey.p12 │ ├── privatekey.pem │ ├── privatekey.pub │ ├── public_cert.pem │ ├── service_account.json │ ├── service_account_non_gdu.json │ ├── trust_chain_with_leaf.pem │ ├── trust_chain_without_leaf.pem │ └── trust_chain_wrong_order.pem ├── oauth2 │ ├── __init__.py │ ├── test__client.py │ ├── test_challenges.py │ ├── test_credentials.py │ ├── test_gdch_credentials.py │ ├── test_id_token.py │ ├── test_reauth.py │ ├── test_service_account.py │ ├── test_sts.py │ ├── test_utils.py │ ├── test_webauthn_handler.py │ ├── test_webauthn_handler_factory.py │ └── test_webauthn_types.py ├── test__cloud_sdk.py ├── test__default.py ├── test__exponential_backoff.py ├── test__helpers.py ├── test__oauth2client.py ├── test__refresh_worker.py ├── test__service_account_info.py ├── test_api_key.py ├── test_app_engine.py ├── test_aws.py ├── test_credentials.py ├── test_credentials_async.py ├── test_downscoped.py ├── test_exceptions.py ├── test_external_account.py ├── test_external_account_authorized_user.py ├── test_iam.py ├── test_identity_pool.py ├── test_impersonated_credentials.py ├── test_jwt.py ├── test_metrics.py ├── test_packaging.py ├── test_pluggable.py └── transport │ ├── __init__.py │ ├── aio │ ├── test_aiohttp.py │ └── test_sessions.py │ ├── compliance.py │ ├── test__custom_tls_signer.py │ ├── test__http_client.py │ ├── test__mtls_helper.py │ ├── test_grpc.py │ ├── test_mtls.py │ ├── test_requests.py │ └── test_urllib3.py └── tests_async ├── __init__.py ├── conftest.py ├── oauth2 ├── test__client_async.py ├── test_credentials_async.py ├── test_id_token.py ├── test_reauth_async.py └── test_service_account_async.py ├── test__default_async.py ├── test_credentials_async.py ├── test_jwt_async.py └── transport ├── __init__.py ├── async_compliance.py └── test_aiohttp_requests.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | 4 | [report] 5 | omit = 6 | */samples/* 7 | */conftest.py 8 | */google-cloud-sdk/lib/* 9 | # NOTE: Temporarily disabling coverage for `_requests_base.py`. 10 | */_requests_base.py 11 | exclude_lines = 12 | # Re-enable the standard pragma 13 | pragma: NO COVER 14 | # Ignore debug-only repr 15 | def __repr__ 16 | # Don't complain if tests don't hit defensive assertion code: 17 | raise NotImplementedError 18 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E203, E266, E501, W503 3 | exclude = 4 | # Standard linting exemptions. 5 | __pycache__, 6 | .git, 7 | *.pyc, 8 | conf.py 9 | -------------------------------------------------------------------------------- /.github/.OwlBot.lock.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | docker: 15 | image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest 16 | digest: sha256:023a21377a2a00008057f99f0118edadc30a19d1636a3fee47189ebec2f3921c 17 | # created: 2025-03-31T16:51:40.130756953Z 18 | -------------------------------------------------------------------------------- /.github/.OwlBot.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | docker: 16 | image: gcr.io/cloud-devrel-public-resources/owlbot-python:latest 17 | 18 | begin-after-commit-hash: ee56c3493ec6aeb237ff515ecea949710944a20f 19 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners file. 2 | # This file controls who is tagged for review for any given pull request. 3 | # 4 | # For syntax help see: 5 | # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax 6 | 7 | # The @googleapis/googleapis-auth and @googleapis/yoshi-python is the default owner for changes in this repo 8 | * @googleapis/googleapis-auth @googleapis/yoshi-python 9 | google/auth/_default.py @googleapis/googleapis-auth @googleapis/aion-sdk 10 | google/auth/aws.py @googleapis/googleapis-auth @googleapis/aion-sdk 11 | google/auth/credentials.py @googleapis/googleapis-auth @googleapis/aion-sdk 12 | google/auth/downscoped.py @googleapis/googleapis-auth @googleapis/aion-sdk 13 | google/auth/external_account.py @googleapis/googleapis-auth @googleapis/aion-sdk 14 | google/auth/external_account_authorized_user.py @googleapis/googleapis-auth @googleapis/aion-sdk 15 | google/auth/identity_pool.py @googleapis/googleapis-auth @googleapis/aion-sdk 16 | google/auth/pluggable.py @googleapis/googleapis-auth @googleapis/aion-sdk 17 | google/auth/sts.py @googleapis/googleapis-auth @googleapis/aion-sdk 18 | google/auth/impersonated_credentials.py @googleapis/googleapis-auth @googleapis/aion-sdk 19 | tests/test__default.py @googleapis/googleapis-auth @googleapis/aion-sdk 20 | tests/test_aws.py @googleapis/googleapis-auth @googleapis/aion-sdk 21 | tests/test_credentials.py @googleapis/googleapis-auth @googleapis/aion-sdk 22 | tests/test_downscoped.py @googleapis/googleapis-auth @googleapis/aion-sdk 23 | tests/test_external_account.py @googleapis/googleapis-auth @googleapis/aion-sdk 24 | tests/test_external_account_authorized_user.py @googleapis/googleapis-auth @googleapis/aion-sdk 25 | tests/test_identity_pool.py @googleapis/googleapis-auth @googleapis/aion-sdk 26 | tests/test_pluggable.py @googleapis/googleapis-auth @googleapis/aion-sdk 27 | tests/test_sts.py @googleapis/googleapis-auth @googleapis/aion-sdk 28 | tests/test_impersonated_credentials.py @googleapis/googleapis-auth @googleapis/aion-sdk 29 | /samples/ @googleapis/googleapis-auth @googleapis/aion-sdk @googleapis/python-samples-owners 30 | system_tests/secrets.tar.enc # Remove noise from test creds. 31 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google.com/conduct/). 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | Thanks for stopping by to let us know something could be better! 8 | 9 | **PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. 10 | 11 | Please run down the following list and make sure you've tried the usual "quick fixes": 12 | 13 | - Search the issues already opened: https://github.com/googleapis/google-auth-library-python/issues 14 | 15 | If you are still having issues, please be sure to include as much information as possible: 16 | 17 | #### Environment details 18 | 19 | - OS: 20 | - Python version: 21 | - pip version: 22 | - `google-auth` version: 23 | 24 | #### Steps to reproduce 25 | 26 | 1. ? 27 | 2. ? 28 | 29 | Making sure to follow these steps will guarantee the quickest resolution possible. 30 | 31 | Thanks! 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this library 4 | 5 | --- 6 | 7 | Thanks for stopping by to let us know something could be better! 8 | 9 | **PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. 10 | 11 | **Is your feature request related to a problem? Please describe.** 12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | **Additional context** 18 | Add any other context or screenshots about the feature request here. 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/support_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Support request 3 | about: If you have a support contract with Google, please create an issue in the Google Cloud Support console. 4 | 5 | --- 6 | 7 | **PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. 8 | -------------------------------------------------------------------------------- /.github/release-please.yml: -------------------------------------------------------------------------------- 1 | releaseType: python 2 | handleGHRelease: true 3 | -------------------------------------------------------------------------------- /.github/release-trigger.yml: -------------------------------------------------------------------------------- 1 | enabled: true 2 | -------------------------------------------------------------------------------- /.github/sync-repo-settings.yaml: -------------------------------------------------------------------------------- 1 | # https://github.com/googleapis/repo-automation-bots/tree/main/packages/sync-repo-settings 2 | # Rules for main branch protection 3 | branchProtectionRules: 4 | # Identifies the protection rule pattern. Name of the branch to be protected. 5 | # Defaults to `main` 6 | - pattern: main 7 | requiresCodeOwnerReviews: true 8 | requiresStrictStatusChecks: true 9 | requiredStatusCheckContexts: 10 | - 'cla/google' 11 | - 'OwlBot Post Processor' 12 | - 'Kokoro system-3.7' 13 | - 'Kokoro' 14 | - 'Samples - Python 3.7' 15 | - 'Samples - Python 3.8' 16 | - 'Samples - Python 3.9' 17 | - 'Samples - Python 3.10' 18 | - 'Samples - Python 3.11' 19 | - 'Samples - Python 3.12' 20 | permissionRules: 21 | - team: actools-python 22 | permission: admin 23 | - team: actools 24 | permission: admin 25 | - team: yoshi-python 26 | permission: push 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build artifacts 2 | *.py[cod] 3 | __pycache__ 4 | *.egg-info/ 5 | build/ 6 | dist/ 7 | 8 | # Documentation-related 9 | docs/_build 10 | 11 | # Test files 12 | .nox/ 13 | .tox/ 14 | .cache/ 15 | .pytest_cache/ 16 | cert_path 17 | key_path 18 | 19 | # Django test database 20 | db.sqlite3 21 | 22 | # Coverage files 23 | .coverage 24 | coverage.xml 25 | *sponge_log.xml 26 | nosetests.xml 27 | htmlcov/ 28 | 29 | # Files with private / local data 30 | scripts/local_test_setup 31 | tests/data/key.json 32 | tests/data/key.p12 33 | tests/data/user-key.json 34 | system_tests/data/ 35 | 36 | # PyCharm configuration: 37 | .idea 38 | venv/ 39 | 40 | # Generated files 41 | pylintrc 42 | pylintrc.test 43 | pytype_output/ 44 | 45 | .python-version 46 | .DS_Store 47 | cert_path 48 | key_path 49 | env/ 50 | .vscode/ -------------------------------------------------------------------------------- /.kokoro/build-systests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | 18 | if [[ -z "${PROJECT_ROOT:-}" ]]; then 19 | PROJECT_ROOT="github/google-auth-library-python" 20 | fi 21 | 22 | cd "${PROJECT_ROOT}" 23 | 24 | # Disable buffering, so that the logs stream through. 25 | export PYTHONUNBUFFERED=1 26 | 27 | # Remove old nox 28 | python3 -m pip uninstall --yes --quiet nox-automation 29 | 30 | # Install nox 31 | python3 -m pip install nox==2024.10.9 32 | python3 -m nox --version 33 | 34 | # Setup service account credentials. 35 | export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json 36 | 37 | # Setup project id. 38 | export PROJECT_ID=$(cat "${KOKORO_GFILE_DIR}/project-id.txt") 39 | 40 | # Activate gcloud with service account credentials 41 | gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS 42 | gcloud config set project ${PROJECT_ID} 43 | 44 | # Decrypt system test secrets 45 | ./scripts/decrypt-secrets.sh 46 | 47 | # Run system tests which use a different noxfile 48 | python3 -m nox -f system_tests/noxfile.py 49 | -------------------------------------------------------------------------------- /.kokoro/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | 18 | if [[ -z "${PROJECT_ROOT:-}" ]]; then 19 | PROJECT_ROOT="github/google-auth-library-python" 20 | fi 21 | 22 | cd "${PROJECT_ROOT}" 23 | 24 | # Disable buffering, so that the logs stream through. 25 | export PYTHONUNBUFFERED=1 26 | 27 | # Remove old nox 28 | python3 -m pip uninstall --yes --quiet nox-automation 29 | 30 | # Install nox 31 | python3 -m pip install --upgrade --quiet nox 32 | python3 -m nox --version 33 | 34 | # If NOX_SESSION is set, it only runs the specified session, 35 | # otherwise run all the sessions. 36 | if [[ -n "${NOX_SESSION:-}" ]]; then 37 | python3 -m nox -s ${NOX_SESSION:-} 38 | else 39 | python3 -m nox 40 | fi 41 | -------------------------------------------------------------------------------- /.kokoro/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Download trampoline resources. These will be in ${KOKORO_GFILE_DIR} 4 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 5 | 6 | # Download resources for tests 7 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 8 | 9 | # All builds use the trampoline script to run in docker. 10 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 11 | 12 | # Use the Python worker docker iamge. 13 | env_vars: { 14 | key: "TRAMPOLINE_IMAGE" 15 | value: "gcr.io/cloud-devrel-public-resources/python-multi" 16 | } 17 | -------------------------------------------------------------------------------- /.kokoro/continuous/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Download resources for system tests (service account key, etc.) 14 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 15 | 16 | # Use the trampoline script to run in docker. 17 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 18 | 19 | # Configure the docker image for kokoro-trampoline. 20 | env_vars: { 21 | key: "TRAMPOLINE_IMAGE" 22 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 23 | } 24 | env_vars: { 25 | key: "TRAMPOLINE_BUILD_FILE" 26 | value: "github/google-auth-library-python/.kokoro/build.sh" 27 | } 28 | -------------------------------------------------------------------------------- /.kokoro/continuous/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto -------------------------------------------------------------------------------- /.kokoro/continuous/prerelease-deps.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Only run this nox session. 4 | env_vars: { 5 | key: "NOX_SESSION" 6 | value: "prerelease_deps" 7 | } 8 | -------------------------------------------------------------------------------- /.kokoro/populate-secrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2024 Google LLC. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | 18 | function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;} 19 | function msg { println "$*" >&2 ;} 20 | function println { printf '%s\n' "$(now) $*" ;} 21 | 22 | 23 | # Populates requested secrets set in SECRET_MANAGER_KEYS from service account: 24 | # kokoro-trampoline@cloud-devrel-kokoro-resources.iam.gserviceaccount.com 25 | SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" 26 | msg "Creating folder on disk for secrets: ${SECRET_LOCATION}" 27 | mkdir -p ${SECRET_LOCATION} 28 | for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g") 29 | do 30 | msg "Retrieving secret ${key}" 31 | docker run --entrypoint=gcloud \ 32 | --volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR} \ 33 | gcr.io/google.com/cloudsdktool/cloud-sdk \ 34 | secrets versions access latest \ 35 | --project cloud-devrel-kokoro-resources \ 36 | --secret ${key} > \ 37 | "${SECRET_LOCATION}/${key}" 38 | if [[ $? == 0 ]]; then 39 | msg "Secret written to ${SECRET_LOCATION}/${key}" 40 | else 41 | msg "Error retrieving secret ${key}" 42 | fi 43 | done 44 | -------------------------------------------------------------------------------- /.kokoro/presubmit/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Download trampoline resources. 11 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 12 | 13 | # Download resources for system tests (service account key, etc.) 14 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 15 | 16 | # Use the trampoline script to run in docker. 17 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 18 | 19 | # Configure the docker image for kokoro-trampoline. 20 | env_vars: { 21 | key: "TRAMPOLINE_IMAGE" 22 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 23 | } 24 | env_vars: { 25 | key: "TRAMPOLINE_BUILD_FILE" 26 | value: "github/google-auth-library-python/.kokoro/build.sh" 27 | } 28 | -------------------------------------------------------------------------------- /.kokoro/presubmit/prerelease-deps.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Only run this nox session. 4 | env_vars: { 5 | key: "NOX_SESSION" 6 | value: "prerelease_deps" 7 | } 8 | -------------------------------------------------------------------------------- /.kokoro/presubmit/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto -------------------------------------------------------------------------------- /.kokoro/presubmit/system-3.7.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | env_vars: { 3 | key: "TRAMPOLINE_BUILD_FILE" 4 | value: "github/google-auth-library-python/.kokoro/build-systests.sh" 5 | } 6 | -------------------------------------------------------------------------------- /.kokoro/samples-test-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | 18 | if [[ -z "${PROJECT_ROOT:-}" ]]; then 19 | PROJECT_ROOT="github/google-auth-library-python" 20 | fi 21 | 22 | cd "${PROJECT_ROOT}" 23 | 24 | # Disable buffering, so that the logs stream through. 25 | export PYTHONUNBUFFERED=1 26 | 27 | # Remove old nox 28 | python3 -m pip uninstall --yes --quiet nox-automation 29 | 30 | # Install nox 31 | python3 -m pip install --upgrade --quiet nox 32 | python3 -m nox --version 33 | 34 | # Setup service account credentials. 35 | export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json 36 | 37 | # Setup project id. 38 | export PROJECT_ID=$(cat "${KOKORO_GFILE_DIR}/project-id.txt") 39 | 40 | # Activate gcloud with service account credentials 41 | gcloud auth activate-service-account --key-file=$GOOGLE_APPLICATION_CREDENTIALS 42 | gcloud config set project ${PROJECT_ID} 43 | 44 | # Decrypt system test secrets 45 | ./scripts/decrypt-secrets.sh 46 | 47 | # Run samples tests which use a different noxfile 48 | python3 -m nox -f samples/cloud-client/snippets/noxfile.py -s "$RUN_TESTS_SESSION" 49 | -------------------------------------------------------------------------------- /.kokoro/samples/lint/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Specify which tests to run 11 | env_vars: { 12 | key: "RUN_TESTS_SESSION" 13 | value: "lint" 14 | } 15 | 16 | 17 | # Download trampoline resources. 18 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 19 | 20 | # Download resources for system tests (service account key, etc.) 21 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 22 | 23 | # Use the trampoline script to run in docker. 24 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 25 | 26 | # Configure the docker image for kokoro-trampoline. 27 | env_vars: { 28 | key: "TRAMPOLINE_IMAGE" 29 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 30 | } 31 | env_vars: { 32 | key: "TRAMPOLINE_BUILD_FILE" 33 | value: "github/google-auth-library-python/.kokoro/build.sh" 34 | } 35 | env_vars: { 36 | key: "TRAMPOLINE_BUILD_FILE" 37 | value: "github/google-auth-library-python/.kokoro/samples-test-setup.sh" 38 | } -------------------------------------------------------------------------------- /.kokoro/samples/lint/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/lint/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "False" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/lint/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.10/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Specify which tests to run 11 | env_vars: { 12 | key: "RUN_TESTS_SESSION" 13 | value: "unit-3.10" 14 | } 15 | 16 | # Download trampoline resources. 17 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 18 | 19 | # Download resources for system tests (service account key, etc.) 20 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 21 | 22 | # Use the trampoline script to run in docker. 23 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 24 | 25 | # Configure the docker image for kokoro-trampoline. 26 | env_vars: { 27 | key: "TRAMPOLINE_IMAGE" 28 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 29 | } 30 | env_vars: { 31 | key: "TRAMPOLINE_BUILD_FILE" 32 | value: "github/google-auth-library-python/.kokoro/build.sh" 33 | } 34 | env_vars: { 35 | key: "TRAMPOLINE_BUILD_FILE" 36 | value: "github/google-auth-library-python/.kokoro/samples-test-setup.sh" 37 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.10/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.10/periodic-head.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } 7 | 8 | env_vars: { 9 | key: "TRAMPOLINE_BUILD_FILE" 10 | value: "github/google-auth-library-python/.kokoro/test-samples-against-head.sh" 11 | } 12 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.10/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "False" 6 | } 7 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.10/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.11/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Specify which tests to run 11 | env_vars: { 12 | key: "RUN_TESTS_SESSION" 13 | value: "unit-3.11" 14 | } 15 | 16 | # Download trampoline resources. 17 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 18 | 19 | # Download resources for system tests (service account key, etc.) 20 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 21 | 22 | # Use the trampoline script to run in docker. 23 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 24 | 25 | # Configure the docker image for kokoro-trampoline. 26 | env_vars: { 27 | key: "TRAMPOLINE_IMAGE" 28 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 29 | } 30 | env_vars: { 31 | key: "TRAMPOLINE_BUILD_FILE" 32 | value: "github/google-auth-library-python/.kokoro/build.sh" 33 | } 34 | env_vars: { 35 | key: "TRAMPOLINE_BUILD_FILE" 36 | value: "github/google-auth-library-python/.kokoro/samples-test-setup.sh" 37 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.11/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.11/periodic-head.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } 7 | 8 | env_vars: { 9 | key: "TRAMPOLINE_BUILD_FILE" 10 | value: "github/google-auth-library-python/.kokoro/test-samples-against-head.sh" 11 | } 12 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.11/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "False" 6 | } 7 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.11/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.12/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Specify which tests to run 11 | env_vars: { 12 | key: "RUN_TESTS_SESSION" 13 | value: "unit-3.12" 14 | } 15 | 16 | # Download trampoline resources. 17 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 18 | 19 | # Download resources for system tests (service account key, etc.) 20 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 21 | 22 | # Use the trampoline script to run in docker. 23 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 24 | 25 | # Configure the docker image for kokoro-trampoline. 26 | env_vars: { 27 | key: "TRAMPOLINE_IMAGE" 28 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 29 | } 30 | env_vars: { 31 | key: "TRAMPOLINE_BUILD_FILE" 32 | value: "github/google-auth-library-python/.kokoro/build.sh" 33 | } 34 | env_vars: { 35 | key: "TRAMPOLINE_BUILD_FILE" 36 | value: "github/google-auth-library-python/.kokoro/samples-test-setup.sh" 37 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.12/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.12/periodic-head.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } 7 | 8 | env_vars: { 9 | key: "TRAMPOLINE_BUILD_FILE" 10 | value: "github/google-auth-library-python/.kokoro/test-samples-against-head.sh" 11 | } 12 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.12/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "False" 6 | } 7 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.12/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.13/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Specify which tests to run 11 | env_vars: { 12 | key: "RUN_TESTS_SESSION" 13 | value: "unit-3.13" 14 | } 15 | 16 | # Download trampoline resources. 17 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 18 | 19 | # Download resources for system tests (service account key, etc.) 20 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 21 | 22 | # Use the trampoline script to run in docker. 23 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 24 | 25 | # Configure the docker image for kokoro-trampoline. 26 | env_vars: { 27 | key: "TRAMPOLINE_IMAGE" 28 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 29 | } 30 | env_vars: { 31 | key: "TRAMPOLINE_BUILD_FILE" 32 | value: "github/google-auth-library-python/.kokoro/build.sh" 33 | } 34 | env_vars: { 35 | key: "TRAMPOLINE_BUILD_FILE" 36 | value: "github/google-auth-library-python/.kokoro/samples-test-setup.sh" 37 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.13/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.13/periodic-head.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } 7 | 8 | env_vars: { 9 | key: "TRAMPOLINE_BUILD_FILE" 10 | value: "github/google-auth-library-python/.kokoro/test-samples-against-head.sh" 11 | } 12 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.13/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "False" 6 | } 7 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.13/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.7/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | 11 | # Specify which tests to run 12 | env_vars: { 13 | key: "RUN_TESTS_SESSION" 14 | value: "unit-3.7" 15 | } 16 | 17 | # Download trampoline resources. 18 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 19 | 20 | # Download resources for system tests (service account key, etc.) 21 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 22 | 23 | # Use the trampoline script to run in docker. 24 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 25 | 26 | # Configure the docker image for kokoro-trampoline. 27 | env_vars: { 28 | key: "TRAMPOLINE_IMAGE" 29 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 30 | } 31 | env_vars: { 32 | key: "TRAMPOLINE_BUILD_FILE" 33 | value: "github/google-auth-library-python/.kokoro/build.sh" 34 | } 35 | env_vars: { 36 | key: "TRAMPOLINE_BUILD_FILE" 37 | value: "github/google-auth-library-python/.kokoro/samples-test-setup.sh" 38 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.7/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.7/periodic-head.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } 7 | 8 | env_vars: { 9 | key: "TRAMPOLINE_BUILD_FILE" 10 | value: "github/google-auth-library-python/.kokoro/test-samples-against-head.sh" 11 | } 12 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.7/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "False" 6 | } 7 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.7/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.8/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Specify which tests to run 11 | env_vars: { 12 | key: "RUN_TESTS_SESSION" 13 | value: "unit-3.8" 14 | } 15 | 16 | # Download trampoline resources. 17 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 18 | 19 | # Download resources for system tests (service account key, etc.) 20 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 21 | 22 | # Use the trampoline script to run in docker. 23 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 24 | 25 | # Configure the docker image for kokoro-trampoline. 26 | env_vars: { 27 | key: "TRAMPOLINE_IMAGE" 28 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 29 | } 30 | env_vars: { 31 | key: "TRAMPOLINE_BUILD_FILE" 32 | value: "github/google-auth-library-python/.kokoro/build.sh" 33 | } 34 | env_vars: { 35 | key: "TRAMPOLINE_BUILD_FILE" 36 | value: "github/google-auth-library-python/.kokoro/samples-test-setup.sh" 37 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.8/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.8/periodic-head.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } 7 | 8 | env_vars: { 9 | key: "TRAMPOLINE_BUILD_FILE" 10 | value: "github/google-auth-library-python/.kokoro/test-samples-against-head.sh" 11 | } 12 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.8/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "False" 6 | } 7 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.8/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.9/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | } 8 | } 9 | 10 | # Specify which tests to run 11 | env_vars: { 12 | key: "RUN_TESTS_SESSION" 13 | value: "unit-3.9" 14 | } 15 | 16 | # Download trampoline resources. 17 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 18 | 19 | # Download resources for system tests (service account key, etc.) 20 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-auth-library-python" 21 | 22 | # Use the trampoline script to run in docker. 23 | build_file: "google-auth-library-python/.kokoro/trampoline.sh" 24 | 25 | # Configure the docker image for kokoro-trampoline. 26 | env_vars: { 27 | key: "TRAMPOLINE_IMAGE" 28 | value: "gcr.io/cloud-devrel-kokoro-resources/python-multi" 29 | } 30 | env_vars: { 31 | key: "TRAMPOLINE_BUILD_FILE" 32 | value: "github/google-auth-library-python/.kokoro/build.sh" 33 | } 34 | env_vars: { 35 | key: "TRAMPOLINE_BUILD_FILE" 36 | value: "github/google-auth-library-python/.kokoro/samples-test-setup.sh" 37 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.9/continuous.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/samples/python3.9/periodic-head.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } 7 | 8 | env_vars: { 9 | key: "TRAMPOLINE_BUILD_FILE" 10 | value: "github/google-auth-library-python/.kokoro/test-samples-against-head.sh" 11 | } 12 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.9/periodic.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "False" 6 | } 7 | -------------------------------------------------------------------------------- /.kokoro/samples/python3.9/presubmit.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | env_vars: { 4 | key: "INSTALL_LIBRARY_FROM_SOURCE" 5 | value: "True" 6 | } -------------------------------------------------------------------------------- /.kokoro/test-samples-against-head.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2024 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # A customized test runner for samples. 17 | # 18 | # For periodic builds, you can specify this file for testing against head. 19 | 20 | # `-e` enables the script to automatically fail when a command fails 21 | # `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero 22 | set -eo pipefail 23 | # Enables `**` to include files nested inside sub-folders 24 | shopt -s globstar 25 | 26 | exec .kokoro/test-samples-impl.sh 27 | -------------------------------------------------------------------------------- /.kokoro/test-samples.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2024 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # The default test runner for samples. 17 | # 18 | # For periodic builds, we rewinds the repo to the latest release, and 19 | # run test-samples-impl.sh. 20 | 21 | # `-e` enables the script to automatically fail when a command fails 22 | # `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero 23 | set -eo pipefail 24 | # Enables `**` to include files nested inside sub-folders 25 | shopt -s globstar 26 | 27 | # Run periodic samples tests at latest release 28 | if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"periodic"* ]]; then 29 | # preserving the test runner implementation. 30 | cp .kokoro/test-samples-impl.sh "${TMPDIR}/test-samples-impl.sh" 31 | echo "--- IMPORTANT IMPORTANT IMPORTANT ---" 32 | echo "Now we rewind the repo back to the latest release..." 33 | LATEST_RELEASE=$(git describe --abbrev=0 --tags) 34 | git checkout $LATEST_RELEASE 35 | echo "The current head is: " 36 | echo $(git rev-parse --verify HEAD) 37 | echo "--- IMPORTANT IMPORTANT IMPORTANT ---" 38 | # move back the test runner implementation if there's no file. 39 | if [ ! -f .kokoro/test-samples-impl.sh ]; then 40 | cp "${TMPDIR}/test-samples-impl.sh" .kokoro/test-samples-impl.sh 41 | fi 42 | fi 43 | 44 | exec .kokoro/test-samples-impl.sh 45 | -------------------------------------------------------------------------------- /.kokoro/trampoline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2024 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | 18 | # Always run the cleanup script, regardless of the success of bouncing into 19 | # the container. 20 | function cleanup() { 21 | chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh 22 | ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh 23 | echo "cleanup"; 24 | } 25 | trap cleanup EXIT 26 | 27 | $(dirname $0)/populate-secrets.sh # Secret Manager secrets. 28 | python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the OS, Python version, and other tools you might need 8 | build: 9 | os: ubuntu-24.04 10 | tools: 11 | python: "3.10" 12 | 13 | # Build documentation in the "docs/" directory with Sphinx 14 | sphinx: 15 | configuration: docs/conf.py 16 | 17 | python: 18 | install: 19 | - requirements: docs/requirements-docs.txt 20 | # Install our python package before building the docs 21 | - method: pip 22 | path: . 23 | -------------------------------------------------------------------------------- /.repo-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-auth", 3 | "name_pretty": "Google Auth Python Library", 4 | "client_documentation": "https://googleapis.dev/python/google-auth/latest", 5 | "issue_tracker": "https://github.com/googleapis/google-auth-library-python/issues", 6 | "release_level": "stable", 7 | "language": "python", 8 | "library_type": "AUTH", 9 | "repo": "googleapis/google-auth-library-python", 10 | "distribution_name": "google-auth" 11 | } 12 | -------------------------------------------------------------------------------- /.trampolinerc: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Add required env vars here. 16 | required_envvars+=( 17 | ) 18 | 19 | # Add env vars which are passed down into the container here. 20 | pass_down_envvars+=( 21 | "NOX_SESSION" 22 | ############### 23 | # Docs builds 24 | ############### 25 | "STAGING_BUCKET" 26 | "V2_STAGING_BUCKET" 27 | ################## 28 | # Samples builds 29 | ################## 30 | "INSTALL_LIBRARY_FROM_SOURCE" 31 | "RUN_TESTS_SESSION" 32 | "BUILD_SPECIFIC_GCLOUD_PROJECT" 33 | # Target directories. 34 | "RUN_TESTS_DIRS" 35 | # The nox session to run. 36 | "RUN_TESTS_SESSION" 37 | ) 38 | 39 | # Prevent unintentional override on the default image. 40 | if [[ "${TRAMPOLINE_IMAGE_UPLOAD:-false}" == "true" ]] && \ 41 | [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then 42 | echo "Please set TRAMPOLINE_IMAGE if you want to upload the Docker image." 43 | exit 1 44 | fi 45 | 46 | # Define the default value if it makes sense. 47 | if [[ -z "${TRAMPOLINE_IMAGE_UPLOAD:-}" ]]; then 48 | TRAMPOLINE_IMAGE_UPLOAD="" 49 | fi 50 | 51 | if [[ -z "${TRAMPOLINE_IMAGE:-}" ]]; then 52 | TRAMPOLINE_IMAGE="" 53 | fi 54 | 55 | if [[ -z "${TRAMPOLINE_DOCKERFILE:-}" ]]; then 56 | TRAMPOLINE_DOCKERFILE="" 57 | fi 58 | 59 | if [[ -z "${TRAMPOLINE_BUILD_FILE:-}" ]]; then 60 | TRAMPOLINE_BUILD_FILE="" 61 | fi 62 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, 4 | and in the interest of fostering an open and welcoming community, 5 | we pledge to respect all people who contribute through reporting issues, 6 | posting feature requests, updating documentation, 7 | submitting pull requests or patches, and other activities. 8 | 9 | We are committed to making participation in this project 10 | a harassment-free experience for everyone, 11 | regardless of level of experience, gender, gender identity and expression, 12 | sexual orientation, disability, personal appearance, 13 | body size, race, ethnicity, age, religion, or nationality. 14 | 15 | Examples of unacceptable behavior by participants include: 16 | 17 | * The use of sexualized language or imagery 18 | * Personal attacks 19 | * Trolling or insulting/derogatory comments 20 | * Public or private harassment 21 | * Publishing other's private information, 22 | such as physical or electronic 23 | addresses, without explicit permission 24 | * Other unethical or unprofessional conduct. 25 | 26 | Project maintainers have the right and responsibility to remove, edit, or reject 27 | comments, commits, code, wiki edits, issues, and other contributions 28 | that are not aligned to this Code of Conduct. 29 | By adopting this Code of Conduct, 30 | project maintainers commit themselves to fairly and consistently 31 | applying these principles to every aspect of managing this project. 32 | Project maintainers who do not follow or enforce the Code of Conduct 33 | may be permanently removed from the project team. 34 | 35 | This code of conduct applies both within project spaces and in public spaces 36 | when an individual is representing the project or its community. 37 | 38 | Instances of abusive, harassing, or otherwise unacceptable behavior 39 | may be reported by opening an issue 40 | or contacting one or more of the project maintainers. 41 | 42 | This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, 43 | available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) 44 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst LICENSE CHANGELOG.rst 2 | recursive-include tests * 3 | global-exclude *.pyc __pycache__ 4 | global-include *.typed 5 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Google Auth Python Library 2 | ========================== 3 | 4 | |pypi| 5 | 6 | This library simplifies using Google's various server-to-server authentication 7 | mechanisms to access Google APIs. 8 | 9 | .. |pypi| image:: https://img.shields.io/pypi/v/google-auth.svg 10 | :target: https://pypi.python.org/pypi/google-auth 11 | 12 | Installing 13 | ---------- 14 | 15 | You can install using `pip`_:: 16 | 17 | $ pip install google-auth 18 | 19 | .. _pip: https://pip.pypa.io/en/stable/ 20 | 21 | For more information on setting up your Python development environment, please refer to `Python Development Environment Setup Guide`_ for Google Cloud Platform. 22 | 23 | .. _`Python Development Environment Setup Guide`: https://cloud.google.com/python/docs/setup 24 | 25 | Extras 26 | ------ 27 | 28 | google-auth has few extras that you can install. For example:: 29 | 30 | $ pip install google-auth[pyopenssl] 31 | 32 | Note that the extras pyopenssl and enterprise_cert should not be used together because they use conflicting versions of `cryptography`_. 33 | 34 | .. _`cryptography`: https://cryptography.io/en/latest/ 35 | 36 | Supported Python Versions 37 | ^^^^^^^^^^^^^^^^^^^^^^^^^ 38 | Python >= 3.7 39 | 40 | **NOTE**: 41 | Python 3.7 was marked as `unsupported`_ by the python community in June 2023. 42 | We recommend that all developers upgrade to Python 3.8 and newer as soon as 43 | they can. Support for Python 3.7 will be removed from this library after 44 | January 1 2024. Previous releases that support Python 3.7 will continue to be available 45 | for download, but releases after January 1 2024 will only target Python 3.8 and 46 | newer. 47 | 48 | .. _unsupported: https://devguide.python.org/versions/#unsupported-versions 49 | 50 | Unsupported Python Versions 51 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 52 | - Python == 2.7: The last version of this library with support for Python 2.7 53 | was `google.auth == 1.34.0`. 54 | 55 | - Python 3.5: The last version of this library with support for Python 3.5 56 | was `google.auth == 1.23.0`. 57 | 58 | - Python 3.6: The last version of this library with support for Python 3.6 59 | was `google.auth == 2.22.0`. 60 | 61 | Documentation 62 | ------------- 63 | 64 | Google Auth Python Library has usage and reference documentation at https://googleapis.dev/python/google-auth/latest/index.html. 65 | 66 | Current Maintainers 67 | ------------------- 68 | - googleapis-auth@google.com 69 | 70 | Authors 71 | ------- 72 | 73 | - `@theacodes `_ (Thea Flowers) 74 | - `@dhermes `_ (Danny Hermes) 75 | - `@lukesneeringer `_ (Luke Sneeringer) 76 | - `@busunkim96 `_ (Bu Sun Kim) 77 | 78 | Contributing 79 | ------------ 80 | 81 | Contributions to this library are always welcome and highly encouraged. 82 | 83 | See `CONTRIBUTING.rst`_ for more information on how to get started. 84 | 85 | .. _CONTRIBUTING.rst: https://github.com/googleapis/google-auth-library-python/blob/main/CONTRIBUTING.rst 86 | 87 | License 88 | ------- 89 | 90 | Apache 2.0 - See `the LICENSE`_ for more information. 91 | 92 | .. _the LICENSE: https://github.com/googleapis/google-auth-library-python/blob/main/LICENSE 93 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). 4 | 5 | The Google Security Team will respond within 5 working days of your report on g.co/vulnz. 6 | 7 | We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. 8 | -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto|Roboto+Mono'); 2 | 3 | @media screen and (min-width: 1080px) { 4 | div.document { 5 | width: 1040px; 6 | } 7 | } 8 | 9 | code.descname { 10 | color: #4885ed; 11 | } 12 | 13 | th.field-name { 14 | min-width: 100px; 15 | color: #3cba54; 16 | } 17 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | google-auth 2 | =========== 3 | 4 | .. toctree:: 5 | :hidden: 6 | :maxdepth: 2 7 | 8 | user-guide 9 | Reference 10 | 11 | google-auth is the Google authentication library for Python. This library 12 | provides the ability to authenticate to Google APIs using various methods. It 13 | also provides integration with several HTTP libraries. 14 | 15 | - Support for Google :func:`Application Default Credentials `. 16 | - Support for signing and verifying :mod:`JWTs `. 17 | - Support for creating `Google ID Tokens `__. 18 | - Support for verifying and decoding :mod:`ID Tokens `. 19 | - Support for Google :mod:`Service Account credentials `. 20 | - Support for Google :mod:`Impersonated Credentials `. 21 | - Support for :mod:`Google Compute Engine credentials `. 22 | - Support for :mod:`Google App Engine standard credentials `. 23 | - Support for :mod:`Identity Pool credentials `. 24 | - Support for :mod:`AWS credentials `. 25 | - Support for :mod:`Downscoping with Credential Access Boundaries credentials `. 26 | - Support for various transports, including 27 | :mod:`Requests `, 28 | :mod:`urllib3 `, and 29 | :mod:`gRPC `. 30 | 31 | .. note:: ``oauth2client`` was recently deprecated in favor of this library. For more details on the deprecation, see :doc:`oauth2client-deprecation`. 32 | 33 | Installing 34 | ---------- 35 | 36 | google-auth can be installed with `pip`_:: 37 | 38 | $ pip install --upgrade google-auth 39 | 40 | google-auth is open-source, so you can alternatively grab the source code from 41 | `GitHub`_ and install from source. 42 | 43 | 44 | For more information on setting up your Python development environment, please refer to `Python Development Environment Setup Guide`_ for Google Cloud Platform. 45 | 46 | .. _`Python Development Environment Setup Guide`: https://cloud.google.com/python/setup 47 | .. _pip: https://pip.pypa.io 48 | .. _GitHub: https://github.com/GoogleCloudPlatform/google-auth-library-python 49 | 50 | Usage 51 | ----- 52 | 53 | The :doc:`user-guide` is the place to go to learn how to use the library and 54 | accomplish common tasks. 55 | 56 | The :doc:`Module Reference ` documentation provides API-level documentation. 57 | 58 | License 59 | ------- 60 | 61 | google-auth is made available under the Apache License, Version 2.0. For more 62 | details, see `LICENSE`_ 63 | 64 | .. _LICENSE: 65 | https://github.com/GoogleCloudPlatform/google-auth-library-python/blob/main/LICENSE 66 | 67 | Contributing 68 | ------------ 69 | 70 | We happily welcome contributions, please see our `contributing`_ documentation 71 | for details. 72 | 73 | .. _contributing: 74 | https://github.com/GoogleCloudPlatform/google-auth-library-python/blob/main/CONTRIBUTING.rst 75 | -------------------------------------------------------------------------------- /docs/reference/google.auth._credentials_async.rst: -------------------------------------------------------------------------------- 1 | google.auth.credentials\_async module 2 | ===================================== 3 | 4 | .. automodule:: google.auth._credentials_async 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth._jwt_async.rst: -------------------------------------------------------------------------------- 1 | google.auth.jwt\_async module 2 | ============================= 3 | 4 | .. automodule:: google.auth._jwt_async 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.app_engine.rst: -------------------------------------------------------------------------------- 1 | google.auth.app\_engine module 2 | ============================== 3 | 4 | .. automodule:: google.auth.app_engine 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.aws.rst: -------------------------------------------------------------------------------- 1 | google.auth.aws module 2 | ====================== 3 | 4 | .. automodule:: google.auth.aws 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.compute_engine.credentials.rst: -------------------------------------------------------------------------------- 1 | google.auth.compute\_engine.credentials module 2 | ============================================== 3 | 4 | .. automodule:: google.auth.compute_engine.credentials 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.compute_engine.rst: -------------------------------------------------------------------------------- 1 | google.auth.compute\_engine package 2 | =================================== 3 | 4 | .. automodule:: google.auth.compute_engine 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | 9 | Submodules 10 | ---------- 11 | 12 | .. toctree:: 13 | :maxdepth: 4 14 | 15 | google.auth.compute_engine.credentials 16 | -------------------------------------------------------------------------------- /docs/reference/google.auth.credentials.rst: -------------------------------------------------------------------------------- 1 | google.auth.credentials module 2 | ============================== 3 | 4 | .. automodule:: google.auth.credentials 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.crypt.base.rst: -------------------------------------------------------------------------------- 1 | google.auth.crypt.base module 2 | ============================= 3 | 4 | .. automodule:: google.auth.crypt.base 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.crypt.es256.rst: -------------------------------------------------------------------------------- 1 | google.auth.crypt.es256 module 2 | ============================== 3 | 4 | .. automodule:: google.auth.crypt.es256 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.crypt.rsa.rst: -------------------------------------------------------------------------------- 1 | google.auth.crypt.rsa module 2 | ============================ 3 | 4 | .. automodule:: google.auth.crypt.rsa 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.crypt.rst: -------------------------------------------------------------------------------- 1 | google.auth.crypt package 2 | ========================= 3 | 4 | .. automodule:: google.auth.crypt 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | 9 | Submodules 10 | ---------- 11 | 12 | .. toctree:: 13 | :maxdepth: 4 14 | 15 | google.auth.crypt.base 16 | google.auth.crypt.es256 17 | google.auth.crypt.rsa 18 | -------------------------------------------------------------------------------- /docs/reference/google.auth.downscoped.rst: -------------------------------------------------------------------------------- 1 | google.auth.downscoped module 2 | ============================= 3 | 4 | .. automodule:: google.auth.downscoped 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.environment_vars.rst: -------------------------------------------------------------------------------- 1 | google.auth.environment\_vars module 2 | ==================================== 3 | 4 | .. automodule:: google.auth.environment_vars 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.exceptions.rst: -------------------------------------------------------------------------------- 1 | google.auth.exceptions module 2 | ============================= 3 | 4 | .. automodule:: google.auth.exceptions 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.external_account.rst: -------------------------------------------------------------------------------- 1 | google.auth.external\_account module 2 | ==================================== 3 | 4 | .. automodule:: google.auth.external_account 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.iam.rst: -------------------------------------------------------------------------------- 1 | google.auth.iam module 2 | ====================== 3 | 4 | .. automodule:: google.auth.iam 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.identity_pool.rst: -------------------------------------------------------------------------------- 1 | google.auth.identity\_pool module 2 | ================================= 3 | 4 | .. automodule:: google.auth.identity_pool 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.impersonated_credentials.rst: -------------------------------------------------------------------------------- 1 | google.auth.impersonated\_credentials module 2 | ============================================ 3 | 4 | .. automodule:: google.auth.impersonated_credentials 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.jwt.rst: -------------------------------------------------------------------------------- 1 | google.auth.jwt module 2 | ====================== 3 | 4 | .. automodule:: google.auth.jwt 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.rst: -------------------------------------------------------------------------------- 1 | google.auth package 2 | =================== 3 | 4 | .. automodule:: google.auth 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | 9 | Subpackages 10 | ----------- 11 | 12 | .. toctree:: 13 | :maxdepth: 4 14 | 15 | google.auth.compute_engine 16 | google.auth.crypt 17 | google.auth.transport 18 | 19 | Submodules 20 | ---------- 21 | 22 | .. toctree:: 23 | :maxdepth: 4 24 | 25 | google.auth.app_engine 26 | google.auth.aws 27 | google.auth.credentials 28 | google.auth._credentials_async 29 | google.auth.downscoped 30 | google.auth.environment_vars 31 | google.auth.exceptions 32 | google.auth.external_account 33 | google.auth.iam 34 | google.auth.identity_pool 35 | google.auth.impersonated_credentials 36 | google.auth.jwt 37 | google.auth._jwt_async 38 | -------------------------------------------------------------------------------- /docs/reference/google.auth.transport._aiohttp_requests.rst: -------------------------------------------------------------------------------- 1 | google.auth.transport.aiohttp\_requests module 2 | ============================================== 3 | 4 | .. automodule:: google.auth.transport._aiohttp_requests 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.transport.grpc.rst: -------------------------------------------------------------------------------- 1 | google.auth.transport.grpc module 2 | ================================= 3 | 4 | .. automodule:: google.auth.transport.grpc 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.transport.mtls.rst: -------------------------------------------------------------------------------- 1 | google.auth.transport.mtls module 2 | ================================= 3 | 4 | .. automodule:: google.auth.transport.mtls 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.transport.requests.rst: -------------------------------------------------------------------------------- 1 | google.auth.transport.requests module 2 | ===================================== 3 | 4 | .. automodule:: google.auth.transport.requests 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.auth.transport.rst: -------------------------------------------------------------------------------- 1 | google.auth.transport package 2 | ============================= 3 | 4 | .. automodule:: google.auth.transport 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | 9 | Submodules 10 | ---------- 11 | 12 | .. toctree:: 13 | :maxdepth: 4 14 | 15 | google.auth.transport._aiohttp_requests 16 | google.auth.transport.grpc 17 | google.auth.transport.mtls 18 | google.auth.transport.requests 19 | google.auth.transport.urllib3 20 | -------------------------------------------------------------------------------- /docs/reference/google.auth.transport.urllib3.rst: -------------------------------------------------------------------------------- 1 | google.auth.transport.urllib3 module 2 | ==================================== 3 | 4 | .. automodule:: google.auth.transport.urllib3 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.oauth2._credentials_async.rst: -------------------------------------------------------------------------------- 1 | google.oauth2.credentials\_async module 2 | ======================================= 3 | 4 | .. automodule:: google.oauth2._credentials_async 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.oauth2._service_account_async.rst: -------------------------------------------------------------------------------- 1 | google.oauth2.service\_account\_async module 2 | ============================================ 3 | 4 | .. automodule:: google.oauth2._service_account_async 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.oauth2.credentials.rst: -------------------------------------------------------------------------------- 1 | google.oauth2.credentials module 2 | ================================ 3 | 4 | .. automodule:: google.oauth2.credentials 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.oauth2.id_token.rst: -------------------------------------------------------------------------------- 1 | google.oauth2.id\_token module 2 | ============================== 3 | 4 | .. automodule:: google.oauth2.id_token 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.oauth2.rst: -------------------------------------------------------------------------------- 1 | google.oauth2 package 2 | ===================== 3 | 4 | .. automodule:: google.oauth2 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | 9 | Submodules 10 | ---------- 11 | 12 | .. toctree:: 13 | :maxdepth: 4 14 | 15 | google.oauth2.credentials 16 | google.oauth2._credentials_async 17 | google.oauth2.id_token 18 | google.oauth2.service_account 19 | google.oauth2._service_account_async 20 | google.oauth2.sts 21 | google.oauth2.utils 22 | -------------------------------------------------------------------------------- /docs/reference/google.oauth2.service_account.rst: -------------------------------------------------------------------------------- 1 | google.oauth2.service\_account module 2 | ===================================== 3 | 4 | .. automodule:: google.oauth2.service_account 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.oauth2.sts.rst: -------------------------------------------------------------------------------- 1 | google.oauth2.sts module 2 | ======================== 3 | 4 | .. automodule:: google.oauth2.sts 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.oauth2.utils.rst: -------------------------------------------------------------------------------- 1 | google.oauth2.utils module 2 | ========================== 3 | 4 | .. automodule:: google.oauth2.utils 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/reference/google.rst: -------------------------------------------------------------------------------- 1 | google package 2 | ============== 3 | 4 | .. automodule:: google 5 | :members: 6 | :inherited-members: 7 | :show-inheritance: 8 | 9 | Subpackages 10 | ----------- 11 | 12 | .. toctree:: 13 | :maxdepth: 4 14 | 15 | google.auth 16 | google.oauth2 17 | -------------------------------------------------------------------------------- /docs/reference/modules.rst: -------------------------------------------------------------------------------- 1 | google 2 | ====== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | google 8 | -------------------------------------------------------------------------------- /docs/requirements-docs.txt: -------------------------------------------------------------------------------- 1 | cryptography 2 | sphinx-docstring-typing 3 | urllib3 4 | requests 5 | requests-oauthlib 6 | # We need to pin to specific versions of the `sphinxcontrib-*` packages 7 | # which still support sphinx 4.x. 8 | # See https://github.com/googleapis/sphinx-docfx-yaml/issues/344 9 | # and https://github.com/googleapis/sphinx-docfx-yaml/issues/345. 10 | sphinxcontrib-applehelp==1.0.4 11 | sphinxcontrib-devhelp==1.0.2 12 | sphinxcontrib-htmlhelp==2.0.1 13 | sphinxcontrib-qthelp==1.0.3 14 | sphinxcontrib-serializinghtml==1.1.5 15 | sphinx==4.5.0 16 | alabaster 17 | recommonmark 18 | -------------------------------------------------------------------------------- /google/auth/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Google Auth Library for Python.""" 16 | 17 | import logging 18 | import sys 19 | import warnings 20 | 21 | from google.auth import version as google_auth_version 22 | from google.auth._default import ( 23 | default, 24 | load_credentials_from_dict, 25 | load_credentials_from_file, 26 | ) 27 | 28 | 29 | __version__ = google_auth_version.__version__ 30 | 31 | 32 | __all__ = ["default", "load_credentials_from_file", "load_credentials_from_dict"] 33 | 34 | 35 | class Python37DeprecationWarning(DeprecationWarning): # pragma: NO COVER 36 | """ 37 | Deprecation warning raised when Python 3.7 runtime is detected. 38 | Python 3.7 support will be dropped after January 1, 2024. 39 | """ 40 | 41 | pass 42 | 43 | 44 | # Checks if the current runtime is Python 3.7. 45 | if sys.version_info.major == 3 and sys.version_info.minor == 7: # pragma: NO COVER 46 | message = ( 47 | "After January 1, 2024, new releases of this library will drop support " 48 | "for Python 3.7." 49 | ) 50 | warnings.warn(message, Python37DeprecationWarning) 51 | 52 | # Set default logging handler to avoid "No handler found" warnings. 53 | logging.getLogger(__name__).addHandler(logging.NullHandler()) 54 | -------------------------------------------------------------------------------- /google/auth/_credentials_base.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | """Interface for base credentials.""" 17 | 18 | import abc 19 | 20 | from google.auth import _helpers 21 | 22 | 23 | class _BaseCredentials(metaclass=abc.ABCMeta): 24 | """Base class for all credentials. 25 | 26 | All credentials have a :attr:`token` that is used for authentication and 27 | may also optionally set an :attr:`expiry` to indicate when the token will 28 | no longer be valid. 29 | 30 | Most credentials will be :attr:`invalid` until :meth:`refresh` is called. 31 | Credentials can do this automatically before the first HTTP request in 32 | :meth:`before_request`. 33 | 34 | Although the token and expiration will change as the credentials are 35 | :meth:`refreshed ` and used, credentials should be considered 36 | immutable. Various credentials will accept configuration such as private 37 | keys, scopes, and other options. These options are not changeable after 38 | construction. Some classes will provide mechanisms to copy the credentials 39 | with modifications such as :meth:`ScopedCredentials.with_scopes`. 40 | 41 | Attributes: 42 | token (Optional[str]): The bearer token that can be used in HTTP headers to make 43 | authenticated requests. 44 | """ 45 | 46 | def __init__(self): 47 | self.token = None 48 | 49 | @abc.abstractmethod 50 | def refresh(self, request): 51 | """Refreshes the access token. 52 | 53 | Args: 54 | request (google.auth.transport.Request): The object used to make 55 | HTTP requests. 56 | 57 | Raises: 58 | google.auth.exceptions.RefreshError: If the credentials could 59 | not be refreshed. 60 | """ 61 | # pylint: disable=missing-raises-doc 62 | # (pylint doesn't recognize that this is abstract) 63 | raise NotImplementedError("Refresh must be implemented") 64 | 65 | def _apply(self, headers, token=None): 66 | """Apply the token to the authentication header. 67 | 68 | Args: 69 | headers (Mapping): The HTTP request headers. 70 | token (Optional[str]): If specified, overrides the current access 71 | token. 72 | """ 73 | headers["authorization"] = "Bearer {}".format( 74 | _helpers.from_bytes(token or self.token) 75 | ) 76 | -------------------------------------------------------------------------------- /google/auth/_service_account_info.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Helper functions for loading data from a Google service account file.""" 16 | 17 | import io 18 | import json 19 | 20 | from google.auth import crypt 21 | from google.auth import exceptions 22 | 23 | 24 | def from_dict(data, require=None, use_rsa_signer=True): 25 | """Validates a dictionary containing Google service account data. 26 | 27 | Creates and returns a :class:`google.auth.crypt.Signer` instance from the 28 | private key specified in the data. 29 | 30 | Args: 31 | data (Mapping[str, str]): The service account data 32 | require (Sequence[str]): List of keys required to be present in the 33 | info. 34 | use_rsa_signer (Optional[bool]): Whether to use RSA signer or EC signer. 35 | We use RSA signer by default. 36 | 37 | Returns: 38 | google.auth.crypt.Signer: A signer created from the private key in the 39 | service account file. 40 | 41 | Raises: 42 | MalformedError: if the data was in the wrong format, or if one of the 43 | required keys is missing. 44 | """ 45 | keys_needed = set(require if require is not None else []) 46 | 47 | missing = keys_needed.difference(data.keys()) 48 | 49 | if missing: 50 | raise exceptions.MalformedError( 51 | "Service account info was not in the expected format, missing " 52 | "fields {}.".format(", ".join(missing)) 53 | ) 54 | 55 | # Create a signer. 56 | if use_rsa_signer: 57 | signer = crypt.RSASigner.from_service_account_info(data) 58 | else: 59 | signer = crypt.ES256Signer.from_service_account_info(data) 60 | 61 | return signer 62 | 63 | 64 | def from_filename(filename, require=None, use_rsa_signer=True): 65 | """Reads a Google service account JSON file and returns its parsed info. 66 | 67 | Args: 68 | filename (str): The path to the service account .json file. 69 | require (Sequence[str]): List of keys required to be present in the 70 | info. 71 | use_rsa_signer (Optional[bool]): Whether to use RSA signer or EC signer. 72 | We use RSA signer by default. 73 | 74 | Returns: 75 | Tuple[ Mapping[str, str], google.auth.crypt.Signer ]: The verified 76 | info and a signer instance. 77 | """ 78 | with io.open(filename, "r", encoding="utf-8") as json_file: 79 | data = json.load(json_file) 80 | return data, from_dict(data, require=require, use_rsa_signer=use_rsa_signer) 81 | -------------------------------------------------------------------------------- /google/auth/aio/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Google Auth AIO Library for Python.""" 16 | 17 | import logging 18 | 19 | from google.auth import version as google_auth_version 20 | 21 | 22 | __version__ = google_auth_version.__version__ 23 | 24 | # Set default logging handler to avoid "No handler found" warnings. 25 | logging.getLogger(__name__).addHandler(logging.NullHandler()) 26 | -------------------------------------------------------------------------------- /google/auth/aio/_helpers.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Helper functions for commonly used utilities.""" 16 | 17 | 18 | import logging 19 | from typing import Any 20 | 21 | from google.auth import _helpers 22 | 23 | 24 | async def _parse_response_async(response: Any) -> Any: 25 | """ 26 | Parses an async response, attempting to decode JSON. 27 | 28 | Args: 29 | response: The response object to parse. This can be any type, but 30 | it is expected to have a `json()` method if it contains JSON. 31 | 32 | Returns: 33 | The parsed response. If the response contains valid JSON, the 34 | decoded JSON object (e.g., a dictionary) is returned. 35 | If the response does not have a `json()` method or if the JSON 36 | decoding fails, None is returned. 37 | """ 38 | try: 39 | json_response = await response.json() 40 | return json_response 41 | except Exception: 42 | # TODO(https://github.com/googleapis/google-auth-library-python/issues/1745): 43 | # Parse and return response payload as json based on different content types. 44 | return None 45 | 46 | 47 | async def response_log_async(logger: logging.Logger, response: Any) -> None: 48 | """ 49 | Logs an Async HTTP response at the DEBUG level if logging is enabled. 50 | 51 | Args: 52 | logger: The logging.Logger instance to use. 53 | response: The HTTP response object to log. 54 | """ 55 | if _helpers.is_logging_enabled(logger): 56 | # TODO(https://github.com/googleapis/google-auth-library-python/issues/1755): 57 | # Parsing the response for async streaming logging results in 58 | # the stream to be empty downstream. For now, we will not be logging 59 | # the response for async responses until we investigate further. 60 | # json_response = await _parse_response_async(response) 61 | json_response = None 62 | _helpers._response_log_base(logger, json_response) 63 | -------------------------------------------------------------------------------- /google/auth/api_key.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Google API key support. 16 | This module provides authentication using the `API key`_. 17 | .. _API key: 18 | https://cloud.google.com/docs/authentication/api-keys/ 19 | """ 20 | 21 | from google.auth import _helpers 22 | from google.auth import credentials 23 | from google.auth import exceptions 24 | 25 | 26 | class Credentials(credentials.Credentials): 27 | """API key credentials. 28 | These credentials use API key to provide authorization to applications. 29 | """ 30 | 31 | def __init__(self, token): 32 | """ 33 | Args: 34 | token (str): API key string 35 | Raises: 36 | ValueError: If the provided API key is not a non-empty string. 37 | """ 38 | super(Credentials, self).__init__() 39 | if not token: 40 | raise exceptions.InvalidValue("Token must be a non-empty API key string") 41 | self.token = token 42 | 43 | @property 44 | def expired(self): 45 | return False 46 | 47 | @property 48 | def valid(self): 49 | return True 50 | 51 | @_helpers.copy_docstring(credentials.Credentials) 52 | def refresh(self, request): 53 | return 54 | 55 | def apply(self, headers, token=None): 56 | """Apply the API key token to the x-goog-api-key header. 57 | Args: 58 | headers (Mapping): The HTTP request headers. 59 | token (Optional[str]): If specified, overrides the current access 60 | token. 61 | """ 62 | headers["x-goog-api-key"] = token or self.token 63 | 64 | def before_request(self, request, method, url, headers): 65 | """Performs credential-specific before request logic. 66 | Refreshes the credentials if necessary, then calls :meth:`apply` to 67 | apply the token to the x-goog-api-key header. 68 | Args: 69 | request (google.auth.transport.Request): The object used to make 70 | HTTP requests. 71 | method (str): The request's HTTP method or the RPC method being 72 | invoked. 73 | url (str): The request's URI or the RPC service's URI. 74 | headers (Mapping): The request's headers. 75 | """ 76 | self.apply(headers) 77 | -------------------------------------------------------------------------------- /google/auth/compute_engine/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Google Compute Engine authentication.""" 16 | 17 | from google.auth.compute_engine._metadata import detect_gce_residency_linux 18 | from google.auth.compute_engine.credentials import Credentials 19 | from google.auth.compute_engine.credentials import IDTokenCredentials 20 | 21 | 22 | __all__ = ["Credentials", "IDTokenCredentials", "detect_gce_residency_linux"] 23 | -------------------------------------------------------------------------------- /google/auth/crypt/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Cryptography helpers for verifying and signing messages. 16 | 17 | The simplest way to verify signatures is using :func:`verify_signature`:: 18 | 19 | cert = open('certs.pem').read() 20 | valid = crypt.verify_signature(message, signature, cert) 21 | 22 | If you're going to verify many messages with the same certificate, you can use 23 | :class:`RSAVerifier`:: 24 | 25 | cert = open('certs.pem').read() 26 | verifier = crypt.RSAVerifier.from_string(cert) 27 | valid = verifier.verify(message, signature) 28 | 29 | To sign messages use :class:`RSASigner` with a private key:: 30 | 31 | private_key = open('private_key.pem').read() 32 | signer = crypt.RSASigner.from_string(private_key) 33 | signature = signer.sign(message) 34 | 35 | The code above also works for :class:`ES256Signer` and :class:`ES256Verifier`. 36 | Note that these two classes are only available if your `cryptography` dependency 37 | version is at least 1.4.0. 38 | """ 39 | 40 | from google.auth.crypt import base 41 | from google.auth.crypt import rsa 42 | 43 | try: 44 | from google.auth.crypt import es256 45 | except ImportError: # pragma: NO COVER 46 | es256 = None # type: ignore 47 | 48 | if es256 is not None: # pragma: NO COVER 49 | __all__ = [ 50 | "ES256Signer", 51 | "ES256Verifier", 52 | "RSASigner", 53 | "RSAVerifier", 54 | "Signer", 55 | "Verifier", 56 | ] 57 | else: # pragma: NO COVER 58 | __all__ = ["RSASigner", "RSAVerifier", "Signer", "Verifier"] 59 | 60 | 61 | # Aliases to maintain the v1.0.0 interface, as the crypt module was split 62 | # into submodules. 63 | Signer = base.Signer 64 | Verifier = base.Verifier 65 | RSASigner = rsa.RSASigner 66 | RSAVerifier = rsa.RSAVerifier 67 | 68 | if es256 is not None: # pragma: NO COVER 69 | ES256Signer = es256.ES256Signer 70 | ES256Verifier = es256.ES256Verifier 71 | 72 | 73 | def verify_signature(message, signature, certs, verifier_cls=rsa.RSAVerifier): 74 | """Verify an RSA or ECDSA cryptographic signature. 75 | 76 | Checks that the provided ``signature`` was generated from ``bytes`` using 77 | the private key associated with the ``cert``. 78 | 79 | Args: 80 | message (Union[str, bytes]): The plaintext message. 81 | signature (Union[str, bytes]): The cryptographic signature to check. 82 | certs (Union[Sequence, str, bytes]): The certificate or certificates 83 | to use to check the signature. 84 | verifier_cls (Optional[~google.auth.crypt.base.Signer]): Which verifier 85 | class to use for verification. This can be used to select different 86 | algorithms, such as RSA or ECDSA. Default value is :class:`RSAVerifier`. 87 | 88 | Returns: 89 | bool: True if the signature is valid, otherwise False. 90 | """ 91 | if isinstance(certs, (str, bytes)): 92 | certs = [certs] 93 | 94 | for cert in certs: 95 | verifier = verifier_cls.from_string(cert) 96 | if verifier.verify(message, signature): 97 | return True 98 | return False 99 | -------------------------------------------------------------------------------- /google/auth/crypt/_helpers.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/google/auth/crypt/_helpers.py -------------------------------------------------------------------------------- /google/auth/crypt/rsa.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """RSA cryptography signer and verifier.""" 16 | 17 | 18 | try: 19 | # Prefer cryptograph-based RSA implementation. 20 | from google.auth.crypt import _cryptography_rsa 21 | 22 | RSASigner = _cryptography_rsa.RSASigner 23 | RSAVerifier = _cryptography_rsa.RSAVerifier 24 | except ImportError: # pragma: NO COVER 25 | # Fallback to pure-python RSA implementation if cryptography is 26 | # unavailable. 27 | from google.auth.crypt import _python_rsa 28 | 29 | RSASigner = _python_rsa.RSASigner # type: ignore 30 | RSAVerifier = _python_rsa.RSAVerifier # type: ignore 31 | -------------------------------------------------------------------------------- /google/auth/environment_vars.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Environment variables used by :mod:`google.auth`.""" 16 | 17 | 18 | PROJECT = "GOOGLE_CLOUD_PROJECT" 19 | """Environment variable defining default project. 20 | 21 | This used by :func:`google.auth.default` to explicitly set a project ID. This 22 | environment variable is also used by the Google Cloud Python Library. 23 | """ 24 | 25 | LEGACY_PROJECT = "GCLOUD_PROJECT" 26 | """Previously used environment variable defining the default project. 27 | 28 | This environment variable is used instead of the current one in some 29 | situations (such as Google App Engine). 30 | """ 31 | 32 | GOOGLE_CLOUD_QUOTA_PROJECT = "GOOGLE_CLOUD_QUOTA_PROJECT" 33 | """Environment variable defining the project to be used for 34 | quota and billing.""" 35 | 36 | CREDENTIALS = "GOOGLE_APPLICATION_CREDENTIALS" 37 | """Environment variable defining the location of Google application default 38 | credentials.""" 39 | 40 | # The environment variable name which can replace ~/.config if set. 41 | CLOUD_SDK_CONFIG_DIR = "CLOUDSDK_CONFIG" 42 | """Environment variable defines the location of Google Cloud SDK's config 43 | files.""" 44 | 45 | # These two variables allow for customization of the addresses used when 46 | # contacting the GCE metadata service. 47 | GCE_METADATA_HOST = "GCE_METADATA_HOST" 48 | """Environment variable providing an alternate hostname or host:port to be 49 | used for GCE metadata requests. 50 | 51 | This environment variable was originally named GCE_METADATA_ROOT. The system will 52 | check this environemnt variable first; should there be no value present, 53 | the system will fall back to the old variable. 54 | """ 55 | 56 | GCE_METADATA_ROOT = "GCE_METADATA_ROOT" 57 | """Old environment variable for GCE_METADATA_HOST.""" 58 | 59 | GCE_METADATA_IP = "GCE_METADATA_IP" 60 | """Environment variable providing an alternate ip:port to be used for ip-only 61 | GCE metadata requests.""" 62 | 63 | GOOGLE_API_USE_CLIENT_CERTIFICATE = "GOOGLE_API_USE_CLIENT_CERTIFICATE" 64 | """Environment variable controlling whether to use client certificate or not. 65 | 66 | The default value is false. Users have to explicitly set this value to true 67 | in order to use client certificate to establish a mutual TLS channel.""" 68 | 69 | LEGACY_APPENGINE_RUNTIME = "APPENGINE_RUNTIME" 70 | """Gen1 environment variable defining the App Engine Runtime. 71 | 72 | Used to distinguish between GAE gen1 and GAE gen2+. 73 | """ 74 | 75 | # AWS environment variables used with AWS workload identity pools to retrieve 76 | # AWS security credentials and the AWS region needed to create a serialized 77 | # signed requests to the AWS STS GetCalledIdentity API that can be exchanged 78 | # for a Google access tokens via the GCP STS endpoint. 79 | # When not available the AWS metadata server is used to retrieve these values. 80 | AWS_ACCESS_KEY_ID = "AWS_ACCESS_KEY_ID" 81 | AWS_SECRET_ACCESS_KEY = "AWS_SECRET_ACCESS_KEY" 82 | AWS_SESSION_TOKEN = "AWS_SESSION_TOKEN" 83 | AWS_REGION = "AWS_REGION" 84 | AWS_DEFAULT_REGION = "AWS_DEFAULT_REGION" 85 | -------------------------------------------------------------------------------- /google/auth/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Exceptions used in the google.auth package.""" 16 | 17 | 18 | class GoogleAuthError(Exception): 19 | """Base class for all google.auth errors.""" 20 | 21 | def __init__(self, *args, **kwargs): 22 | super(GoogleAuthError, self).__init__(*args) 23 | retryable = kwargs.get("retryable", False) 24 | self._retryable = retryable 25 | 26 | @property 27 | def retryable(self): 28 | return self._retryable 29 | 30 | 31 | class TransportError(GoogleAuthError): 32 | """Used to indicate an error occurred during an HTTP request.""" 33 | 34 | 35 | class RefreshError(GoogleAuthError): 36 | """Used to indicate that an refreshing the credentials' access token 37 | failed.""" 38 | 39 | 40 | class UserAccessTokenError(GoogleAuthError): 41 | """Used to indicate ``gcloud auth print-access-token`` command failed.""" 42 | 43 | 44 | class DefaultCredentialsError(GoogleAuthError): 45 | """Used to indicate that acquiring default credentials failed.""" 46 | 47 | 48 | class MutualTLSChannelError(GoogleAuthError): 49 | """Used to indicate that mutual TLS channel creation is failed, or mutual 50 | TLS channel credentials is missing or invalid.""" 51 | 52 | 53 | class ClientCertError(GoogleAuthError): 54 | """Used to indicate that client certificate is missing or invalid.""" 55 | 56 | @property 57 | def retryable(self): 58 | return False 59 | 60 | 61 | class OAuthError(GoogleAuthError): 62 | """Used to indicate an error occurred during an OAuth related HTTP 63 | request.""" 64 | 65 | 66 | class ReauthFailError(RefreshError): 67 | """An exception for when reauth failed.""" 68 | 69 | def __init__(self, message=None, **kwargs): 70 | super(ReauthFailError, self).__init__( 71 | "Reauthentication failed. {0}".format(message), **kwargs 72 | ) 73 | 74 | 75 | class ReauthSamlChallengeFailError(ReauthFailError): 76 | """An exception for SAML reauth challenge failures.""" 77 | 78 | 79 | class MalformedError(DefaultCredentialsError, ValueError): 80 | """An exception for malformed data.""" 81 | 82 | 83 | class InvalidResource(DefaultCredentialsError, ValueError): 84 | """An exception for URL error.""" 85 | 86 | 87 | class InvalidOperation(DefaultCredentialsError, ValueError): 88 | """An exception for invalid operation.""" 89 | 90 | 91 | class InvalidValue(DefaultCredentialsError, ValueError): 92 | """Used to wrap general ValueError of python.""" 93 | 94 | 95 | class InvalidType(DefaultCredentialsError, TypeError): 96 | """Used to wrap general TypeError of python.""" 97 | 98 | 99 | class OSError(DefaultCredentialsError, EnvironmentError): 100 | """Used to wrap EnvironmentError(OSError after python3.3).""" 101 | 102 | 103 | class TimeoutError(GoogleAuthError): 104 | """Used to indicate a timeout error occurred during an HTTP request.""" 105 | 106 | 107 | class ResponseError(GoogleAuthError): 108 | """Used to indicate an error occurred when reading an HTTP response.""" 109 | -------------------------------------------------------------------------------- /google/auth/py.typed: -------------------------------------------------------------------------------- 1 | # Marker file for PEP 561. 2 | # The google-auth package uses inline types. 3 | -------------------------------------------------------------------------------- /google/auth/transport/_requests_base.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Transport adapter for Base Requests.""" 16 | # NOTE: The coverage for this file is temporarily disabled in `.coveragerc` 17 | # since it is currently unused. 18 | 19 | import abc 20 | 21 | 22 | _DEFAULT_TIMEOUT = 120 # in second 23 | 24 | 25 | class _BaseAuthorizedSession(metaclass=abc.ABCMeta): 26 | """Base class for a Request Session with credentials. This class is intended to capture 27 | the common logic between synchronous and asynchronous request sessions and is not intended to 28 | be instantiated directly. 29 | 30 | Args: 31 | credentials (google.auth._credentials_base.BaseCredentials): The credentials to 32 | add to the request. 33 | """ 34 | 35 | def __init__(self, credentials): 36 | self.credentials = credentials 37 | 38 | @abc.abstractmethod 39 | def request( 40 | self, 41 | method, 42 | url, 43 | data=None, 44 | headers=None, 45 | max_allowed_time=None, 46 | timeout=_DEFAULT_TIMEOUT, 47 | **kwargs 48 | ): 49 | raise NotImplementedError("Request must be implemented") 50 | 51 | @abc.abstractmethod 52 | def close(self): 53 | raise NotImplementedError("Close must be implemented") 54 | -------------------------------------------------------------------------------- /google/auth/version.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | __version__ = "2.40.3" 16 | -------------------------------------------------------------------------------- /google/oauth2/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Google OAuth 2.0 Library for Python.""" 16 | 17 | import sys 18 | import warnings 19 | 20 | 21 | class Python37DeprecationWarning(DeprecationWarning): # pragma: NO COVER 22 | """ 23 | Deprecation warning raised when Python 3.7 runtime is detected. 24 | Python 3.7 support will be dropped after January 1, 2024. 25 | """ 26 | 27 | pass 28 | 29 | 30 | # Checks if the current runtime is Python 3.7. 31 | if sys.version_info.major == 3 and sys.version_info.minor == 7: # pragma: NO COVER 32 | message = ( 33 | "After January 1, 2024, new releases of this library will drop support " 34 | "for Python 3.7." 35 | ) 36 | warnings.warn(message, Python37DeprecationWarning) 37 | -------------------------------------------------------------------------------- /google/oauth2/py.typed: -------------------------------------------------------------------------------- 1 | # Marker file for PEP 561. 2 | # The google-oauth2 package uses inline types. 3 | -------------------------------------------------------------------------------- /google/oauth2/webauthn_handler.py: -------------------------------------------------------------------------------- 1 | import abc 2 | import os 3 | import struct 4 | import subprocess 5 | 6 | from google.auth import exceptions 7 | from google.oauth2.webauthn_types import GetRequest, GetResponse 8 | 9 | 10 | class WebAuthnHandler(abc.ABC): 11 | @abc.abstractmethod 12 | def is_available(self) -> bool: 13 | """Check whether this WebAuthn handler is available""" 14 | raise NotImplementedError("is_available method must be implemented") 15 | 16 | @abc.abstractmethod 17 | def get(self, get_request: GetRequest) -> GetResponse: 18 | """WebAuthn get (assertion)""" 19 | raise NotImplementedError("get method must be implemented") 20 | 21 | 22 | class PluginHandler(WebAuthnHandler): 23 | """Offloads WebAuthn get reqeust to a pluggable command-line tool. 24 | 25 | Offloads WebAuthn get to a plugin which takes the form of a 26 | command-line tool. The command-line tool is configurable via the 27 | PluginHandler._ENV_VAR environment variable. 28 | 29 | The WebAuthn plugin should implement the following interface: 30 | 31 | Communication occurs over stdin/stdout, and messages are both sent and 32 | received in the form: 33 | 34 | [4 bytes - payload size (little-endian)][variable bytes - json payload] 35 | """ 36 | 37 | _ENV_VAR = "GOOGLE_AUTH_WEBAUTHN_PLUGIN" 38 | 39 | def is_available(self) -> bool: 40 | try: 41 | self._find_plugin() 42 | except Exception: 43 | return False 44 | else: 45 | return True 46 | 47 | def get(self, get_request: GetRequest) -> GetResponse: 48 | request_json = get_request.to_json() 49 | cmd = self._find_plugin() 50 | response_json = self._call_plugin(cmd, request_json) 51 | return GetResponse.from_json(response_json) 52 | 53 | def _call_plugin(self, cmd: str, input_json: str) -> str: 54 | # Calculate length of input 55 | input_length = len(input_json) 56 | length_bytes_le = struct.pack(" str: 77 | plugin_cmd = os.environ.get(PluginHandler._ENV_VAR) 78 | if plugin_cmd is None: 79 | raise exceptions.InvalidResource( 80 | "{} env var is not set".format(PluginHandler._ENV_VAR) 81 | ) 82 | return plugin_cmd 83 | -------------------------------------------------------------------------------- /google/oauth2/webauthn_handler_factory.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | from google.oauth2.webauthn_handler import PluginHandler, WebAuthnHandler 4 | 5 | 6 | class WebauthnHandlerFactory: 7 | handlers: List[WebAuthnHandler] 8 | 9 | def __init__(self): 10 | self.handlers = [PluginHandler()] 11 | 12 | def get_handler(self) -> Optional[WebAuthnHandler]: 13 | for handler in self.handlers: 14 | if handler.is_available(): 15 | return handler 16 | return None 17 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | python_version = 3.7 3 | namespace_packages = True 4 | -------------------------------------------------------------------------------- /owlbot.py: -------------------------------------------------------------------------------- 1 | import synthtool as s 2 | from synthtool import gcp 3 | 4 | common = gcp.CommonTemplates() 5 | 6 | # ---------------------------------------------------------------------------- 7 | # Add templated files 8 | # ---------------------------------------------------------------------------- 9 | templated_files = common.py_library(unit_cov_level=100, cov_level=100) 10 | 11 | 12 | s.move( 13 | templated_files / ".kokoro", 14 | excludes=[ 15 | "continuous/common.cfg", 16 | "presubmit/common.cfg", 17 | "build.sh", 18 | "samples/*", 19 | ], 20 | ) # just move kokoro configs 21 | s.move( 22 | # needed by samples kokoro jobs 23 | templated_files / ".trampolinerc" 24 | ) 25 | s.move( 26 | templated_files / "renovate.json", 27 | ) 28 | 29 | s.shell.run(["nox", "-s", "blacken"], hide_output=False) 30 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | "group:all", 5 | ":preserveSemverRanges", 6 | ":disableDependencyDashboard" 7 | ], 8 | "ignorePaths": [".pre-commit-config.yaml", ".kokoro/requirements.txt", "setup.py", ".github/workflows/unittest.yml"], 9 | "pip_requirements": { 10 | "fileMatch": ["requirements-test.txt", "samples/[\\S/]*constraints.txt", "samples/[\\S/]*constraints-test.txt"] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/authenticate_explicit_with_adc.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # [START auth_cloud_explicit_adc] 16 | 17 | from google.cloud import storage 18 | 19 | import google.oauth2.credentials 20 | import google.auth 21 | 22 | 23 | def authenticate_explicit_with_adc(): 24 | """ 25 | List storage buckets by authenticating with ADC. 26 | 27 | // TODO(Developer): 28 | // 1. Before running this sample, 29 | // set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc 30 | // 2. Replace the project variable. 31 | // 3. Make sure you have the necessary permission to list storage buckets: "storage.buckets.list" 32 | """ 33 | 34 | # Construct the Google credentials object which obtains the default configuration from your 35 | # working environment. 36 | # google.auth.default() will give you ComputeEngineCredentials 37 | # if you are on a GCE (or other metadata server supported environments). 38 | credentials, project_id = google.auth.default() 39 | # If you are authenticating to a Cloud API, you can let the library include the default scope, 40 | # https://www.googleapis.com/auth/cloud-platform, because IAM is used to provide fine-grained 41 | # permissions for Cloud. 42 | # If you need to provide a scope, specify it as follows: 43 | # credentials = google.auth.default(scopes=scope) 44 | # For more information on scopes to use, 45 | # see: https://developers.google.com/identity/protocols/oauth2/scopes 46 | 47 | # Construct the Storage client. 48 | storage_client = storage.Client(credentials=credentials, project=project_id) 49 | buckets = storage_client.list_buckets() 50 | print("Buckets:") 51 | for bucket in buckets: 52 | print(bucket.name) 53 | print("Listed all storage buckets.") 54 | 55 | # [END auth_cloud_explicit_adc] 56 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/authenticate_implicit_with_adc.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # [START auth_cloud_implicit_adc] 16 | 17 | from google.cloud import storage 18 | 19 | 20 | def authenticate_implicit_with_adc(project_id="your-google-cloud-project-id"): 21 | """ 22 | When interacting with Google Cloud Client libraries, the library can auto-detect the 23 | credentials to use. 24 | 25 | // TODO(Developer): 26 | // 1. Before running this sample, 27 | // set up ADC as described in https://cloud.google.com/docs/authentication/external/set-up-adc 28 | // 2. Replace the project variable. 29 | // 3. Make sure that the user account or service account that you are using 30 | // has the required permissions. For this sample, you must have "storage.buckets.list". 31 | Args: 32 | project_id: The project id of your Google Cloud project. 33 | """ 34 | 35 | # This snippet demonstrates how to list buckets. 36 | # *NOTE*: Replace the client created below with the client required for your application. 37 | # Note that the credentials are not specified when constructing the client. 38 | # Hence, the client library will look for credentials using ADC. 39 | storage_client = storage.Client(project=project_id) 40 | buckets = storage_client.list_buckets() 41 | print("Buckets:") 42 | for bucket in buckets: 43 | print(bucket.name) 44 | print("Listed all storage buckets.") 45 | 46 | # [END auth_cloud_implicit_adc] 47 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/idtoken_from_impersonated_credentials.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # [auth_cloud_idtoken_impersonated_credentials] 16 | 17 | import google 18 | from google.auth import impersonated_credentials 19 | import google.auth.transport.requests 20 | 21 | 22 | def idtoken_from_impersonated_credentials( 23 | impersonated_service_account: str, scope: str, target_audience: str): 24 | """ 25 | Use a service account (SA1) to impersonate as another service account (SA2) and obtain id token 26 | for the impersonated account. 27 | To obtain token for SA2, SA1 should have the "roles/iam.serviceAccountTokenCreator" permission 28 | on SA2. 29 | 30 | Args: 31 | impersonated_service_account: The name of the privilege-bearing service account for whom the credential is created. 32 | Examples: name@project.service.gserviceaccount.com 33 | 34 | scope: Provide the scopes that you might need to request to access Google APIs, 35 | depending on the level of access you need. 36 | For this example, we use the cloud-wide scope and use IAM to narrow the permissions. 37 | https://cloud.google.com/docs/authentication#authorization_for_services 38 | For more information, see: https://developers.google.com/identity/protocols/oauth2/scopes 39 | 40 | target_audience: The service name for which the id token is requested. Service name refers to the 41 | logical identifier of an API service, such as "iap.googleapis.com". 42 | Examples: iap.googleapis.com 43 | """ 44 | 45 | # Construct the GoogleCredentials object which obtains the default configuration from your 46 | # working environment. 47 | credentials, project_id = google.auth.default() 48 | 49 | # Create the impersonated credential. 50 | target_credentials = impersonated_credentials.Credentials( 51 | source_credentials=credentials, 52 | target_principal=impersonated_service_account, 53 | # delegates: The chained list of delegates required to grant the final accessToken. 54 | # For more information, see: 55 | # https://cloud.google.com/iam/docs/create-short-lived-credentials-direct#sa-credentials-permissions 56 | # Delegate is NOT USED here. 57 | delegates=[], 58 | target_scopes=[scope], 59 | lifetime=300) 60 | 61 | # Set the impersonated credential, target audience and token options. 62 | id_creds = impersonated_credentials.IDTokenCredentials( 63 | target_credentials, 64 | target_audience=target_audience, 65 | include_email=True) 66 | 67 | # Get the ID token. 68 | # Once you've obtained the ID token, use it to make an authenticated call 69 | # to the target audience. 70 | request = google.auth.transport.requests.Request() 71 | id_creds.refresh(request) 72 | # token = id_creds.token 73 | print("Generated ID token.") 74 | 75 | # [auth_cloud_idtoken_impersonated_credentials] 76 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/idtoken_from_metadata_server.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # [START auth_cloud_idtoken_metadata_server] 16 | 17 | import google 18 | import google.oauth2.credentials 19 | from google.auth import compute_engine 20 | import google.auth.transport.requests 21 | 22 | 23 | def idtoken_from_metadata_server(url: str): 24 | """ 25 | Use the Google Cloud metadata server in the Cloud Run (or AppEngine or Kubernetes etc.,) 26 | environment to create an identity token and add it to the HTTP request as part of an 27 | Authorization header. 28 | 29 | Args: 30 | url: The url or target audience to obtain the ID token for. 31 | Examples: http://www.example.com 32 | """ 33 | 34 | request = google.auth.transport.requests.Request() 35 | # Set the target audience. 36 | # Setting "use_metadata_identity_endpoint" to "True" will make the request use the default application 37 | # credentials. Optionally, you can also specify a specific service account to use by mentioning 38 | # the service_account_email. 39 | credentials = compute_engine.IDTokenCredentials( 40 | request=request, target_audience=url, use_metadata_identity_endpoint=True 41 | ) 42 | 43 | # Get the ID token. 44 | # Once you've obtained the ID token, use it to make an authenticated call 45 | # to the target audience. 46 | credentials.refresh(request) 47 | # print(credentials.token) 48 | print("Generated ID token.") 49 | 50 | # [END auth_cloud_idtoken_metadata_server] 51 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/idtoken_from_service_account.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # [START auth_cloud_idtoken_service_account] 16 | 17 | import google.auth 18 | import google.auth.transport.requests 19 | 20 | from google.oauth2 import service_account 21 | 22 | 23 | def get_idToken_from_serviceaccount(json_credential_path: str, target_audience: str): 24 | """ 25 | TODO(Developer): Replace the below variables before running the code. 26 | 27 | *NOTE*: 28 | Using service account keys introduces risk; they are long-lived, and can be used by anyone 29 | that obtains the key. Proper rotation and storage reduce this risk but do not eliminate it. 30 | For these reasons, you should consider an alternative approach that 31 | does not use a service account key. Several alternatives to service account keys 32 | are described here: 33 | https://cloud.google.com/docs/authentication/external/set-up-adc 34 | 35 | Args: 36 | json_credential_path: Path to the service account json credential file. 37 | target_audience: The url or target audience to obtain the ID token for. 38 | Examples: http://www.abc.com 39 | """ 40 | 41 | # Obtain the id token by providing the json file path and target audience. 42 | credentials = service_account.IDTokenCredentials.from_service_account_file( 43 | filename=json_credential_path, 44 | target_audience=target_audience) 45 | 46 | request = google.auth.transport.requests.Request() 47 | credentials.refresh(request) 48 | print("Generated ID token.") 49 | 50 | # [END auth_cloud_idtoken_service_account] 51 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/noxfile.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import pathlib 16 | 17 | import nox 18 | 19 | CURRENT_DIRECTORY = pathlib.Path(__file__).parent.absolute() 20 | 21 | # https://github.com/psf/black/issues/2964, pin click version to 8.0.4 to 22 | # avoid incompatiblity with black. 23 | CLICK_VERSION = "click==8.0.4" 24 | BLACK_VERSION = "black==19.3b0" 25 | BLACK_PATHS = [ 26 | "google", 27 | "tests", 28 | "tests_async", 29 | "noxfile.py", 30 | "setup.py", 31 | "docs/conf.py", 32 | ] 33 | 34 | 35 | # Error if a python version is missing 36 | nox.options.error_on_missing_interpreters = True 37 | 38 | # 39 | # Style Checks 40 | # 41 | 42 | 43 | # Linting with flake8. 44 | # 45 | # We ignore the following rules: 46 | # E203: whitespace before ‘:’ 47 | # E266: too many leading ‘#’ for block comment 48 | # E501: line too long 49 | # I202: Additional newline in a section of imports 50 | # 51 | # We also need to specify the rules which are ignored by default: 52 | # ['E226', 'W504', 'E126', 'E123', 'W503', 'E24', 'E704', 'E121'] 53 | FLAKE8_COMMON_ARGS = [ 54 | "--show-source", 55 | "--builtin=gettext", 56 | "--max-complexity=20", 57 | "--exclude=.nox,.cache,env,lib,generated_pb2,*_pb2.py,*_pb2_grpc.py", 58 | "--ignore=E121,E123,E126,E203,E226,E24,E266,E501,E704,W503,W504,I202", 59 | "--max-line-length=88", 60 | ] 61 | 62 | 63 | @nox.session(python=["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]) 64 | def unit(session): 65 | # constraints_path = str( 66 | # CURRENT_DIRECTORY / "testing" / f"constraints-{session.python}.txt" 67 | # ) 68 | session.install("-r", "requirements.txt") 69 | # session.install("-e", ".") 70 | session.run( 71 | "pytest", 72 | f"--junitxml=unit_{session.python}_sponge_log.xml", 73 | "snippets_test.py", 74 | # "tests_async", 75 | ) 76 | 77 | 78 | @nox.session 79 | def lint(session: nox.sessions.Session) -> None: 80 | session.install("flake8") 81 | 82 | args = FLAKE8_COMMON_ARGS + [ 83 | ".", 84 | ] 85 | session.run("flake8", *args) 86 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/noxfile_config.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Default TEST_CONFIG_OVERRIDE for python repos. 16 | 17 | # You can copy this file into your directory, then it will be inported from 18 | # the noxfile.py. 19 | 20 | # The source of truth: 21 | # https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/noxfile_config.py 22 | 23 | TEST_CONFIG_OVERRIDE = { 24 | # You can opt out from the test for specific Python versions. 25 | "ignored_versions": ["2.7"], 26 | # Old samples are opted out of enforcing Python type hints 27 | # All new samples should feature them 28 | "enforce_type_hints": True, 29 | # An envvar key for determining the project id to use. Change it 30 | # to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a 31 | # build specific Cloud project. You can also use your own string 32 | # to use your own Cloud project. 33 | # "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", 34 | "gcloud_project_env": "GOOGLE_CLOUD_PROJECT", 35 | # A dictionary you want to inject into your test. Don't put any 36 | # secrets here. These values will override predefined values. 37 | "envs": {}, 38 | } 39 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/requirements.txt: -------------------------------------------------------------------------------- 1 | google-cloud-compute==1.5.1 2 | google-cloud-storage==3.1.0 3 | google-auth==2.38.0 4 | pytest==7.1.2 5 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/snippets_test.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import re 15 | 16 | from _pytest.capture import CaptureFixture 17 | 18 | import authenticate_explicit_with_adc 19 | import authenticate_implicit_with_adc 20 | import idtoken_from_metadata_server 21 | import idtoken_from_service_account 22 | # from system_tests.noxfile import SERVICE_ACCOUNT_FILE 23 | import verify_google_idtoken 24 | 25 | import google 26 | from google.oauth2 import service_account 27 | import google.auth.transport.requests 28 | import os 29 | 30 | CREDENTIALS, PROJECT = google.auth.default() 31 | SERVICE_ACCOUNT_FILE = os.getenv("GOOGLE_APPLICATION_CREDENTIALS") 32 | 33 | 34 | def test_authenticate_explicit_with_adc(capsys: CaptureFixture): 35 | authenticate_explicit_with_adc.authenticate_explicit_with_adc() 36 | out, err = capsys.readouterr() 37 | assert re.search("Listed all storage buckets.", out) 38 | 39 | 40 | def test_authenticate_implicit_with_adc(capsys: CaptureFixture): 41 | authenticate_implicit_with_adc.authenticate_implicit_with_adc(PROJECT) 42 | out, err = capsys.readouterr() 43 | assert re.search("Listed all storage buckets.", out) 44 | 45 | 46 | def test_idtoken_from_metadata_server(capsys: CaptureFixture): 47 | idtoken_from_metadata_server.idtoken_from_metadata_server("https://www.google.com") 48 | out, err = capsys.readouterr() 49 | assert re.search("Generated ID token.", out) 50 | 51 | 52 | def test_idtoken_from_service_account(capsys: CaptureFixture): 53 | idtoken_from_service_account.get_idToken_from_serviceaccount( 54 | SERVICE_ACCOUNT_FILE, 55 | "iap.googleapis.com") 56 | out, err = capsys.readouterr() 57 | assert re.search("Generated ID token.", out) 58 | 59 | 60 | def test_verify_google_idtoken(): 61 | idtoken = get_idtoken_from_service_account(SERVICE_ACCOUNT_FILE, "iap.googleapis.com") 62 | 63 | verify_google_idtoken.verify_google_idtoken( 64 | idtoken, 65 | "iap.googleapis.com", 66 | "https://www.googleapis.com/oauth2/v3/certs" 67 | ) 68 | 69 | 70 | def get_idtoken_from_service_account(json_credential_path: str, target_audience: str): 71 | credentials = service_account.IDTokenCredentials.from_service_account_file( 72 | filename=json_credential_path, 73 | target_audience=target_audience) 74 | 75 | request = google.auth.transport.requests.Request() 76 | credentials.refresh(request) 77 | return credentials.token 78 | -------------------------------------------------------------------------------- /samples/cloud-client/snippets/verify_google_idtoken.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # [START auth_cloud_verify_google_idtoken] 16 | 17 | import google 18 | import google.auth.transport.requests 19 | from google.oauth2 import id_token 20 | 21 | 22 | def verify_google_idtoken(idtoken: str, audience="iap.googleapis.com", 23 | jwk_url="https://www.googleapis.com/oauth2/v3/certs"): 24 | """ 25 | Verifies the obtained Google id token. This is done at the receiving end of the OIDC endpoint. 26 | The most common use case for verifying the ID token is when you are protecting 27 | your own APIs with IAP. Google services already verify credentials as a platform, 28 | so verifying ID tokens before making Google API calls is usually unnecessary. 29 | 30 | Args: 31 | idtoken: The Google ID token to verify. 32 | 33 | audience: The service name for which the id token is requested. Service name refers to the 34 | logical identifier of an API service, such as "iap.googleapis.com". 35 | 36 | jwk_url: To verify id tokens, get the Json Web Key endpoint (jwk). 37 | OpenID Connect allows the use of a "Discovery document," a JSON document found at a 38 | well-known location containing key-value pairs which provide details about the 39 | OpenID Connect provider's configuration. 40 | For more information on validating the jwt, see: 41 | https://developers.google.com/identity/protocols/oauth2/openid-connect#validatinganidtoken 42 | 43 | Here, we validate Google's token using Google's OpenID Connect service (jwkUrl). 44 | For more information on jwk,see: 45 | https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets 46 | """ 47 | 48 | request = google.auth.transport.requests.Request() 49 | # Set the parameters and verify the token. 50 | # Setting "certs_url" is optional. When verifying a Google ID token, this is set by default. 51 | result = id_token.verify_token(idtoken, request, audience, clock_skew_in_seconds=10) 52 | 53 | # Verify that the token contains subject and email claims. 54 | # Get the User id. 55 | if not result["sub"] is None: 56 | print(f"User id: {result['sub']}") 57 | # Optionally, if "INCLUDE_EMAIL" was set in the token options, check if the 58 | # email was verified. 59 | if result['email_verified'] == "True": 60 | print(f"Email verified {result['email']}") 61 | 62 | # [END auth_cloud_verify_google_idtoken] 63 | -------------------------------------------------------------------------------- /scripts/decrypt-secrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015 Google Inc. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 18 | ROOT=$( dirname "$DIR" ) 19 | 20 | # Work from the project root. 21 | cd $ROOT 22 | 23 | gcloud kms decrypt \ 24 | --location=global \ 25 | --keyring=ci \ 26 | --key=kokoro-secrets \ 27 | --ciphertext-file=system_tests/secrets.tar.enc \ 28 | --plaintext-file=system_tests/secrets.tar 29 | tar xvf system_tests/secrets.tar 30 | rm system_tests/secrets.tar 31 | -------------------------------------------------------------------------------- /scripts/encrypt-secrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015 Google Inc. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 18 | ROOT=$( dirname "$DIR" ) 19 | 20 | # Work from the project root. 21 | cd $ROOT 22 | 23 | tar cvf system_tests/secrets.tar system_tests/data 24 | 25 | gcloud kms encrypt \ 26 | --location=global \ 27 | --keyring=ci \ 28 | --key=kokoro-secrets \ 29 | --plaintext-file=system_tests/secrets.tar \ 30 | --ciphertext-file=system_tests/secrets.tar.enc 31 | 32 | rm system_tests/secrets.tar -------------------------------------------------------------------------------- /scripts/travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2015 Google Inc. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 20 | ROOT=$( dirname "$DIR" ) 21 | 22 | # Work from the project root. 23 | cd $ROOT 24 | 25 | # Decrypt secrets and run system tests if not on an external PR. 26 | if [[ -n $SYSTEM_TEST ]]; then 27 | if [[ $TRAVIS_SECURE_ENV_VARS == "true" ]]; then 28 | echo 'Extracting secrets.' 29 | scripts/decrypt-secrets.sh "$SECRETS_PASSWORD" 30 | # Prevent build failures from leaking our password. 31 | # looking at you, Tox. 32 | export SECRETS_PASSWORD="" 33 | else 34 | # This is an external PR, so just mark system tests as green. 35 | echo 'In system test but secrets are not available, skipping.' 36 | exit 0 37 | fi 38 | fi 39 | 40 | # Run nox. 41 | echo "Running nox..." 42 | nox -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 -------------------------------------------------------------------------------- /system_tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/system_tests/__init__.py -------------------------------------------------------------------------------- /system_tests/secrets.tar.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/system_tests/secrets.tar.enc -------------------------------------------------------------------------------- /system_tests/system_tests_async/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/system_tests/system_tests_async/__init__.py -------------------------------------------------------------------------------- /system_tests/system_tests_async/test_default.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import pytest 17 | 18 | from google.auth import _default_async 19 | 20 | EXPECT_PROJECT_ID = os.environ.get("EXPECT_PROJECT_ID") 21 | 22 | @pytest.mark.asyncio 23 | async def test_application_default_credentials(verify_refresh): 24 | credentials, project_id = _default_async.default_async() 25 | 26 | if EXPECT_PROJECT_ID is not None: 27 | assert project_id is not None 28 | 29 | await verify_refresh(credentials) 30 | -------------------------------------------------------------------------------- /system_tests/system_tests_async/test_id_token.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import pytest 15 | 16 | from google.auth import jwt 17 | import google.oauth2._id_token_async 18 | 19 | @pytest.mark.asyncio 20 | async def test_fetch_id_token(http_request): 21 | audience = "https://pubsub.googleapis.com" 22 | token = await google.oauth2._id_token_async.fetch_id_token(http_request, audience) 23 | 24 | _, payload, _, _ = jwt._unverified_decode(token) 25 | assert payload["aud"] == audience 26 | -------------------------------------------------------------------------------- /system_tests/system_tests_async/test_service_account.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import pytest 16 | 17 | from google.auth import _helpers 18 | from google.auth import exceptions 19 | from google.auth import iam 20 | from google.oauth2 import _service_account_async 21 | 22 | 23 | @pytest.fixture 24 | def credentials(service_account_file): 25 | yield _service_account_async.Credentials.from_service_account_file(service_account_file) 26 | 27 | 28 | @pytest.mark.asyncio 29 | async def test_refresh_no_scopes(http_request, credentials): 30 | """ 31 | We expect the http request to refresh credentials 32 | without scopes provided to throw an error. 33 | """ 34 | with pytest.raises(exceptions.RefreshError): 35 | await credentials.refresh(http_request) 36 | 37 | @pytest.mark.asyncio 38 | async def test_refresh_success(http_request, credentials, token_info): 39 | credentials = credentials.with_scopes(["email", "profile"]) 40 | await credentials.refresh(http_request) 41 | 42 | assert credentials.token 43 | 44 | info = await token_info(credentials.token) 45 | 46 | assert info["email"] == credentials.service_account_email 47 | info_scopes = _helpers.string_to_scopes(info["scope"]) 48 | assert set(info_scopes) == set( 49 | [ 50 | "https://www.googleapis.com/auth/userinfo.email", 51 | "https://www.googleapis.com/auth/userinfo.profile", 52 | ] 53 | ) 54 | -------------------------------------------------------------------------------- /system_tests/system_tests_sync/.gitignore: -------------------------------------------------------------------------------- 1 | data 2 | secrets.tar -------------------------------------------------------------------------------- /system_tests/system_tests_sync/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/system_tests/system_tests_sync/__init__.py -------------------------------------------------------------------------------- /system_tests/system_tests_sync/secrets.tar.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/system_tests/system_tests_sync/secrets.tar.enc -------------------------------------------------------------------------------- /system_tests/system_tests_sync/test_compute_engine.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from datetime import datetime 16 | 17 | import pytest 18 | 19 | import google.auth 20 | from google.auth import compute_engine 21 | from google.auth import _helpers 22 | from google.auth import exceptions 23 | from google.auth import jwt 24 | from google.auth.compute_engine import _metadata 25 | import google.oauth2.id_token 26 | 27 | AUDIENCE = "https://pubsub.googleapis.com" 28 | 29 | 30 | @pytest.fixture(autouse=True) 31 | def check_gce_environment(http_request): 32 | try: 33 | _metadata.get_service_account_info(http_request) 34 | except exceptions.TransportError: 35 | pytest.skip("Compute Engine metadata service is not available.") 36 | 37 | 38 | def test_refresh(http_request, token_info): 39 | credentials = compute_engine.Credentials() 40 | 41 | credentials.refresh(http_request) 42 | 43 | assert credentials.token is not None 44 | assert credentials.service_account_email is not None 45 | 46 | info = token_info(credentials.token) 47 | info_scopes = _helpers.string_to_scopes(info["scope"]) 48 | assert set(info_scopes) == set(credentials.scopes) 49 | 50 | 51 | def test_default(verify_refresh): 52 | credentials, project_id = google.auth.default() 53 | 54 | assert project_id is not None 55 | assert isinstance(credentials, compute_engine.Credentials) 56 | verify_refresh(credentials) 57 | 58 | 59 | def test_id_token_from_metadata(http_request): 60 | credentials = compute_engine.IDTokenCredentials( 61 | http_request, AUDIENCE, use_metadata_identity_endpoint=True 62 | ) 63 | credentials.refresh(http_request) 64 | 65 | _, payload, _, _ = jwt._unverified_decode(credentials.token) 66 | assert credentials.valid 67 | assert payload["aud"] == AUDIENCE 68 | assert datetime.fromtimestamp(payload["exp"]) == credentials.expiry 69 | 70 | 71 | def test_fetch_id_token(http_request): 72 | token = google.oauth2.id_token.fetch_id_token(http_request, AUDIENCE) 73 | 74 | _, payload, _, _ = jwt._unverified_decode(token) 75 | assert payload["aud"] == AUDIENCE 76 | -------------------------------------------------------------------------------- /system_tests/system_tests_sync/test_default.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | 17 | import google.auth 18 | 19 | EXPECT_PROJECT_ID = os.environ.get("EXPECT_PROJECT_ID") 20 | 21 | 22 | def test_application_default_credentials(verify_refresh): 23 | credentials, project_id = google.auth.default() 24 | 25 | if EXPECT_PROJECT_ID is not None: 26 | assert project_id is not None 27 | 28 | verify_refresh(credentials) 29 | -------------------------------------------------------------------------------- /system_tests/system_tests_sync/test_grpc.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import google.auth 16 | import google.auth.credentials 17 | import google.auth.jwt 18 | import google.auth.transport.grpc 19 | from google.oauth2 import service_account 20 | 21 | from google.cloud import pubsub_v1 22 | 23 | 24 | def test_grpc_request_with_regular_credentials(http_request): 25 | credentials, project_id = google.auth.default() 26 | credentials = google.auth.credentials.with_scopes_if_required( 27 | credentials, scopes=["https://www.googleapis.com/auth/pubsub"] 28 | ) 29 | 30 | 31 | # Create a pub/sub client. 32 | client = pubsub_v1.PublisherClient(credentials=credentials) 33 | 34 | # list the topics and drain the iterator to test that an authorized API 35 | # call works. 36 | list_topics_iter = client.list_topics(project="projects/{}".format(project_id)) 37 | list(list_topics_iter) 38 | 39 | 40 | def test_grpc_request_with_regular_credentials_and_self_signed_jwt(http_request): 41 | credentials, project_id = google.auth.default() 42 | 43 | # At the time this test is being written, there are no GAPIC libraries 44 | # that will trigger the self-signed JWT flow. Manually create the self-signed 45 | # jwt on the service account credential to check that the request 46 | # succeeds. 47 | credentials = credentials.with_scopes( 48 | scopes=[], default_scopes=["https://www.googleapis.com/auth/pubsub"] 49 | ) 50 | credentials._create_self_signed_jwt(audience="https://pubsub.googleapis.com/") 51 | 52 | # Create a pub/sub client. 53 | client = pubsub_v1.PublisherClient(credentials=credentials) 54 | 55 | # list the topics and drain the iterator to test that an authorized API 56 | # call works. 57 | list_topics_iter = client.list_topics(project="projects/{}".format(project_id)) 58 | list(list_topics_iter) 59 | 60 | # Check that self-signed JWT was created and is being used 61 | assert credentials._jwt_credentials is not None 62 | assert credentials._jwt_credentials.token == credentials.token 63 | 64 | 65 | def test_grpc_request_with_jwt_credentials(): 66 | credentials, project_id = google.auth.default() 67 | audience = "https://pubsub.googleapis.com/google.pubsub.v1.Publisher" 68 | credentials = google.auth.jwt.Credentials.from_signing_credentials( 69 | credentials, audience=audience 70 | ) 71 | 72 | # Create a pub/sub client. 73 | client = pubsub_v1.PublisherClient(credentials=credentials) 74 | 75 | # list the topics and drain the iterator to test that an authorized API 76 | # call works. 77 | list_topics_iter = client.list_topics(project="projects/{}".format(project_id)) 78 | list(list_topics_iter) 79 | 80 | 81 | def test_grpc_request_with_on_demand_jwt_credentials(): 82 | credentials, project_id = google.auth.default() 83 | credentials = google.auth.jwt.OnDemandCredentials.from_signing_credentials( 84 | credentials 85 | ) 86 | 87 | # Create a pub/sub client. 88 | client = pubsub_v1.PublisherClient(credentials=credentials) 89 | 90 | # list the topics and drain the iterator to test that an authorized API 91 | # call works. 92 | list_topics_iter = client.list_topics(project="projects/{}".format(project_id)) 93 | list(list_topics_iter) 94 | -------------------------------------------------------------------------------- /system_tests/system_tests_sync/test_id_token.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import pytest 15 | 16 | from google.auth import jwt 17 | import google.oauth2.id_token 18 | 19 | 20 | def test_fetch_id_token(http_request): 21 | audience = "https://pubsub.googleapis.com" 22 | token = google.oauth2.id_token.fetch_id_token(http_request, audience) 23 | 24 | _, payload, _, _ = jwt._unverified_decode(token) 25 | assert payload["aud"] == audience 26 | -------------------------------------------------------------------------------- /system_tests/system_tests_sync/test_oauth2_credentials.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import json 16 | 17 | from google.auth import _helpers 18 | import google.oauth2.credentials 19 | 20 | GOOGLE_OAUTH2_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token" 21 | 22 | 23 | def test_refresh(authorized_user_file, http_request, token_info): 24 | with open(authorized_user_file, "r") as fh: 25 | info = json.load(fh) 26 | 27 | credentials = google.oauth2.credentials.Credentials( 28 | None, # No access token, must be refreshed. 29 | refresh_token=info["refresh_token"], 30 | token_uri=GOOGLE_OAUTH2_TOKEN_ENDPOINT, 31 | client_id=info["client_id"], 32 | client_secret=info["client_secret"], 33 | ) 34 | 35 | credentials.refresh(http_request) 36 | 37 | assert credentials.token 38 | 39 | info = token_info(credentials.token) 40 | 41 | info_scopes = _helpers.string_to_scopes(info["scope"]) 42 | 43 | # Canonical list of scopes at https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login 44 | # or do `gcloud auth application-defaut login --help` 45 | canonical_scopes = set( 46 | [ 47 | "https://www.googleapis.com/auth/userinfo.email", 48 | "https://www.googleapis.com/auth/cloud-platform", 49 | "openid", 50 | ] 51 | ) 52 | # When running the test locally, we always have an additional "accounts.reauth" scope. 53 | canonical_scopes_with_reauth = canonical_scopes.copy() 54 | canonical_scopes_with_reauth.add("https://www.googleapis.com/auth/accounts.reauth") 55 | assert set(info_scopes) == canonical_scopes or set(info_scopes) == canonical_scopes_with_reauth 56 | -------------------------------------------------------------------------------- /system_tests/system_tests_sync/test_requests.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import google.auth 16 | import google.auth.credentials 17 | import google.auth.transport.requests 18 | from google.oauth2 import service_account 19 | 20 | 21 | def test_authorized_session_with_service_account_and_self_signed_jwt(): 22 | credentials, project_id = google.auth.default() 23 | 24 | credentials = credentials.with_scopes( 25 | scopes=[], 26 | default_scopes=["https://www.googleapis.com/auth/pubsub"], 27 | ) 28 | 29 | session = google.auth.transport.requests.AuthorizedSession( 30 | credentials=credentials, default_host="pubsub.googleapis.com" 31 | ) 32 | 33 | # List Pub/Sub Topics through the REST API 34 | # https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/list 35 | url = "https://pubsub.googleapis.com/v1/projects/{}/topics".format(project_id) 36 | with session: 37 | response = session.get(url) 38 | response.raise_for_status() 39 | 40 | # Check that self-signed JWT was created and is being used 41 | assert credentials._jwt_credentials is not None 42 | assert credentials._jwt_credentials.token.decode() == credentials.token 43 | -------------------------------------------------------------------------------- /system_tests/system_tests_sync/test_service_account.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import pytest 16 | 17 | from google.auth import _helpers 18 | from google.auth import exceptions 19 | from google.auth import iam 20 | from google.oauth2 import service_account 21 | 22 | 23 | @pytest.fixture 24 | def credentials(service_account_file): 25 | yield service_account.Credentials.from_service_account_file(service_account_file) 26 | 27 | 28 | def test_refresh_no_scopes(http_request, credentials): 29 | with pytest.raises(exceptions.RefreshError): 30 | credentials.refresh(http_request) 31 | 32 | 33 | def test_refresh_success(http_request, credentials, token_info): 34 | credentials = credentials.with_scopes(["email", "profile"]) 35 | 36 | credentials.refresh(http_request) 37 | 38 | assert credentials.token 39 | 40 | info = token_info(credentials.token) 41 | 42 | assert info["email"] == credentials.service_account_email 43 | info_scopes = _helpers.string_to_scopes(info["scope"]) 44 | assert set(info_scopes) == set( 45 | [ 46 | "https://www.googleapis.com/auth/userinfo.email", 47 | "https://www.googleapis.com/auth/userinfo.profile", 48 | ] 49 | ) 50 | 51 | def test_iam_signer(http_request, credentials): 52 | credentials = credentials.with_scopes( 53 | ["https://www.googleapis.com/auth/iam"] 54 | ) 55 | 56 | # Verify iamcredentials signer. 57 | signer = iam.Signer( 58 | http_request, 59 | credentials, 60 | credentials.service_account_email 61 | ) 62 | 63 | signed_blob = signer.sign("message") 64 | 65 | assert isinstance(signed_blob, bytes) 66 | -------------------------------------------------------------------------------- /system_tests/system_tests_sync/test_urllib3.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import google.auth 16 | import google.auth.credentials 17 | import google.auth.transport.requests 18 | from google.oauth2 import service_account 19 | 20 | 21 | def test_authorized_session_with_service_account_and_self_signed_jwt(): 22 | credentials, project_id = google.auth.default() 23 | 24 | credentials = credentials.with_scopes( 25 | scopes=[], 26 | default_scopes=["https://www.googleapis.com/auth/pubsub"], 27 | ) 28 | 29 | http = google.auth.transport.urllib3.AuthorizedHttp( 30 | credentials=credentials, default_host="pubsub.googleapis.com" 31 | ) 32 | 33 | # List Pub/Sub Topics through the REST API 34 | # https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/list 35 | response = http.urlopen( 36 | method="GET", 37 | url="https://pubsub.googleapis.com/v1/projects/{}/topics".format(project_id) 38 | ) 39 | 40 | assert response.status == 200 41 | 42 | # Check that self-signed JWT was created and is being used 43 | assert credentials._jwt_credentials is not None 44 | assert credentials._jwt_credentials.token.decode() == credentials.token 45 | -------------------------------------------------------------------------------- /testing/constraints-3.10.txt: -------------------------------------------------------------------------------- 1 | urllib3<2.0.0 -------------------------------------------------------------------------------- /testing/constraints-3.11.txt: -------------------------------------------------------------------------------- 1 | urllib3>2.0.0 -------------------------------------------------------------------------------- /testing/constraints-3.12.txt: -------------------------------------------------------------------------------- 1 | urllib3>2.0.0 -------------------------------------------------------------------------------- /testing/constraints-3.13.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/testing/constraints-3.13.txt -------------------------------------------------------------------------------- /testing/constraints-3.7.txt: -------------------------------------------------------------------------------- 1 | # This constraints file is used to check that lower bounds 2 | # are correct in setup.py 3 | # List *all* library dependencies and extras in this file. 4 | # Pin the version to the lower bound. 5 | # 6 | # e.g., if setup.py has "foo >= 1.14.0, < 2.0.0dev", 7 | # Then this file should have foo==1.14.0 8 | cachetools==2.0.0 9 | pyasn1-modules==0.2.1 10 | setuptools==40.3.0 11 | rsa==3.1.4 12 | aiohttp==3.6.2 13 | requests==2.20.0 14 | pyjwt==2.0 -------------------------------------------------------------------------------- /testing/constraints-3.8.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/testing/constraints-3.8.txt -------------------------------------------------------------------------------- /testing/constraints-3.9.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/testing/constraints-3.9.txt -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests/__init__.py -------------------------------------------------------------------------------- /tests/compute_engine/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests/compute_engine/__init__.py -------------------------------------------------------------------------------- /tests/compute_engine/data/smbios_product_name: -------------------------------------------------------------------------------- 1 | Google Compute Engine 2 | -------------------------------------------------------------------------------- /tests/compute_engine/data/smbios_product_name_non_google: -------------------------------------------------------------------------------- 1 | ABC Compute Engine 2 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | 18 | import mock 19 | import pytest # type: ignore 20 | 21 | 22 | def pytest_configure(): 23 | """Load public certificate and private key.""" 24 | pytest.data_dir = os.path.join(os.path.dirname(__file__), "data") 25 | 26 | with open(os.path.join(pytest.data_dir, "privatekey.pem"), "rb") as fh: 27 | pytest.private_key_bytes = fh.read() 28 | 29 | with open(os.path.join(pytest.data_dir, "public_cert.pem"), "rb") as fh: 30 | pytest.public_cert_bytes = fh.read() 31 | 32 | 33 | @pytest.fixture 34 | def mock_non_existent_module(monkeypatch): 35 | """Mocks a non-existing module in sys.modules. 36 | 37 | Additionally mocks any non-existing modules specified in the dotted path. 38 | """ 39 | 40 | def _mock_non_existent_module(path): 41 | parts = path.split(".") 42 | partial = [] 43 | for part in parts: 44 | partial.append(part) 45 | current_module = ".".join(partial) 46 | if current_module not in sys.modules: 47 | monkeypatch.setitem(sys.modules, current_module, mock.MagicMock()) 48 | 49 | return _mock_non_existent_module 50 | -------------------------------------------------------------------------------- /tests/crypt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests/crypt/__init__.py -------------------------------------------------------------------------------- /tests/crypt/test_crypt.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | 17 | from google.auth import crypt 18 | 19 | 20 | DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data") 21 | 22 | # To generate privatekey.pem, privatekey.pub, and public_cert.pem: 23 | # $ openssl req -new -newkey rsa:1024 -x509 -nodes -out public_cert.pem \ 24 | # > -keyout privatekey.pem 25 | # $ openssl rsa -in privatekey.pem -pubout -out privatekey.pub 26 | 27 | with open(os.path.join(DATA_DIR, "privatekey.pem"), "rb") as fh: 28 | PRIVATE_KEY_BYTES = fh.read() 29 | 30 | with open(os.path.join(DATA_DIR, "public_cert.pem"), "rb") as fh: 31 | PUBLIC_CERT_BYTES = fh.read() 32 | 33 | # To generate other_cert.pem: 34 | # $ openssl req -new -newkey rsa:1024 -x509 -nodes -out other_cert.pem 35 | 36 | with open(os.path.join(DATA_DIR, "other_cert.pem"), "rb") as fh: 37 | OTHER_CERT_BYTES = fh.read() 38 | 39 | 40 | def test_verify_signature(): 41 | to_sign = b"foo" 42 | signer = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES) 43 | signature = signer.sign(to_sign) 44 | 45 | assert crypt.verify_signature(to_sign, signature, PUBLIC_CERT_BYTES) 46 | 47 | # List of certs 48 | assert crypt.verify_signature( 49 | to_sign, signature, [OTHER_CERT_BYTES, PUBLIC_CERT_BYTES] 50 | ) 51 | 52 | 53 | def test_verify_signature_failure(): 54 | to_sign = b"foo" 55 | signer = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES) 56 | signature = signer.sign(to_sign) 57 | 58 | assert not crypt.verify_signature(to_sign, signature, OTHER_CERT_BYTES) 59 | -------------------------------------------------------------------------------- /tests/data/authorized_user.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "123", 3 | "client_secret": "secret", 4 | "refresh_token": "alabalaportocala", 5 | "type": "authorized_user" 6 | } 7 | -------------------------------------------------------------------------------- /tests/data/authorized_user_cloud_sdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com", 3 | "client_secret": "secret", 4 | "refresh_token": "alabalaportocala", 5 | "type": "authorized_user" 6 | } 7 | -------------------------------------------------------------------------------- /tests/data/authorized_user_cloud_sdk_with_quota_project_id.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com", 3 | "client_secret": "secret", 4 | "refresh_token": "alabalaportocala", 5 | "type": "authorized_user", 6 | "quota_project_id": "quota_project_id" 7 | } 8 | -------------------------------------------------------------------------------- /tests/data/authorized_user_with_rapt_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "123", 3 | "client_secret": "secret", 4 | "refresh_token": "alabalaportocala", 5 | "type": "authorized_user", 6 | "rapt_token": "rapt" 7 | } 8 | -------------------------------------------------------------------------------- /tests/data/client_secrets.json: -------------------------------------------------------------------------------- 1 | { 2 | "web": { 3 | "client_id": "example.apps.googleusercontent.com", 4 | "project_id": "example", 5 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 6 | "token_uri": "https://accounts.google.com/o/oauth2/token", 7 | "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 8 | "client_secret": "itsasecrettoeveryone", 9 | "redirect_uris": [ 10 | "urn:ietf:wg:oauth:2.0:oob", 11 | "http://localhost" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/data/context_aware_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "cert_provider_command":[ 3 | "/opt/google/endpoint-verification/bin/SecureConnectHelper", 4 | "--print_certificate"], 5 | "device_resource_ids":["11111111-1111-1111"] 6 | } 7 | -------------------------------------------------------------------------------- /tests/data/enterprise_cert_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "libs": {} 3 | } -------------------------------------------------------------------------------- /tests/data/enterprise_cert_valid.json: -------------------------------------------------------------------------------- 1 | { 2 | "libs": { 3 | "ecp_client": "/path/to/signer/lib", 4 | "tls_offload": "/path/to/offload/lib" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/data/enterprise_cert_valid_provider.json: -------------------------------------------------------------------------------- 1 | { 2 | "libs": { 3 | "ecp_client": "/path/to/signer/lib", 4 | "ecp_provider": "/path/to/provider/lib" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/data/es256_privatekey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIAIC57aTx5ev4T2HBMQk4fXV09AzLDQ3Ju1uNoEB0LngoAoGCCqGSM49 3 | AwEHoUQDQgAEsACsrmP6Bp216OCFm73C8W/VRHZWcO8yU/bMwx96f05BkTII3KeJ 4 | z2O0IRAnXfso8K6YsjMuUDGCfj+b1IDIoA== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /tests/data/es256_public_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBGDCBwAIJAPUA0H4EQWsdMAoGCCqGSM49BAMCMBUxEzARBgNVBAMMCnVuaXQt 3 | dGVzdHMwHhcNMTkwNTA5MDI1MDExWhcNMTkwNjA4MDI1MDExWjAVMRMwEQYDVQQD 4 | DAp1bml0LXRlc3RzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsACsrmP6Bp21 5 | 6OCFm73C8W/VRHZWcO8yU/bMwx96f05BkTII3KeJz2O0IRAnXfso8K6YsjMuUDGC 6 | fj+b1IDIoDAKBggqhkjOPQQDAgNHADBEAh8PcDTMyWk8SHqV/v8FLuMbDxdtAsq2 7 | dwCpuHQwqCcmAiEAnwtkiyieN+8zozaf1P4QKp2mAqNGqua50y3ua5uVotc= 8 | -----END CERTIFICATE----- 9 | -------------------------------------------------------------------------------- /tests/data/es256_publickey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsACsrmP6Bp216OCFm73C8W/VRHZW 3 | cO8yU/bMwx96f05BkTII3KeJz2O0IRAnXfso8K6YsjMuUDGCfj+b1IDIoA== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /tests/data/es256_service_account.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "project_id": "example-project", 4 | "private_key_id": "1", 5 | "private_key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIAIC57aTx5ev4T2HBMQk4fXV09AzLDQ3Ju1uNoEB0LngoAoGCCqGSM49\nAwEHoUQDQgAEsACsrmP6Bp216OCFm73C8W/VRHZWcO8yU/bMwx96f05BkTII3KeJ\nz2O0IRAnXfso8K6YsjMuUDGCfj+b1IDIoA==\n-----END EC PRIVATE KEY-----", 6 | "client_email": "service-account@example.com", 7 | "client_id": "1234", 8 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 9 | "token_uri": "https://accounts.google.com/o/oauth2/token" 10 | } 11 | -------------------------------------------------------------------------------- /tests/data/external_account_authorized_user.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "external_account_authorized_user", 3 | "audience": "//iam.googleapis.com/locations/global/workforcePools/$WORKFORCE_POOL_ID/providers/$PROVIDER_ID", 4 | "refresh_token": "refreshToken", 5 | "token_url": "https://sts.googleapis.com/v1/oauth/token", 6 | "token_info_url": "https://sts.googleapis.com/v1/instrospect", 7 | "client_id": "clientId", 8 | "client_secret": "clientSecret" 9 | } 10 | -------------------------------------------------------------------------------- /tests/data/external_account_authorized_user_non_gdu.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "external_account_authorized_user", 3 | "audience": "//iam.fake_universe_domain/locations/global/workforcePools/$WORKFORCE_POOL_ID/providers/$PROVIDER_ID", 4 | "refresh_token": "refreshToken", 5 | "token_url": "https://sts.fake_universe_domain/v1/oauth/token", 6 | "token_info_url": "https://sts.fake_universe_domain/v1/instrospect", 7 | "client_id": "clientId", 8 | "client_secret": "clientSecret", 9 | "universe_domain": "fake_universe_domain" 10 | } 11 | -------------------------------------------------------------------------------- /tests/data/external_subject_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "access_token": "HEADER.SIMULATED_JWT_PAYLOAD.SIGNATURE" 3 | } -------------------------------------------------------------------------------- /tests/data/external_subject_token.txt: -------------------------------------------------------------------------------- 1 | HEADER.SIMULATED_JWT_PAYLOAD.SIGNATURE -------------------------------------------------------------------------------- /tests/data/gdch_service_account.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "gdch_service_account", 3 | "format_version": "1", 4 | "project": "project_foo", 5 | "private_key_id": "key_foo", 6 | "private_key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIIGb2np7v54Hs6++NiLE7CQtQg7rzm4znstHvrOUlcMMoAoGCCqGSM49\nAwEHoUQDQgAECvv0VyZS9nYOa8tdwKCbkNxlWgrAZVClhJXqrvOZHlH4N3d8Rplk\n2DEJvzp04eMxlHw1jm6JCs3iJR6KAokG+w==\n-----END EC PRIVATE KEY-----\n", 7 | "name": "service_identity_name", 8 | "ca_cert_path": "/path/to/ca/cert", 9 | "token_uri": "https://service-identity./authenticate" 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/data/impersonated_service_account_authorized_user_source.json: -------------------------------------------------------------------------------- 1 | { 2 | "delegates": [ 3 | "service-account-delegate@example.com" 4 | ], 5 | "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-target@example.com:generateAccessToken", 6 | "source_credentials": { 7 | "client_id": "123", 8 | "client_secret": "secret", 9 | "refresh_token": "alabalaportocala", 10 | "type": "authorized_user" 11 | }, 12 | "type": "impersonated_service_account" 13 | } -------------------------------------------------------------------------------- /tests/data/impersonated_service_account_external_account_authorized_user_source.json: -------------------------------------------------------------------------------- 1 | { 2 | "delegates": [ 3 | "service-account-delegate@example.com" 4 | ], 5 | "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-target@example.com:generateAccessToken", 6 | "source_credentials": { 7 | "type": "external_account_authorized_user", 8 | "audience": "//iam.googleapis.com/locations/global/workforcePools/$WORKFORCE_POOL_ID/providers/$PROVIDER_ID", 9 | "refresh_token": "refreshToken", 10 | "token_url": "https://sts.googleapis.com/v1/oauth/token", 11 | "token_info_url": "https://sts.googleapis.com/v1/instrospect", 12 | "client_id": "clientId", 13 | "client_secret": "clientSecret" 14 | }, 15 | "type": "impersonated_service_account" 16 | } -------------------------------------------------------------------------------- /tests/data/impersonated_service_account_service_account_source.json: -------------------------------------------------------------------------------- 1 | { 2 | "delegates": [ 3 | "service-account-delegate@example.com" 4 | ], 5 | "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-target@example.com:generateAccessToken", 6 | "source_credentials": { 7 | "type": "service_account", 8 | "project_id": "example-project", 9 | "private_key_id": "1", 10 | "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj\n7wZgkdmM7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/\nxmVU1WeruQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYs\nSliS5qQpgyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18\npe+zpyl4+WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xk\nSBc//fy3ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABAoIBAQDGGHzQxGKX+ANk\nnQi53v/c6632dJKYXVJC+PDAz4+bzU800Y+n/bOYsWf/kCp94XcG4Lgsdd0Gx+Zq\nHD9CI1IcqqBRR2AFscsmmX6YzPLTuEKBGMW8twaYy3utlFxElMwoUEsrSWRcCA1y\nnHSDzTt871c7nxCXHxuZ6Nm/XCL7Bg8uidRTSC1sQrQyKgTPhtQdYrPQ4WZ1A4J9\nIisyDYmZodSNZe5P+LTJ6M1SCgH8KH9ZGIxv3diMwzNNpk3kxJc9yCnja4mjiGE2\nYCNusSycU5IhZwVeCTlhQGcNeV/skfg64xkiJE34c2y2ttFbdwBTPixStGaF09nU\nZ422D40BAoGBAPvVyRRsC3BF+qZdaSMFwI1yiXY7vQw5+JZh01tD28NuYdRFzjcJ\nvzT2n8LFpj5ZfZFvSMLMVEFVMgQvWnN0O6xdXvGov6qlRUSGaH9u+TCPNnIldjMP\nB8+xTwFMqI7uQr54wBB+Poq7dVRP+0oHb0NYAwUBXoEuvYo3c/nDoRcZAoGBAOWl\naLHjMv4CJbArzT8sPfic/8waSiLV9Ixs3Re5YREUTtnLq7LoymqB57UXJB3BNz/2\neCueuW71avlWlRtE/wXASj5jx6y5mIrlV4nZbVuyYff0QlcG+fgb6pcJQuO9DxMI\naqFGrWP3zye+LK87a6iR76dS9vRU+bHZpSVvGMKJAoGAFGt3TIKeQtJJyqeUWNSk\nklORNdcOMymYMIlqG+JatXQD1rR6ThgqOt8sgRyJqFCVT++YFMOAqXOBBLnaObZZ\nCFbh1fJ66BlSjoXff0W+SuOx5HuJJAa5+WtFHrPajwxeuRcNa8jwxUsB7n41wADu\nUqWWSRedVBg4Ijbw3nWwYDECgYB0pLew4z4bVuvdt+HgnJA9n0EuYowVdadpTEJg\nsoBjNHV4msLzdNqbjrAqgz6M/n8Ztg8D2PNHMNDNJPVHjJwcR7duSTA6w2p/4k28\nbvvk/45Ta3XmzlxZcZSOct3O31Cw0i2XDVc018IY5be8qendDYM08icNo7vQYkRH\n504kQQKBgQDjx60zpz8ozvm1XAj0wVhi7GwXe+5lTxiLi9Fxq721WDxPMiHDW2XL\nYXfFVy/9/GIMvEiGYdmarK1NW+VhWl1DC5xhDg0kvMfxplt4tynoq1uTsQTY31Mx\nBeF5CT/JuNYk3bEBF0H/Q3VGO1/ggVS+YezdFbLWIRoMnLj6XCFEGg==\n-----END RSA PRIVATE KEY-----\n", 11 | "client_email": "service-account@example.com", 12 | "client_id": "1234", 13 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 14 | "token_uri": "https://accounts.google.com/o/oauth2/token" 15 | }, 16 | "type": "impersonated_service_account" 17 | } -------------------------------------------------------------------------------- /tests/data/impersonated_service_account_with_quota_project.json: -------------------------------------------------------------------------------- 1 | { 2 | "delegates": [ 3 | "service-account-delegate@example.com" 4 | ], 5 | "quota_project_id": "quota_project", 6 | "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/service-account-target@example.com:generateAccessToken", 7 | "source_credentials": { 8 | "client_id": "123", 9 | "client_secret": "secret", 10 | "refresh_token": "alabalaportocala", 11 | "type": "authorized_user" 12 | }, 13 | "type": "impersonated_service_account" 14 | } -------------------------------------------------------------------------------- /tests/data/old_oauth_credentials_py3.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests/data/old_oauth_credentials_py3.pickle -------------------------------------------------------------------------------- /tests/data/other_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFtTCCA52gAwIBAgIJAPBsLZmNGfKtMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMTYwOTIxMDI0NTEyWhcNMTYxMDIxMDI0NTEyWjBF 5 | MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 7 | CgKCAgEAsiMC7mTsmUXwZoYlT4aHY1FLw8bxIXC+z3IqA+TY1WqfbeiZRo8MA5Zx 8 | lTTxYMKPCZUE1XBc7jvD8GJhWIj6pToPYHn73B01IBkLBxq4kF1yV2Z7DVmkvc6H 9 | EcxXXq8zkCx0j6XOfiI4+qkXnuQn8cvrk8xfhtnMMZM7iVm6VSN93iRP/8ey6xuL 10 | XTHrDX7ukoRce1hpT8O+15GXNrY0irhhYQz5xKibNCJF3EjV28WMry8y7I8uYUFU 11 | RWDiQawwK9ec1zhZ94v92+GZDlPevmcFmSERKYQ0NsKcT0Y3lGuGnaExs8GyOpnC 12 | oksu4YJGXQjg7lkv4MxzsNbRqmCkUwxw1Mg6FP0tsCNsw9qTrkvWCRA9zp/aU+sZ 13 | IBGh1t4UGCub8joeQFvHxvr/3F7mH/dyvCjA34u0Lo1VPx+jYUIi9i0odltMspDW 14 | xOpjqdGARZYmlJP5Au9q5cQjPMcwS/EBIb8cwNl32mUE6WnFlep+38mNR/FghIjO 15 | ViAkXuKQmcHe6xppZAoHFsO/t3l4Tjek5vNW7erI1rgrFku/fvkIW/G8V1yIm/+Q 16 | F+CE4maQzCJfhftpkhM/sPC/FuLNBmNE8BHVX8y58xG4is/cQxL4Z9TsFIw0C5+3 17 | uTrFW9D0agysahMVzPGtCqhDQqJdIJrBQqlS6bztpzBA8zEI0skCAwEAAaOBpzCB 18 | pDAdBgNVHQ4EFgQUz/8FmW6TfqXyNJZr7rhc+Tn5sKQwdQYDVR0jBG4wbIAUz/8F 19 | mW6TfqXyNJZr7rhc+Tn5sKShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT 20 | b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDw 21 | bC2ZjRnyrTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCQmrcfhurX 22 | riR3Q0Y+nq040/3dJIAJXjyI9CEtxaU0nzCNTng7PwgZ0CKmCelQfInuwWFwBSHS 23 | 6kBfC1rgJeFnjnTt8a3RCgRlIgUr9NCdPSEccB7TurobwPJ2h6cJjjR8urcb0CXh 24 | CEMvPneyPj0xUFY8vVKXMGWahz/kyfwIiVqcX/OtMZ29fUu1onbWl71g2gVLtUZl 25 | sECdZ+AC/6HDCVpYIVETMl1T7N/XyqXZQiDLDNRDeZhnapz8w9fsW1KVujAZLNQR 26 | pVnw2qa2UK1dSf2FHX+lQU5mFSYM4vtwaMlX/LgfdLZ9I796hFh619WwTVz+LO2N 27 | vHnwBMabld3XSPuZRqlbBulDQ07Vbqdjv8DYSLA2aKI4ZkMMKuFLG/oS28V2ZYmv 28 | /KpGEs5UgKY+P9NulYpTDwCU/6SomuQpP795wbG6sm7Hzq82r2RmB61GupNRGeqi 29 | pXKsy69T388zBxYu6zQrosXiDl5YzaViH7tm0J7opye8dCWjjpnahki0vq2znti7 30 | 6cWla2j8Xz1glvLz+JI/NCOMfxUInb82T7ijo80N0VJ2hzf7p2GxRZXAxAV9knLI 31 | nM4F5TLjSd7ZhOOZ7ni/eZFueTMisWfypt2nc41whGjHMX/Zp1kPfhB4H2bLKIX/ 32 | lSrwNr3qbGTEJX8JqpDBNVAd96XkMvDNyA== 33 | -----END CERTIFICATE----- 34 | -------------------------------------------------------------------------------- /tests/data/pem_from_pkcs12.pem: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | friendlyName: key 3 | localKeyID: 22 7E 04 FC 64 48 20 83 1E C1 BD E3 F5 2F 44 7D EA 99 A5 BC 4 | Key Attributes: 5 | -----BEGIN PRIVATE KEY----- 6 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDh6PSnttDsv+vi 7 | tUZTP1E3hVBah6PUGDWZhYgNiyW8quTWCmPvBmCR2YzuhUrY5+CtKP8UJOQico+p 8 | oJHSAPsrzSr6YsGs3c9SQOslBmm9Fkh9/f/GZVTVZ6u5AsUmOcVvZ2q7Sz8Vj/aR 9 | aIm0EJqRe9cQ5vvN9sg25rIv4xKwIZJ1VixKWJLmpCmDINqn7xvl+ldlUmSr3aGt 10 | w21uSDuEJhQlzO3yf2FwJMkJ9SkCm9oVDXyl77OnKXj5bOQ/rojbyGeIxDJSUDWE 11 | GKyRPuqKi6rSbwg6h2G/Z9qBJkqM5NNTbGRIFz/9/LdmmwvtaqCxlLtD7RVEryAp 12 | +qTGDk5hAgMBAAECggEBAMYYfNDEYpf4A2SdCLne/9zrrfZ0kphdUkL48MDPj5vN 13 | TzTRj6f9s5ixZ/+QKn3hdwbguCx13QbH5mocP0IjUhyqoFFHYAWxyyaZfpjM8tO4 14 | QoEYxby3BpjLe62UXESUzChQSytJZFwIDXKcdIPNO3zvVzufEJcfG5no2b9cIvsG 15 | Dy6J1FNILWxCtDIqBM+G1B1is9DhZnUDgn0iKzINiZmh1I1l7k/4tMnozVIKAfwo 16 | f1kYjG/d2IzDM02mTeTElz3IKeNriaOIYTZgI26xLJxTkiFnBV4JOWFAZw15X+yR 17 | +DrjGSIkTfhzbLa20Vt3AFM+LFK0ZoXT2dRnjbYPjQECgYEA+9XJFGwLcEX6pl1p 18 | IwXAjXKJdju9DDn4lmHTW0Pbw25h1EXONwm/NPafwsWmPll9kW9IwsxUQVUyBC9a 19 | c3Q7rF1e8ai/qqVFRIZof275MI82ciV2Mw8Hz7FPAUyoju5CvnjAEH4+irt1VE/7 20 | SgdvQ1gDBQFegS69ijdz+cOhFxkCgYEA5aVoseMy/gIlsCvNPyw9+Jz/zBpKItX0 21 | jGzdF7lhERRO2cursujKaoHntRckHcE3P/Z4K565bvVq+VaVG0T/BcBKPmPHrLmY 22 | iuVXidltW7Jh9/RCVwb5+BvqlwlC470PEwhqoUatY/fPJ74srztrqJHvp1L29FT5 23 | sdmlJW8YwokCgYAUa3dMgp5C0knKp5RY1KSSU5E11w4zKZgwiWob4lq1dAPWtHpO 24 | GCo63yyBHImoUJVP75gUw4Cpc4EEudo5tlkIVuHV8nroGVKOhd9/Rb5K47Hke4kk 25 | Brn5a0Ues9qPDF65Fw1ryPDFSwHufjXAAO5SpZZJF51UGDgiNvDedbBgMQKBgHSk 26 | t7DjPhtW69234eCckD2fQS5ijBV1p2lMQmCygGM0dXiawvN02puOsCqDPoz+fxm2 27 | DwPY80cw0M0k9UeMnBxHt25JMDrDan/iTbxu++T/jlNrdebOXFlxlI5y3c7fULDS 28 | LZcNVzTXwhjlt7yp6d0NgzTyJw2ju9BiREfnTiRBAoGBAOPHrTOnPyjO+bVcCPTB 29 | WGLsbBd77mVPGIuL0XGrvbVYPE8yIcNbZcthd8VXL/38Ygy8SIZh2ZqsrU1b5WFa 30 | XUMLnGEODSS8x/GmW3i3KeirW5OxBNjfUzEF4XkJP8m41iTdsQEXQf9DdUY7X+CB 31 | VL5h7N0VstYhGgycuPpcIUQa 32 | -----END PRIVATE KEY----- 33 | -------------------------------------------------------------------------------- /tests/data/privatekey.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests/data/privatekey.p12 -------------------------------------------------------------------------------- /tests/data/privatekey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj 3 | 7wZgkdmM7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/ 4 | xmVU1WeruQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYs 5 | SliS5qQpgyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18 6 | pe+zpyl4+WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xk 7 | SBc//fy3ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABAoIBAQDGGHzQxGKX+ANk 8 | nQi53v/c6632dJKYXVJC+PDAz4+bzU800Y+n/bOYsWf/kCp94XcG4Lgsdd0Gx+Zq 9 | HD9CI1IcqqBRR2AFscsmmX6YzPLTuEKBGMW8twaYy3utlFxElMwoUEsrSWRcCA1y 10 | nHSDzTt871c7nxCXHxuZ6Nm/XCL7Bg8uidRTSC1sQrQyKgTPhtQdYrPQ4WZ1A4J9 11 | IisyDYmZodSNZe5P+LTJ6M1SCgH8KH9ZGIxv3diMwzNNpk3kxJc9yCnja4mjiGE2 12 | YCNusSycU5IhZwVeCTlhQGcNeV/skfg64xkiJE34c2y2ttFbdwBTPixStGaF09nU 13 | Z422D40BAoGBAPvVyRRsC3BF+qZdaSMFwI1yiXY7vQw5+JZh01tD28NuYdRFzjcJ 14 | vzT2n8LFpj5ZfZFvSMLMVEFVMgQvWnN0O6xdXvGov6qlRUSGaH9u+TCPNnIldjMP 15 | B8+xTwFMqI7uQr54wBB+Poq7dVRP+0oHb0NYAwUBXoEuvYo3c/nDoRcZAoGBAOWl 16 | aLHjMv4CJbArzT8sPfic/8waSiLV9Ixs3Re5YREUTtnLq7LoymqB57UXJB3BNz/2 17 | eCueuW71avlWlRtE/wXASj5jx6y5mIrlV4nZbVuyYff0QlcG+fgb6pcJQuO9DxMI 18 | aqFGrWP3zye+LK87a6iR76dS9vRU+bHZpSVvGMKJAoGAFGt3TIKeQtJJyqeUWNSk 19 | klORNdcOMymYMIlqG+JatXQD1rR6ThgqOt8sgRyJqFCVT++YFMOAqXOBBLnaObZZ 20 | CFbh1fJ66BlSjoXff0W+SuOx5HuJJAa5+WtFHrPajwxeuRcNa8jwxUsB7n41wADu 21 | UqWWSRedVBg4Ijbw3nWwYDECgYB0pLew4z4bVuvdt+HgnJA9n0EuYowVdadpTEJg 22 | soBjNHV4msLzdNqbjrAqgz6M/n8Ztg8D2PNHMNDNJPVHjJwcR7duSTA6w2p/4k28 23 | bvvk/45Ta3XmzlxZcZSOct3O31Cw0i2XDVc018IY5be8qendDYM08icNo7vQYkRH 24 | 504kQQKBgQDjx60zpz8ozvm1XAj0wVhi7GwXe+5lTxiLi9Fxq721WDxPMiHDW2XL 25 | YXfFVy/9/GIMvEiGYdmarK1NW+VhWl1DC5xhDg0kvMfxplt4tynoq1uTsQTY31Mx 26 | BeF5CT/JuNYk3bEBF0H/Q3VGO1/ggVS+YezdFbLWIRoMnLj6XCFEGg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /tests/data/privatekey.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PUBLIC KEY----- 2 | MIIBCgKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj7wZg 3 | kdmM7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/xmVU 4 | 1WeruQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYsSliS 5 | 5qQpgyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18pe+z 6 | pyl4+WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xkSBc/ 7 | /fy3ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQAB 8 | -----END RSA PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /tests/data/public_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDIzCCAgugAwIBAgIJAMfISuBQ5m+5MA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV 3 | BAMTCnVuaXQtdGVzdHMwHhcNMTExMjA2MTYyNjAyWhcNMjExMjAzMTYyNjAyWjAV 4 | MRMwEQYDVQQDEwp1bml0LXRlc3RzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 5 | CgKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj7wZgkdmM 6 | 7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/xmVU1Wer 7 | uQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYsSliS5qQp 8 | gyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18pe+zpyl4 9 | +WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xkSBc//fy3 10 | ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABo3YwdDAdBgNVHQ4EFgQU2RQ8yO+O 11 | gN8oVW2SW7RLrfYd9jEwRQYDVR0jBD4wPIAU2RQ8yO+OgN8oVW2SW7RLrfYd9jGh 12 | GaQXMBUxEzARBgNVBAMTCnVuaXQtdGVzdHOCCQDHyErgUOZvuTAMBgNVHRMEBTAD 13 | AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBRv+M/6+FiVu7KXNjFI5pSN17OcW5QUtPr 14 | odJMlWrJBtynn/TA1oJlYu3yV5clc/71Vr/AxuX5xGP+IXL32YDF9lTUJXG/uUGk 15 | +JETpKmQviPbRsvzYhz4pf6ZIOZMc3/GIcNq92ECbseGO+yAgyWUVKMmZM0HqXC9 16 | ovNslqe0M8C1sLm1zAR5z/h/litE7/8O2ietija3Q/qtl2TOXJdCA6sgjJX2WUql 17 | ybrC55ct18NKf3qhpcEkGQvFU40rVYApJpi98DiZPYFdx1oBDp/f4uZ3ojpxRVFT 18 | cDwcJLfNRCPUhormsY7fDS9xSyThiHsW9mjJYdcaKQkwYZ0F11yB 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /tests/data/service_account.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "project_id": "example-project", 4 | "private_key_id": "1", 5 | "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj\n7wZgkdmM7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/\nxmVU1WeruQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYs\nSliS5qQpgyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18\npe+zpyl4+WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xk\nSBc//fy3ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABAoIBAQDGGHzQxGKX+ANk\nnQi53v/c6632dJKYXVJC+PDAz4+bzU800Y+n/bOYsWf/kCp94XcG4Lgsdd0Gx+Zq\nHD9CI1IcqqBRR2AFscsmmX6YzPLTuEKBGMW8twaYy3utlFxElMwoUEsrSWRcCA1y\nnHSDzTt871c7nxCXHxuZ6Nm/XCL7Bg8uidRTSC1sQrQyKgTPhtQdYrPQ4WZ1A4J9\nIisyDYmZodSNZe5P+LTJ6M1SCgH8KH9ZGIxv3diMwzNNpk3kxJc9yCnja4mjiGE2\nYCNusSycU5IhZwVeCTlhQGcNeV/skfg64xkiJE34c2y2ttFbdwBTPixStGaF09nU\nZ422D40BAoGBAPvVyRRsC3BF+qZdaSMFwI1yiXY7vQw5+JZh01tD28NuYdRFzjcJ\nvzT2n8LFpj5ZfZFvSMLMVEFVMgQvWnN0O6xdXvGov6qlRUSGaH9u+TCPNnIldjMP\nB8+xTwFMqI7uQr54wBB+Poq7dVRP+0oHb0NYAwUBXoEuvYo3c/nDoRcZAoGBAOWl\naLHjMv4CJbArzT8sPfic/8waSiLV9Ixs3Re5YREUTtnLq7LoymqB57UXJB3BNz/2\neCueuW71avlWlRtE/wXASj5jx6y5mIrlV4nZbVuyYff0QlcG+fgb6pcJQuO9DxMI\naqFGrWP3zye+LK87a6iR76dS9vRU+bHZpSVvGMKJAoGAFGt3TIKeQtJJyqeUWNSk\nklORNdcOMymYMIlqG+JatXQD1rR6ThgqOt8sgRyJqFCVT++YFMOAqXOBBLnaObZZ\nCFbh1fJ66BlSjoXff0W+SuOx5HuJJAa5+WtFHrPajwxeuRcNa8jwxUsB7n41wADu\nUqWWSRedVBg4Ijbw3nWwYDECgYB0pLew4z4bVuvdt+HgnJA9n0EuYowVdadpTEJg\nsoBjNHV4msLzdNqbjrAqgz6M/n8Ztg8D2PNHMNDNJPVHjJwcR7duSTA6w2p/4k28\nbvvk/45Ta3XmzlxZcZSOct3O31Cw0i2XDVc018IY5be8qendDYM08icNo7vQYkRH\n504kQQKBgQDjx60zpz8ozvm1XAj0wVhi7GwXe+5lTxiLi9Fxq721WDxPMiHDW2XL\nYXfFVy/9/GIMvEiGYdmarK1NW+VhWl1DC5xhDg0kvMfxplt4tynoq1uTsQTY31Mx\nBeF5CT/JuNYk3bEBF0H/Q3VGO1/ggVS+YezdFbLWIRoMnLj6XCFEGg==\n-----END RSA PRIVATE KEY-----\n", 6 | "client_email": "service-account@example.com", 7 | "client_id": "1234", 8 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 9 | "token_uri": "https://accounts.google.com/o/oauth2/token" 10 | } 11 | -------------------------------------------------------------------------------- /tests/data/service_account_non_gdu.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "universe_domain": "universe.foo", 4 | "project_id": "example_project", 5 | "private_key_id": "1", 6 | "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj\n7wZgkdmM7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/\nxmVU1WeruQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYs\nSliS5qQpgyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18\npe+zpyl4+WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xk\nSBc//fy3ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABAoIBAQDGGHzQxGKX+ANk\nnQi53v/c6632dJKYXVJC+PDAz4+bzU800Y+n/bOYsWf/kCp94XcG4Lgsdd0Gx+Zq\nHD9CI1IcqqBRR2AFscsmmX6YzPLTuEKBGMW8twaYy3utlFxElMwoUEsrSWRcCA1y\nnHSDzTt871c7nxCXHxuZ6Nm/XCL7Bg8uidRTSC1sQrQyKgTPhtQdYrPQ4WZ1A4J9\nIisyDYmZodSNZe5P+LTJ6M1SCgH8KH9ZGIxv3diMwzNNpk3kxJc9yCnja4mjiGE2\nYCNusSycU5IhZwVeCTlhQGcNeV/skfg64xkiJE34c2y2ttFbdwBTPixStGaF09nU\nZ422D40BAoGBAPvVyRRsC3BF+qZdaSMFwI1yiXY7vQw5+JZh01tD28NuYdRFzjcJ\nvzT2n8LFpj5ZfZFvSMLMVEFVMgQvWnN0O6xdXvGov6qlRUSGaH9u+TCPNnIldjMP\nB8+xTwFMqI7uQr54wBB+Poq7dVRP+0oHb0NYAwUBXoEuvYo3c/nDoRcZAoGBAOWl\naLHjMv4CJbArzT8sPfic/8waSiLV9Ixs3Re5YREUTtnLq7LoymqB57UXJB3BNz/2\neCueuW71avlWlRtE/wXASj5jx6y5mIrlV4nZbVuyYff0QlcG+fgb6pcJQuO9DxMI\naqFGrWP3zye+LK87a6iR76dS9vRU+bHZpSVvGMKJAoGAFGt3TIKeQtJJyqeUWNSk\nklORNdcOMymYMIlqG+JatXQD1rR6ThgqOt8sgRyJqFCVT++YFMOAqXOBBLnaObZZ\nCFbh1fJ66BlSjoXff0W+SuOx5HuJJAa5+WtFHrPajwxeuRcNa8jwxUsB7n41wADu\nUqWWSRedVBg4Ijbw3nWwYDECgYB0pLew4z4bVuvdt+HgnJA9n0EuYowVdadpTEJg\nsoBjNHV4msLzdNqbjrAqgz6M/n8Ztg8D2PNHMNDNJPVHjJwcR7duSTA6w2p/4k28\nbvvk/45Ta3XmzlxZcZSOct3O31Cw0i2XDVc018IY5be8qendDYM08icNo7vQYkRH\n504kQQKBgQDjx60zpz8ozvm1XAj0wVhi7GwXe+5lTxiLi9Fxq721WDxPMiHDW2XL\nYXfFVy/9/GIMvEiGYdmarK1NW+VhWl1DC5xhDg0kvMfxplt4tynoq1uTsQTY31Mx\nBeF5CT/JuNYk3bEBF0H/Q3VGO1/ggVS+YezdFbLWIRoMnLj6XCFEGg==\n-----END RSA PRIVATE KEY-----\n", 7 | "client_email": "testsa@foo.iam.gserviceaccount.com", 8 | "client_id": "1234", 9 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 10 | "token_uri": "https://oauth2.universe.foo/token", 11 | "auth_provider_x509_cert_url": "https://www.universe.foo/oauth2/v1/certs", 12 | "client_x509_cert_url": "https://www.universe.foo/robot/v1/metadata/x509/foo.iam.gserviceaccount.com" 13 | } 14 | 15 | -------------------------------------------------------------------------------- /tests/data/trust_chain_with_leaf.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDIzCCAgugAwIBAgIJAMfISuBQ5m+5MA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV 3 | BAMTCnVuaXQtdGVzdHMwHhcNMTExMjA2MTYyNjAyWhcNMjExMjAzMTYyNjAyWjAV 4 | MRMwEQYDVQQDEwp1bml0LXRlc3RzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 5 | CgKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj7wZgkdmM 6 | 7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/xmVU1Wer 7 | uQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYsSliS5qQp 8 | gyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18pe+zpyl4 9 | +WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xkSBc//fy3 10 | ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABo3YwdDAdBgNVHQ4EFgQU2RQ8yO+O 11 | gN8oVW2SW7RLrfYd9jEwRQYDVR0jBD4wPIAU2RQ8yO+OgN8oVW2SW7RLrfYd9jGh 12 | GaQXMBUxEzARBgNVBAMTCnVuaXQtdGVzdHOCCQDHyErgUOZvuTAMBgNVHRMEBTAD 13 | AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBRv+M/6+FiVu7KXNjFI5pSN17OcW5QUtPr 14 | odJMlWrJBtynn/TA1oJlYu3yV5clc/71Vr/AxuX5xGP+IXL32YDF9lTUJXG/uUGk 15 | +JETpKmQviPbRsvzYhz4pf6ZIOZMc3/GIcNq92ECbseGO+yAgyWUVKMmZM0HqXC9 16 | ovNslqe0M8C1sLm1zAR5z/h/litE7/8O2ietija3Q/qtl2TOXJdCA6sgjJX2WUql 17 | ybrC55ct18NKf3qhpcEkGQvFU40rVYApJpi98DiZPYFdx1oBDp/f4uZ3ojpxRVFT 18 | cDwcJLfNRCPUhormsY7fDS9xSyThiHsW9mjJYdcaKQkwYZ0F11yB 19 | -----END CERTIFICATE----- 20 | -----BEGIN CERTIFICATE----- 21 | MIIFtTCCA52gAwIBAgIJAPBsLZmNGfKtMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV 22 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX 23 | aWRnaXRzIFB0eSBMdGQwHhcNMTYwOTIxMDI0NTEyWhcNMTYxMDIxMDI0NTEyWjBF 24 | MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 25 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 26 | CgKCAgEAsiMC7mTsmUXwZoYlT4aHY1FLw8bxIXC+z3IqA+TY1WqfbeiZRo8MA5Zx 27 | lTTxYMKPCZUE1XBc7jvD8GJhWIj6pToPYHn73B01IBkLBxq4kF1yV2Z7DVmkvc6H 28 | EcxXXq8zkCx0j6XOfiI4+qkXnuQn8cvrk8xfhtnMMZM7iVm6VSN93iRP/8ey6xuL 29 | XTHrDX7ukoRce1hpT8O+15GXNrY0irhhYQz5xKibNCJF3EjV28WMry8y7I8uYUFU 30 | RWDiQawwK9ec1zhZ94v92+GZDlPevmcFmSERKYQ0NsKcT0Y3lGuGnaExs8GyOpnC 31 | oksu4YJGXQjg7lkv4MxzsNbRqmCkUwxw1Mg6FP0tsCNsw9qTrkvWCRA9zp/aU+sZ 32 | IBGh1t4UGCub8joeQFvHxvr/3F7mH/dyvCjA34u0Lo1VPx+jYUIi9i0odltMspDW 33 | xOpjqdGARZYmlJP5Au9q5cQjPMcwS/EBIb8cwNl32mUE6WnFlep+38mNR/FghIjO 34 | ViAkXuKQmcHe6xppZAoHFsO/t3l4Tjek5vNW7erI1rgrFku/fvkIW/G8V1yIm/+Q 35 | F+CE4maQzCJfhftpkhM/sPC/FuLNBmNE8BHVX8y58xG4is/cQxL4Z9TsFIw0C5+3 36 | uTrFW9D0agysahMVzPGtCqhDQqJdIJrBQqlS6bztpzBA8zEI0skCAwEAAaOBpzCB 37 | pDAdBgNVHQ4EFgQUz/8FmW6TfqXyNJZr7rhc+Tn5sKQwdQYDVR0jBG4wbIAUz/8F 38 | mW6TfqXyNJZr7rhc+Tn5sKShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT 39 | b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDw 40 | bC2ZjRnyrTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCQmrcfhurX 41 | riR3Q0Y+nq040/3dJIAJXjyI9CEtxaU0nzCNTng7PwgZ0CKmCelQfInuwWFwBSHS 42 | 6kBfC1rgJeFnjnTt8a3RCgRlIgUr9NCdPSEccB7TurobwPJ2h6cJjjR8urcb0CXh 43 | CEMvPneyPj0xUFY8vVKXMGWahz/kyfwIiVqcX/OtMZ29fUu1onbWl71g2gVLtUZl 44 | sECdZ+AC/6HDCVpYIVETMl1T7N/XyqXZQiDLDNRDeZhnapz8w9fsW1KVujAZLNQR 45 | pVnw2qa2UK1dSf2FHX+lQU5mFSYM4vtwaMlX/LgfdLZ9I796hFh619WwTVz+LO2N 46 | vHnwBMabld3XSPuZRqlbBulDQ07Vbqdjv8DYSLA2aKI4ZkMMKuFLG/oS28V2ZYmv 47 | /KpGEs5UgKY+P9NulYpTDwCU/6SomuQpP795wbG6sm7Hzq82r2RmB61GupNRGeqi 48 | pXKsy69T388zBxYu6zQrosXiDl5YzaViH7tm0J7opye8dCWjjpnahki0vq2znti7 49 | 6cWla2j8Xz1glvLz+JI/NCOMfxUInb82T7ijo80N0VJ2hzf7p2GxRZXAxAV9knLI 50 | nM4F5TLjSd7ZhOOZ7ni/eZFueTMisWfypt2nc41whGjHMX/Zp1kPfhB4H2bLKIX/ 51 | lSrwNr3qbGTEJX8JqpDBNVAd96XkMvDNyA== 52 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /tests/data/trust_chain_without_leaf.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFtTCCA52gAwIBAgIJAPBsLZmNGfKtMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMTYwOTIxMDI0NTEyWhcNMTYxMDIxMDI0NTEyWjBF 5 | MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 7 | CgKCAgEAsiMC7mTsmUXwZoYlT4aHY1FLw8bxIXC+z3IqA+TY1WqfbeiZRo8MA5Zx 8 | lTTxYMKPCZUE1XBc7jvD8GJhWIj6pToPYHn73B01IBkLBxq4kF1yV2Z7DVmkvc6H 9 | EcxXXq8zkCx0j6XOfiI4+qkXnuQn8cvrk8xfhtnMMZM7iVm6VSN93iRP/8ey6xuL 10 | XTHrDX7ukoRce1hpT8O+15GXNrY0irhhYQz5xKibNCJF3EjV28WMry8y7I8uYUFU 11 | RWDiQawwK9ec1zhZ94v92+GZDlPevmcFmSERKYQ0NsKcT0Y3lGuGnaExs8GyOpnC 12 | oksu4YJGXQjg7lkv4MxzsNbRqmCkUwxw1Mg6FP0tsCNsw9qTrkvWCRA9zp/aU+sZ 13 | IBGh1t4UGCub8joeQFvHxvr/3F7mH/dyvCjA34u0Lo1VPx+jYUIi9i0odltMspDW 14 | xOpjqdGARZYmlJP5Au9q5cQjPMcwS/EBIb8cwNl32mUE6WnFlep+38mNR/FghIjO 15 | ViAkXuKQmcHe6xppZAoHFsO/t3l4Tjek5vNW7erI1rgrFku/fvkIW/G8V1yIm/+Q 16 | F+CE4maQzCJfhftpkhM/sPC/FuLNBmNE8BHVX8y58xG4is/cQxL4Z9TsFIw0C5+3 17 | uTrFW9D0agysahMVzPGtCqhDQqJdIJrBQqlS6bztpzBA8zEI0skCAwEAAaOBpzCB 18 | pDAdBgNVHQ4EFgQUz/8FmW6TfqXyNJZr7rhc+Tn5sKQwdQYDVR0jBG4wbIAUz/8F 19 | mW6TfqXyNJZr7rhc+Tn5sKShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT 20 | b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDw 21 | bC2ZjRnyrTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCQmrcfhurX 22 | riR3Q0Y+nq040/3dJIAJXjyI9CEtxaU0nzCNTng7PwgZ0CKmCelQfInuwWFwBSHS 23 | 6kBfC1rgJeFnjnTt8a3RCgRlIgUr9NCdPSEccB7TurobwPJ2h6cJjjR8urcb0CXh 24 | CEMvPneyPj0xUFY8vVKXMGWahz/kyfwIiVqcX/OtMZ29fUu1onbWl71g2gVLtUZl 25 | sECdZ+AC/6HDCVpYIVETMl1T7N/XyqXZQiDLDNRDeZhnapz8w9fsW1KVujAZLNQR 26 | pVnw2qa2UK1dSf2FHX+lQU5mFSYM4vtwaMlX/LgfdLZ9I796hFh619WwTVz+LO2N 27 | vHnwBMabld3XSPuZRqlbBulDQ07Vbqdjv8DYSLA2aKI4ZkMMKuFLG/oS28V2ZYmv 28 | /KpGEs5UgKY+P9NulYpTDwCU/6SomuQpP795wbG6sm7Hzq82r2RmB61GupNRGeqi 29 | pXKsy69T388zBxYu6zQrosXiDl5YzaViH7tm0J7opye8dCWjjpnahki0vq2znti7 30 | 6cWla2j8Xz1glvLz+JI/NCOMfxUInb82T7ijo80N0VJ2hzf7p2GxRZXAxAV9knLI 31 | nM4F5TLjSd7ZhOOZ7ni/eZFueTMisWfypt2nc41whGjHMX/Zp1kPfhB4H2bLKIX/ 32 | lSrwNr3qbGTEJX8JqpDBNVAd96XkMvDNyA== 33 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /tests/data/trust_chain_wrong_order.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFtTCCA52gAwIBAgIJAPBsLZmNGfKtMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMTYwOTIxMDI0NTEyWhcNMTYxMDIxMDI0NTEyWjBF 5 | MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC 7 | CgKCAgEAsiMC7mTsmUXwZoYlT4aHY1FLw8bxIXC+z3IqA+TY1WqfbeiZRo8MA5Zx 8 | lTTxYMKPCZUE1XBc7jvD8GJhWIj6pToPYHn73B01IBkLBxq4kF1yV2Z7DVmkvc6H 9 | EcxXXq8zkCx0j6XOfiI4+qkXnuQn8cvrk8xfhtnMMZM7iVm6VSN93iRP/8ey6xuL 10 | XTHrDX7ukoRce1hpT8O+15GXNrY0irhhYQz5xKibNCJF3EjV28WMry8y7I8uYUFU 11 | RWDiQawwK9ec1zhZ94v92+GZDlPevmcFmSERKYQ0NsKcT0Y3lGuGnaExs8GyOpnC 12 | oksu4YJGXQjg7lkv4MxzsNbRqmCkUwxw1Mg6FP0tsCNsw9qTrkvWCRA9zp/aU+sZ 13 | IBGh1t4UGCub8joeQFvHxvr/3F7mH/dyvCjA34u0Lo1VPx+jYUIi9i0odltMspDW 14 | xOpjqdGARZYmlJP5Au9q5cQjPMcwS/EBIb8cwNl32mUE6WnFlep+38mNR/FghIjO 15 | ViAkXuKQmcHe6xppZAoHFsO/t3l4Tjek5vNW7erI1rgrFku/fvkIW/G8V1yIm/+Q 16 | F+CE4maQzCJfhftpkhM/sPC/FuLNBmNE8BHVX8y58xG4is/cQxL4Z9TsFIw0C5+3 17 | uTrFW9D0agysahMVzPGtCqhDQqJdIJrBQqlS6bztpzBA8zEI0skCAwEAAaOBpzCB 18 | pDAdBgNVHQ4EFgQUz/8FmW6TfqXyNJZr7rhc+Tn5sKQwdQYDVR0jBG4wbIAUz/8F 19 | mW6TfqXyNJZr7rhc+Tn5sKShSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT 20 | b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDw 21 | bC2ZjRnyrTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCQmrcfhurX 22 | riR3Q0Y+nq040/3dJIAJXjyI9CEtxaU0nzCNTng7PwgZ0CKmCelQfInuwWFwBSHS 23 | 6kBfC1rgJeFnjnTt8a3RCgRlIgUr9NCdPSEccB7TurobwPJ2h6cJjjR8urcb0CXh 24 | CEMvPneyPj0xUFY8vVKXMGWahz/kyfwIiVqcX/OtMZ29fUu1onbWl71g2gVLtUZl 25 | sECdZ+AC/6HDCVpYIVETMl1T7N/XyqXZQiDLDNRDeZhnapz8w9fsW1KVujAZLNQR 26 | pVnw2qa2UK1dSf2FHX+lQU5mFSYM4vtwaMlX/LgfdLZ9I796hFh619WwTVz+LO2N 27 | vHnwBMabld3XSPuZRqlbBulDQ07Vbqdjv8DYSLA2aKI4ZkMMKuFLG/oS28V2ZYmv 28 | /KpGEs5UgKY+P9NulYpTDwCU/6SomuQpP795wbG6sm7Hzq82r2RmB61GupNRGeqi 29 | pXKsy69T388zBxYu6zQrosXiDl5YzaViH7tm0J7opye8dCWjjpnahki0vq2znti7 30 | 6cWla2j8Xz1glvLz+JI/NCOMfxUInb82T7ijo80N0VJ2hzf7p2GxRZXAxAV9knLI 31 | nM4F5TLjSd7ZhOOZ7ni/eZFueTMisWfypt2nc41whGjHMX/Zp1kPfhB4H2bLKIX/ 32 | lSrwNr3qbGTEJX8JqpDBNVAd96XkMvDNyA== 33 | -----END CERTIFICATE----- 34 | -----BEGIN CERTIFICATE----- 35 | MIIDIzCCAgugAwIBAgIJAMfISuBQ5m+5MA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV 36 | BAMTCnVuaXQtdGVzdHMwHhcNMTExMjA2MTYyNjAyWhcNMjExMjAzMTYyNjAyWjAV 37 | MRMwEQYDVQQDEwp1bml0LXRlc3RzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 38 | CgKCAQEA4ej0p7bQ7L/r4rVGUz9RN4VQWoej1Bg1mYWIDYslvKrk1gpj7wZgkdmM 39 | 7oVK2OfgrSj/FCTkInKPqaCR0gD7K80q+mLBrN3PUkDrJQZpvRZIff3/xmVU1Wer 40 | uQLFJjnFb2dqu0s/FY/2kWiJtBCakXvXEOb7zfbINuayL+MSsCGSdVYsSliS5qQp 41 | gyDap+8b5fpXZVJkq92hrcNtbkg7hCYUJczt8n9hcCTJCfUpApvaFQ18pe+zpyl4 42 | +WzkP66I28hniMQyUlA1hBiskT7qiouq0m8IOodhv2fagSZKjOTTU2xkSBc//fy3 43 | ZpsL7WqgsZS7Q+0VRK8gKfqkxg5OYQIDAQABo3YwdDAdBgNVHQ4EFgQU2RQ8yO+O 44 | gN8oVW2SW7RLrfYd9jEwRQYDVR0jBD4wPIAU2RQ8yO+OgN8oVW2SW7RLrfYd9jGh 45 | GaQXMBUxEzARBgNVBAMTCnVuaXQtdGVzdHOCCQDHyErgUOZvuTAMBgNVHRMEBTAD 46 | AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBRv+M/6+FiVu7KXNjFI5pSN17OcW5QUtPr 47 | odJMlWrJBtynn/TA1oJlYu3yV5clc/71Vr/AxuX5xGP+IXL32YDF9lTUJXG/uUGk 48 | +JETpKmQviPbRsvzYhz4pf6ZIOZMc3/GIcNq92ECbseGO+yAgyWUVKMmZM0HqXC9 49 | ovNslqe0M8C1sLm1zAR5z/h/litE7/8O2ietija3Q/qtl2TOXJdCA6sgjJX2WUql 50 | ybrC55ct18NKf3qhpcEkGQvFU40rVYApJpi98DiZPYFdx1oBDp/f4uZ3ojpxRVFT 51 | cDwcJLfNRCPUhormsY7fDS9xSyThiHsW9mjJYdcaKQkwYZ0F11yB 52 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /tests/oauth2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests/oauth2/__init__.py -------------------------------------------------------------------------------- /tests/oauth2/test_webauthn_handler_factory.py: -------------------------------------------------------------------------------- 1 | import mock 2 | import pytest # type: ignore 3 | 4 | from google.oauth2 import webauthn_handler 5 | from google.oauth2 import webauthn_handler_factory 6 | 7 | 8 | @pytest.fixture 9 | def os_get_stub(): 10 | with mock.patch.object( 11 | webauthn_handler.os.environ, 12 | "get", 13 | return_value="gcloud_webauthn_plugin", 14 | name="fake os.environ.get", 15 | ) as mock_os_environ_get: 16 | yield mock_os_environ_get 17 | 18 | 19 | # Check that get_handler returns a value when env is set, 20 | # that type is PluginHandler, and that no value is returned 21 | # if env not set. 22 | def test_WebauthHandlerFactory_get(os_get_stub): 23 | factory = webauthn_handler_factory.WebauthnHandlerFactory() 24 | assert factory.get_handler() is not None 25 | 26 | assert isinstance(factory.get_handler(), webauthn_handler.PluginHandler) 27 | 28 | os_get_stub.return_value = None 29 | assert factory.get_handler() is None 30 | -------------------------------------------------------------------------------- /tests/test__service_account_info.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import json 16 | import os 17 | 18 | import pytest # type: ignore 19 | 20 | from google.auth import _service_account_info 21 | from google.auth import crypt 22 | 23 | 24 | DATA_DIR = os.path.join(os.path.dirname(__file__), "data") 25 | SERVICE_ACCOUNT_JSON_FILE = os.path.join(DATA_DIR, "service_account.json") 26 | GDCH_SERVICE_ACCOUNT_JSON_FILE = os.path.join(DATA_DIR, "gdch_service_account.json") 27 | 28 | with open(SERVICE_ACCOUNT_JSON_FILE, "r") as fh: 29 | SERVICE_ACCOUNT_INFO = json.load(fh) 30 | 31 | with open(GDCH_SERVICE_ACCOUNT_JSON_FILE, "r") as fh: 32 | GDCH_SERVICE_ACCOUNT_INFO = json.load(fh) 33 | 34 | 35 | def test_from_dict(): 36 | signer = _service_account_info.from_dict(SERVICE_ACCOUNT_INFO) 37 | assert isinstance(signer, crypt.RSASigner) 38 | assert signer.key_id == SERVICE_ACCOUNT_INFO["private_key_id"] 39 | 40 | 41 | def test_from_dict_es256_signer(): 42 | signer = _service_account_info.from_dict( 43 | GDCH_SERVICE_ACCOUNT_INFO, use_rsa_signer=False 44 | ) 45 | assert isinstance(signer, crypt.ES256Signer) 46 | assert signer.key_id == GDCH_SERVICE_ACCOUNT_INFO["private_key_id"] 47 | 48 | 49 | def test_from_dict_bad_private_key(): 50 | info = SERVICE_ACCOUNT_INFO.copy() 51 | info["private_key"] = "garbage" 52 | 53 | with pytest.raises(ValueError) as excinfo: 54 | _service_account_info.from_dict(info) 55 | 56 | assert excinfo.match(r"(?i)(key|PEM)") 57 | 58 | 59 | def test_from_dict_bad_format(): 60 | with pytest.raises(ValueError) as excinfo: 61 | _service_account_info.from_dict({}, require=("meep",)) 62 | 63 | assert excinfo.match(r"missing fields") 64 | 65 | 66 | def test_from_filename(): 67 | info, signer = _service_account_info.from_filename(SERVICE_ACCOUNT_JSON_FILE) 68 | 69 | for key, value in SERVICE_ACCOUNT_INFO.items(): 70 | assert info[key] == value 71 | 72 | assert isinstance(signer, crypt.RSASigner) 73 | assert signer.key_id == SERVICE_ACCOUNT_INFO["private_key_id"] 74 | 75 | 76 | def test_from_filename_es256_signer(): 77 | _, signer = _service_account_info.from_filename( 78 | GDCH_SERVICE_ACCOUNT_JSON_FILE, use_rsa_signer=False 79 | ) 80 | 81 | assert isinstance(signer, crypt.ES256Signer) 82 | assert signer.key_id == GDCH_SERVICE_ACCOUNT_INFO["private_key_id"] 83 | -------------------------------------------------------------------------------- /tests/test_api_key.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import pytest # type: ignore 16 | 17 | from google.auth import api_key 18 | 19 | 20 | def test_credentials_constructor(): 21 | with pytest.raises(ValueError) as excinfo: 22 | api_key.Credentials("") 23 | 24 | assert excinfo.match(r"Token must be a non-empty API key string") 25 | 26 | 27 | def test_expired_and_valid(): 28 | credentials = api_key.Credentials("api-key") 29 | 30 | assert credentials.valid 31 | assert credentials.token == "api-key" 32 | assert not credentials.expired 33 | 34 | credentials.refresh(None) 35 | assert credentials.valid 36 | assert credentials.token == "api-key" 37 | assert not credentials.expired 38 | 39 | 40 | def test_before_request(): 41 | credentials = api_key.Credentials("api-key") 42 | headers = {} 43 | 44 | credentials.before_request(None, "http://example.com", "GET", headers) 45 | assert headers["x-goog-api-key"] == "api-key" 46 | -------------------------------------------------------------------------------- /tests/test_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import pytest # type: ignore 16 | 17 | from google.auth import exceptions # type:ignore 18 | 19 | 20 | @pytest.fixture( 21 | params=[ 22 | exceptions.GoogleAuthError, 23 | exceptions.TransportError, 24 | exceptions.RefreshError, 25 | exceptions.UserAccessTokenError, 26 | exceptions.DefaultCredentialsError, 27 | exceptions.MutualTLSChannelError, 28 | exceptions.OAuthError, 29 | exceptions.ReauthFailError, 30 | exceptions.ReauthSamlChallengeFailError, 31 | ] 32 | ) 33 | def retryable_exception(request): 34 | return request.param 35 | 36 | 37 | @pytest.fixture(params=[exceptions.ClientCertError]) 38 | def non_retryable_exception(request): 39 | return request.param 40 | 41 | 42 | def test_default_retryable_exceptions(retryable_exception): 43 | assert not retryable_exception().retryable 44 | 45 | 46 | @pytest.mark.parametrize("retryable", [True, False]) 47 | def test_retryable_exceptions(retryable_exception, retryable): 48 | retryable_exception = retryable_exception(retryable=retryable) 49 | assert retryable_exception.retryable == retryable 50 | 51 | 52 | @pytest.mark.parametrize("retryable", [True, False]) 53 | def test_non_retryable_exceptions(non_retryable_exception, retryable): 54 | non_retryable_exception = non_retryable_exception(retryable=retryable) 55 | assert not non_retryable_exception.retryable 56 | -------------------------------------------------------------------------------- /tests/test_metrics.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 Google Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import platform 16 | 17 | import mock 18 | 19 | from google.auth import metrics 20 | from google.auth import version 21 | 22 | 23 | def test_add_metric_header(): 24 | headers = {} 25 | metrics.add_metric_header(headers, None) 26 | assert headers == {} 27 | 28 | headers = {"x-goog-api-client": "foo"} 29 | metrics.add_metric_header(headers, "bar") 30 | assert headers == {"x-goog-api-client": "foo bar"} 31 | 32 | headers = {} 33 | metrics.add_metric_header(headers, "bar") 34 | assert headers == {"x-goog-api-client": "bar"} 35 | 36 | 37 | @mock.patch.object(platform, "python_version", return_value="3.7") 38 | def test_versions(mock_python_version): 39 | version_save = version.__version__ 40 | version.__version__ = "1.1" 41 | assert metrics.python_and_auth_lib_version() == "gl-python/3.7 auth/1.1" 42 | version.__version__ = version_save 43 | 44 | 45 | @mock.patch( 46 | "google.auth.metrics.python_and_auth_lib_version", 47 | return_value="gl-python/3.7 auth/1.1", 48 | ) 49 | def test_metric_values(mock_python_and_auth_lib_version): 50 | assert ( 51 | metrics.token_request_access_token_mds() 52 | == "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/mds" 53 | ) 54 | assert ( 55 | metrics.token_request_id_token_mds() 56 | == "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/mds" 57 | ) 58 | assert ( 59 | metrics.token_request_access_token_impersonate() 60 | == "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/imp" 61 | ) 62 | assert ( 63 | metrics.token_request_id_token_impersonate() 64 | == "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/imp" 65 | ) 66 | assert ( 67 | metrics.token_request_access_token_sa_assertion() 68 | == "gl-python/3.7 auth/1.1 auth-request-type/at cred-type/sa" 69 | ) 70 | assert ( 71 | metrics.token_request_id_token_sa_assertion() 72 | == "gl-python/3.7 auth/1.1 auth-request-type/it cred-type/sa" 73 | ) 74 | assert metrics.token_request_user() == "gl-python/3.7 auth/1.1 cred-type/u" 75 | assert metrics.mds_ping() == "gl-python/3.7 auth/1.1 auth-request-type/mds" 76 | assert metrics.reauth_start() == "gl-python/3.7 auth/1.1 auth-request-type/re-start" 77 | assert ( 78 | metrics.reauth_continue() == "gl-python/3.7 auth/1.1 auth-request-type/re-cont" 79 | ) 80 | 81 | 82 | @mock.patch( 83 | "google.auth.metrics.python_and_auth_lib_version", 84 | return_value="gl-python/3.7 auth/1.1", 85 | ) 86 | def test_byoid_metric_header(mock_python_and_auth_lib_version): 87 | metrics_options = {} 88 | assert ( 89 | metrics.byoid_metrics_header(metrics_options) 90 | == "gl-python/3.7 auth/1.1 google-byoid-sdk" 91 | ) 92 | metrics_options["testKey"] = "testValue" 93 | assert ( 94 | metrics.byoid_metrics_header(metrics_options) 95 | == "gl-python/3.7 auth/1.1 google-byoid-sdk testKey/testValue" 96 | ) 97 | -------------------------------------------------------------------------------- /tests/test_packaging.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import subprocess 17 | import sys 18 | 19 | 20 | def test_namespace_package_compat(tmp_path): 21 | """ 22 | The ``google`` namespace package should not be masked 23 | by the presence of ``google-auth``. 24 | """ 25 | google = tmp_path / "google" 26 | google.mkdir() 27 | google.joinpath("othermod.py").write_text("") 28 | env = dict(os.environ, PYTHONPATH=str(tmp_path)) 29 | cmd = [sys.executable, "-m", "google.othermod"] 30 | subprocess.check_call(cmd, env=env) 31 | -------------------------------------------------------------------------------- /tests/transport/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests/transport/__init__.py -------------------------------------------------------------------------------- /tests/transport/test__http_client.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import pytest # type: ignore 16 | 17 | from google.auth import exceptions 18 | import google.auth.transport._http_client 19 | from tests.transport import compliance 20 | 21 | 22 | class TestRequestResponse(compliance.RequestResponseTests): 23 | def make_request(self): 24 | return google.auth.transport._http_client.Request() 25 | 26 | def test_non_http(self): 27 | request = self.make_request() 28 | with pytest.raises(exceptions.TransportError) as excinfo: 29 | request(url="https://{}".format(compliance.NXDOMAIN), method="GET") 30 | 31 | assert excinfo.match("https") 32 | -------------------------------------------------------------------------------- /tests_async/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests_async/__init__.py -------------------------------------------------------------------------------- /tests_async/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | 18 | import mock 19 | import pytest # type: ignore 20 | 21 | 22 | def pytest_configure(): 23 | """Load public certificate and private key.""" 24 | pytest.data_dir = os.path.join( 25 | os.path.abspath(os.path.join(__file__, "../..")), "tests/data" 26 | ) 27 | 28 | with open(os.path.join(pytest.data_dir, "privatekey.pem"), "rb") as fh: 29 | pytest.private_key_bytes = fh.read() 30 | 31 | with open(os.path.join(pytest.data_dir, "public_cert.pem"), "rb") as fh: 32 | pytest.public_cert_bytes = fh.read() 33 | 34 | 35 | @pytest.fixture 36 | def mock_non_existent_module(monkeypatch): 37 | """Mocks a non-existing module in sys.modules. 38 | 39 | Additionally mocks any non-existing modules specified in the dotted path. 40 | """ 41 | 42 | def _mock_non_existent_module(path): 43 | parts = path.split(".") 44 | partial = [] 45 | for part in parts: 46 | partial.append(part) 47 | current_module = ".".join(partial) 48 | if current_module not in sys.modules: 49 | monkeypatch.setitem(sys.modules, current_module, mock.MagicMock()) 50 | 51 | return _mock_non_existent_module 52 | -------------------------------------------------------------------------------- /tests_async/transport/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/google-auth-library-python/ca94ead4035beea4741dc5384449032f8e6f75d8/tests_async/transport/__init__.py --------------------------------------------------------------------------------