diff --git a/cookiecutter/tap-template/{{cookiecutter.tap_id}}/pyproject.toml b/cookiecutter/tap-template/{{cookiecutter.tap_id}}/pyproject.toml index b1902b7243..525d2fc31a 100644 --- a/cookiecutter/tap-template/{{cookiecutter.tap_id}}/pyproject.toml +++ b/cookiecutter/tap-template/{{cookiecutter.tap_id}}/pyproject.toml @@ -31,7 +31,11 @@ packages = [ [tool.poetry.dependencies] python = ">=3.8" importlib-resources = { version = "==6.1.*", python = "<3.9" } +{%- if cookiecutter.auth_method == "JWT" %} +singer-sdk = { version="~=0.34.1", extras = ["crypto"] } +{%- else %} singer-sdk = { version="~=0.34.1" } +{%- endif %} fs-s3fs = { version = "~=1.1.1", optional = true } {%- if cookiecutter.stream_type in ["REST", "GraphQL"] %} requests = "~=2.31.0" diff --git a/docs/dev_guide.md b/docs/dev_guide.md index 888ff03faf..4e71b57c02 100644 --- a/docs/dev_guide.md +++ b/docs/dev_guide.md @@ -17,7 +17,7 @@ Create taps with the SDK requires overriding just two or three classes: `http_headers` property in the stream class. - `OAuthAuthenticator` - This class performs an OAuth 2.0 authentication flow. - `OAuthJWTAuthenticator` - This class performs an JWT (JSON Web Token) authentication - flow. + flow. Requires installing the `singer-sdk[crypto]` extra. ## Target Development Overview @@ -181,6 +181,7 @@ Some APIs instead return the records as values inside an object where each key i The following [extra features](https://packaging.python.org/en/latest/specifications/dependency-specifiers/#extras) are available for the Singer SDK: +- `crypto` - Enables the `OAuthJWTAuthenticator` class for JWT (JSON Web Token) authentication. - `s3` - Enables AWS S3 as a [BATCH storage](batch.md#the-batch-message). - `parquet` - Enables as [BATCH encoding](batch.md#encoding). - `testing` - Pytest dependencies required to use the [Tap & Target Testing Frameworks](testing.md). diff --git a/poetry.lock b/poetry.lock index 05d89d6600..f478ac7a30 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2602,6 +2602,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [extras] +crypto = ["cryptography"] docs = ["furo", "myst-parser", "sphinx", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinx-reredirects"] parquet = ["numpy", "numpy", "pyarrow"] s3 = ["fs-s3fs"] @@ -2610,4 +2611,4 @@ testing = ["pytest", "pytest-durations"] [metadata] lock-version = "2.0" python-versions = ">=3.8" -content-hash = "d4e6a793a168c7440918376ba46cf015de7cd633d0f957dfc244db89f81b85d8" +content-hash = "51c3f02adca23fb59a55da88415f96e80797ff2a3750c526eb31e3f14ab67cd5" diff --git a/pyproject.toml b/pyproject.toml index b1dde771a4..92b52213fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,6 +91,9 @@ pytest = {version=">=7.2.1", optional = true} pytest-durations = {version = ">=1.2.0", optional = true} [tool.poetry.extras] +crypto = [ + "cryptography", +] docs = [ "sphinx", "furo", diff --git a/singer_sdk/authenticators.py b/singer_sdk/authenticators.py index 82e0556bc3..3098539a1a 100644 --- a/singer_sdk/authenticators.py +++ b/singer_sdk/authenticators.py @@ -11,8 +11,6 @@ import jwt import requests -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import serialization from singer_sdk.helpers._util import utc_now @@ -564,6 +562,9 @@ def oauth_request_payload(self) -> dict: Raises: ValueError: If the private key is not set. """ + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import serialization + if not self.private_key: msg = "Missing 'private_key' property for OAuth payload." raise ValueError(msg)